diff --git a/WATCHLISTS b/WATCHLISTS
index de8b300..6002a8c 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -596,25 +596,25 @@
                   'chrome/common/search_types.*',
     },
     'ios': {
-      'filepath': 'ios',
+      'filepath': 'ios/',
     },
     'ios_chrome': {
-      'filepath': 'ios/chrome',
+      'filepath': 'ios/chrome/',
     },
     'ios_clean': {
-      'filepath': 'ios/clean',
+      'filepath': 'ios/clean/',
     },
     'ios_showcase': {
-      'filepath': 'ios/showcase',
+      'filepath': 'ios/showcase/',
     },
     'ios_test': {
-      'filepath': 'ios/chrome/test|'\
-                  'ios/testing|'\
-                  'ios/web/public/test|'\
-                  'ios/web/test',
+      'filepath': 'ios/chrome/test/|'\
+                  'ios/testing/|'\
+                  'ios/web/public/test/|'\
+                  'ios/web/test/',
     },
     'ios_web': {
-      'filepath': 'ios/web',
+      'filepath': 'ios/web(_view)?/',
     },
     'ipc': {
       'filepath': 'ipc/ipc',
diff --git a/chrome/android/java/res/layout/account_signin_view.xml b/chrome/android/java/res/layout/account_signin_view.xml
index 3a49a16b..09c3565 100644
--- a/chrome/android/java/res/layout/account_signin_view.xml
+++ b/chrome/android/java/res/layout/account_signin_view.xml
@@ -69,7 +69,7 @@
             android:fadingEdgeLength="48dp"
             android:visibility="gone">
 
-            <RelativeLayout
+            <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical">
@@ -87,8 +87,8 @@
 
                     <ImageView
                         android:id="@+id/signin_account_image"
-                        android:layout_width="64dp"
-                        android:layout_height="64dp"
+                        android:layout_width="@dimen/signin_account_image_size"
+                        android:layout_height="@dimen/signin_account_image_size"
                         android:layout_marginBottom="24dp"
                         android:scaleType="fitCenter"
                         android:contentDescription="@null"/>
@@ -114,18 +114,13 @@
                         android:maxLines="1"/>
                 </LinearLayout>
 
-                <View
-                    android:id="@+id/signin_confirmation_head_body_border"
-                    style="@style/Divider"
-                    android:layout_below="@id/signin_confirmation_head"/>
+                <View style="@style/Divider"/>
 
                 <TextView
-                    android:id="@+id/signin_chrome_sync_title"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="16dp"
                     android:layout_marginBottom="8dp"
-                    android:layout_below="@id/signin_confirmation_head_body_border"
                     android:paddingStart="16dp"
                     android:paddingEnd="16dp"
                     android:text="@string/sync_confirmation_chrome_sync_title"
@@ -136,11 +131,9 @@
                     android:drawablePadding="16dp"/>
 
                 <TextView
-                    android:id="@+id/signin_chrome_sync_description"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginBottom="16dp"
-                    android:layout_below="@id/signin_chrome_sync_title"
                     android:paddingStart="56dp"
                     android:paddingEnd="16dp"
                     android:lineSpacingMultiplier="1.4"
@@ -149,19 +142,15 @@
                     android:textSize="@dimen/fre_normal_text_size" />
 
                 <View
-                    android:id="@+id/signin_confirmation_body_rule_line"
                     style="@style/Divider"
                     android:layout_marginStart="56dp"
-                    android:layout_marginEnd="16dp"
-                    android:layout_below="@id/signin_chrome_sync_description"/>
+                    android:layout_marginEnd="16dp"/>
 
                 <TextView
-                    android:id="@+id/signin_personalize_service_title"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="16dp"
                     android:layout_marginBottom="8dp"
-                    android:layout_below="@id/signin_confirmation_body_rule_line"
                     android:paddingStart="16dp"
                     android:paddingEnd="16dp"
                     android:text="@string/sync_confirmation_personalize_services_title"
@@ -176,7 +165,6 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginBottom="32dp"
-                    android:layout_below="@id/signin_personalize_service_title"
                     android:paddingStart="56dp"
                     android:paddingEnd="16dp"
                     android:lineSpacingMultiplier="1.4"
@@ -188,7 +176,6 @@
                     android:id="@+id/signin_settings_control"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_below="@id/signin_personalize_service_description"
                     android:paddingStart="16dp"
                     android:paddingEnd="16dp"
                     android:paddingBottom="36dp"
@@ -196,7 +183,7 @@
                     android:text="@string/signin_signed_in_settings_description"
                     android:textColor="@color/descriptive_text_color"
                     android:textSize="@dimen/fre_normal_text_size" />
-            </RelativeLayout>
+            </LinearLayout>
         </org.chromium.chrome.browser.signin.AccountSigninConfirmationView>
     </FrameLayout>
 
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index eaad2221..7f66f24 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -184,6 +184,7 @@
     <!-- Account Signin dimensions -->
     <!-- The Account Signin page appears in the First Run Experience (amongst other places), so uses
     a lot of the fre_* dimensions for consistency. -->
+    <dimen name="signin_account_image_size">64dp</dimen>
     <dimen name="signin_image_carousel_width">240dp</dimen>
     <dimen name="signin_chooser_padding">16dp</dimen>
     <dimen name="signin_screen_top_padding">50dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
index b7f15f3..ba5e5ac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ProfileDataCache.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileDownloader;
-import org.chromium.ui.display.DisplayAndroid;
 
 import java.util.HashMap;
 import java.util.List;
@@ -30,9 +29,6 @@
  * should be provided by calling {@link #update(List)}
  */
 public class ProfileDataCache implements ProfileDownloader.Observer {
-    private static final int PROFILE_IMAGE_SIZE_DP = 136;  // Max size of the user picture.
-    private static final int PROFILE_IMAGE_STROKE_DP = 3;
-
     private static class CacheEntry {
         public CacheEntry(Bitmap picture, String fullName, String givenName) {
             this.picture = picture;
@@ -48,9 +44,6 @@
     private final HashMap<String, CacheEntry> mCacheEntries = new HashMap<>();
 
     private final Bitmap mPlaceholderImage;
-    private final int mImageSizePx;
-    private final int mImageStrokePx;
-    private final int mImageStrokeColor;
     private final ObserverList<ProfileDownloader.Observer> mObservers = new ObserverList<>();
 
     private final Context mContext;
@@ -60,12 +53,6 @@
         mContext = context;
         mProfile = profile;
 
-        // There's no WindowAndroid present at this time, so get the default display.
-        final DisplayAndroid displayAndroid = DisplayAndroid.getNonMultiDisplay(context);
-        mImageSizePx = (int) Math.ceil(PROFILE_IMAGE_SIZE_DP * displayAndroid.getDipScale());
-        mImageStrokePx = (int) Math.ceil(PROFILE_IMAGE_STROKE_DP * displayAndroid.getDipScale());
-        mImageStrokeColor = Color.WHITE;
-
         Bitmap placeHolder = BitmapFactory.decodeResource(mContext.getResources(),
                 R.drawable.fre_placeholder);
         mPlaceholderImage = getCroppedBitmap(placeHolder);
@@ -78,10 +65,12 @@
      * Fetched data will be sent to observers of ProfileDownloader.
      */
     public void update(List<String> accounts) {
+        int imageSizePx =
+                mContext.getResources().getDimensionPixelSize(R.dimen.signin_account_image_size);
         for (int i = 0; i < accounts.size(); i++) {
             if (mCacheEntries.get(accounts.get(i)) == null) {
                 ProfileDownloader.startFetchingAccountInfoFor(
-                        mContext, mProfile, accounts.get(i), mImageSizePx, true);
+                        mContext, mProfile, accounts.get(i), imageSizePx, true);
             }
         }
     }
@@ -160,17 +149,11 @@
         canvas.drawARGB(0, 0, 0, 0);
         paint.setColor(Color.WHITE);
 
-        final float radius =  (bitmap.getWidth() - mImageStrokePx) / 2f;
-        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, radius, paint);
+        canvas.drawCircle(
+                bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, bitmap.getWidth() / 2f, paint);
         paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
         canvas.drawBitmap(bitmap, rect, rect, paint);
 
-        paint.setColor(mImageStrokeColor);
-        paint.setStyle(Paint.Style.STROKE);
-        paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
-        paint.setStrokeWidth(mImageStrokePx);
-        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, radius, paint);
-
         return output;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninConfirmationView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninConfirmationView.java
index e3f77e8..aceb06c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninConfirmationView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninConfirmationView.java
@@ -10,7 +10,6 @@
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
 import android.widget.ScrollView;
 
 import org.chromium.chrome.R;
@@ -54,8 +53,8 @@
         int height = MeasureSpec.getSize(heightMeasureSpec);
 
         View head = findViewById(R.id.signin_confirmation_head);
-        RelativeLayout.LayoutParams headLayoutParams =
-                (RelativeLayout.LayoutParams) head.getLayoutParams();
+        LinearLayout.LayoutParams headLayoutParams =
+                (LinearLayout.LayoutParams) head.getLayoutParams();
         View accountImage = findViewById(R.id.signin_account_image);
         LinearLayout.LayoutParams accountImageLayoutParams =
                 (LinearLayout.LayoutParams) accountImage.getLayoutParams();
diff --git a/chrome/browser/browsing_data/bookmark_counter_unittest.cc b/chrome/browser/browsing_data/bookmark_counter_unittest.cc
new file mode 100644
index 0000000..8aa8b17
--- /dev/null
+++ b/chrome/browser/browsing_data/bookmark_counter_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/browsing_data/core/counters/bookmark_counter.h"
+
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node.h"
+#include "components/bookmarks/test/bookmark_test_helpers.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class BookmarkCounterTest : public testing::Test {
+ public:
+  BookmarkCounterTest() {
+    run_loop_.reset(new base::RunLoop());
+    profile_.CreateBookmarkModel(true);
+    model_ =
+        BookmarkModelFactory::GetInstance()->GetForBrowserContext(profile());
+  }
+
+  Profile* profile() { return &profile_; }
+
+  bookmarks::BookmarkModel* model() { return model_; }
+
+  browsing_data::BrowsingDataCounter::ResultInt GetResult() {
+    DCHECK(finished_);
+    return result_;
+  }
+
+  void AddNodes(const std::string& model_string) {
+    bookmarks::test::AddNodesFromModelString(
+        model(), model()->bookmark_bar_node(), model_string);
+  }
+
+  void Callback(
+      std::unique_ptr<browsing_data::BrowsingDataCounter::Result> result) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK(result->Finished());
+    finished_ = result->Finished();
+    result_ = static_cast<browsing_data::BrowsingDataCounter::FinishedResult*>(
+                  result.get())
+                  ->Value();
+    run_loop_->Quit();
+  }
+
+  void WaitForResult() {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    run_loop_->Run();
+    run_loop_.reset(new base::RunLoop());
+  }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+
+  bookmarks::BookmarkModel* model_;
+  bool finished_ = false;
+  browsing_data::BrowsingDataCounter::ResultInt result_ = 0;
+};
+
+TEST_F(BookmarkCounterTest, CountUnloaded) {
+  ASSERT_FALSE(model()->loaded());
+  browsing_data::BookmarkCounter counter(model());
+  counter.InitWithoutPref(
+      base::Time(),
+      base::Bind(&BookmarkCounterTest::Callback, base::Unretained(this)));
+  counter.Restart();
+  WaitForResult();
+  EXPECT_EQ(0, GetResult());
+}
+
+TEST_F(BookmarkCounterTest, Count) {
+  bookmarks::test::WaitForBookmarkModelToLoad(model());
+  ASSERT_TRUE(model()->loaded());
+  AddNodes("1 2 3 ");
+  browsing_data::BookmarkCounter counter(model());
+  counter.InitWithoutPref(
+      base::Time(),
+      base::Bind(&BookmarkCounterTest::Callback, base::Unretained(this)));
+  counter.Restart();
+  EXPECT_EQ(3, GetResult());
+  AddNodes("5 6 ");
+  counter.Restart();
+  EXPECT_EQ(5, GetResult());
+}
+
+TEST_F(BookmarkCounterTest, CountWithPeriod) {
+  bookmarks::test::WaitForBookmarkModelToLoad(model());
+  base::Time now = base::Time::Now();
+  AddNodes("1 2 3 ");
+  GURL url("https://google.com");
+  const bookmarks::BookmarkNode* node1 = model()->AddURL(
+      model()->bookmark_bar_node(), 0, base::ASCIIToUTF16("4"), url);
+  model()->SetDateAdded(node1, now - base::TimeDelta::FromMinutes(30));
+  const bookmarks::BookmarkNode* node2 = model()->AddURL(
+      model()->bookmark_bar_node(), 0, base::ASCIIToUTF16("5"), url);
+  model()->SetDateAdded(node2, now - base::TimeDelta::FromMinutes(90));
+
+  browsing_data::BookmarkCounter counter(model());
+  counter.InitWithoutPref(
+      now - base::TimeDelta::FromMinutes(60),
+      base::Bind(&BookmarkCounterTest::Callback, base::Unretained(this)));
+  counter.Restart();
+  // 1,2,3 and 4 should be counted. 5 is too old, so it will be skipped.
+  EXPECT_EQ(4, GetResult());
+}
+
+TEST_F(BookmarkCounterTest, CountWithFolders) {
+  bookmarks::test::WaitForBookmarkModelToLoad(model());
+  AddNodes("1 2 3 f1:[ 4 5 f2:[ 6 ] ] ");
+  browsing_data::BookmarkCounter counter(model());
+  counter.InitWithoutPref(
+      base::Time(),
+      base::Bind(&BookmarkCounterTest::Callback, base::Unretained(this)));
+  counter.Restart();
+  EXPECT_EQ(6, GetResult());
+}
+
+}  // namespace
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc
index 77e12e9..86901ff 100644
--- a/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -103,8 +103,8 @@
               const CommandCallback& callback)
       : socket_(std::move(socket)),
         command_callback_(callback),
-        expected_size_(-1),
-        header_size_(0) {
+        expected_total_size_(0),
+        header_size_(std::string::npos) {
     SendRequest(request);
   }
 
@@ -113,8 +113,8 @@
               const HttpUpgradeCallback& callback)
       : socket_(std::move(socket)),
         http_upgrade_callback_(callback),
-        expected_size_(-1),
-        header_size_(0) {
+        expected_total_size_(0),
+        header_size_(std::string::npos) {
     SendRequest(request);
   }
 
@@ -166,56 +166,63 @@
   }
 
   void OnResponseData(int result) {
-    if (!CheckNetResultOrDie(result))
-      return;
-    if (result == 0) {
-      CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
-      return;
-    }
+    do {
+      if (!CheckNetResultOrDie(result))
+        return;
+      if (result == 0) {
+        CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
+        return;
+      }
 
-    response_.append(response_buffer_->data(), result);
-    if (expected_size_ < 0) {
-      int expected_length = 0;
+      response_.append(response_buffer_->data(), result);
 
-      // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
-      std::string content_length = ExtractHeader("Content-Length:");
-      if (!content_length.empty()) {
-        if (!base::StringToInt(content_length, &expected_length)) {
-          CheckNetResultOrDie(net::ERR_FAILED);
-          return;
+      if (header_size_ == std::string::npos) {
+        header_size_ = response_.find("\r\n\r\n");
+
+        if (header_size_ != std::string::npos) {
+          header_size_ += 4;
+
+          int expected_body_size = 0;
+
+          // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
+          std::string content_length = ExtractHeader("Content-Length:");
+          if (!content_length.empty()) {
+            if (!base::StringToInt(content_length, &expected_body_size)) {
+              CheckNetResultOrDie(net::ERR_FAILED);
+              return;
+            }
+          }
+
+          expected_total_size_ = header_size_ + expected_body_size;
         }
       }
 
-      header_size_ = response_.find("\r\n\r\n");
-      if (header_size_ != std::string::npos) {
-        header_size_ += 4;
-        expected_size_ = header_size_ + expected_length;
-      }
-    }
+      // WebSocket handshake doesn't contain the Content-Length header. For this
+      // case, |expected_total_size_| is set to the size of the header (opening
+      // handshake).
+      //
+      // Some (part of) WebSocket frames can be already received into
+      // |response_|.
+      if (header_size_ != std::string::npos &&
+          response_.length() >= expected_total_size_) {
+        const std::string& body = response_.substr(header_size_);
 
-    // WebSocket handshake doesn't contain the Content-Length. For this case,
-    // |expected_size_| is set to the size of the header (handshake).
-    // Some WebSocket frames can be already received into |response_|.
-    if (static_cast<int>(response_.length()) >= expected_size_) {
-      const std::string& body = response_.substr(header_size_);
-      if (!command_callback_.is_null()) {
-        command_callback_.Run(net::OK, body);
-      } else {
-        // Pass the WebSocket frames (in |body|), too.
-        http_upgrade_callback_.Run(net::OK,
-                                   ExtractHeader("Sec-WebSocket-Extensions:"),
-                                   body, std::move(socket_));
-      }
-      delete this;
-      return;
-    }
+        if (!command_callback_.is_null()) {
+          command_callback_.Run(net::OK, body);
+        } else {
+          http_upgrade_callback_.Run(net::OK,
+                                     ExtractHeader("Sec-WebSocket-Extensions:"),
+                                     body, std::move(socket_));
+        }
 
-    result = socket_->Read(
-        response_buffer_.get(),
-        kBufferSize,
-        base::Bind(&HttpRequest::OnResponseData, base::Unretained(this)));
-    if (result != net::ERR_IO_PENDING)
-      OnResponseData(result);
+        delete this;
+        return;
+      }
+
+      result = socket_->Read(
+          response_buffer_.get(), kBufferSize,
+          base::Bind(&HttpRequest::OnResponseData, base::Unretained(this)));
+    } while (result != net::ERR_IO_PENDING);
   }
 
   std::string ExtractHeader(const std::string& header) {
@@ -253,14 +260,17 @@
   HttpUpgradeCallback http_upgrade_callback_;
 
   scoped_refptr<net::IOBuffer> response_buffer_;
-  // Initially -1. Once the end of the header is seen:
-  // - If the Content-Length header is included, this variable is set to the
-  //   sum of the header size (including the last two CRLFs) and the value of
+
+  // Initially set to 0. Once the end of the header is seen:
+  // - If the Content-Length header is included, set to the sum of the header
+  //   size (including the last two CRLFs) and the value of
   //   the header.
   // - Otherwise, this variable is set to the size of the header (including the
   //   last two CRLFs).
-  int expected_size_;
-  // Set to the size of the header part in |response_|.
+  size_t expected_total_size_;
+  // Initially set to std::string::npos. Once the end of the header is seen,
+  // set to the size of the header part in |response_| including the two CRLFs
+  // at the end.
   size_t header_size_;
 };
 
diff --git a/chrome/browser/engagement/BUILD.gn b/chrome/browser/engagement/BUILD.gn
index 3bca053..2f45dd43 100644
--- a/chrome/browser/engagement/BUILD.gn
+++ b/chrome/browser/engagement/BUILD.gn
@@ -15,4 +15,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index db214edb..2d102a7 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -63,6 +63,7 @@
 #include "extensions/common/test_util.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_mint_token_flow.h"
+#include "google_apis/gaia/oauth2_token_service.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -642,7 +643,9 @@
   EXPECT_TRUE(info->id.empty());
 }
 
-class GetAuthTokenFunctionTest : public IdentityTestWithSignin {
+class GetAuthTokenFunctionTest
+    : public IdentityTestWithSignin,
+      public OAuth2TokenService::DiagnosticsObserver {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     IdentityTestWithSignin::SetUpCommandLine(command_line);
@@ -673,6 +676,16 @@
     AS_COMPONENT = 4
   };
 
+  void SetUpOnMainThread() override {
+    IdentityTestWithSignin::SetUpOnMainThread();
+    token_service_->AddDiagnosticsObserver(this);
+  }
+
+  void TearDownOnMainThread() override {
+    token_service_->RemoveDiagnosticsObserver(this);
+    IdentityTestWithSignin::TearDownOnMainThread();
+  }
+
   ~GetAuthTokenFunctionTest() override {}
 
   // Helper to create an extension with specific OAuth2Info fields set.
@@ -736,7 +749,26 @@
     id_api()->mint_queue()->RequestComplete(type, key, request);
   }
 
+  base::OnceClosure on_access_token_requested_;
+
  private:
+  // OAuth2TokenService::DiagnosticsObserver:
+  void OnAccessTokenRequested(
+      const std::string& account_id,
+      const std::string& consumer_id,
+      const OAuth2TokenService::ScopeSet& scopes) override {
+    if (on_access_token_requested_.is_null())
+      return;
+    base::ResetAndReturn(&on_access_token_requested_).Run();
+  }
+  void OnFetchAccessTokenComplete(const std::string& account_id,
+                                  const std::string& consumer_id,
+                                  const OAuth2TokenService::ScopeSet& scopes,
+                                  GoogleServiceAuthError error,
+                                  base::Time expiration_time) override {}
+  void OnTokenRemoved(const std::string& account_id,
+                      const OAuth2TokenService::ScopeSet& scopes) override {}
+
   std::string extension_id_;
   std::set<std::string> oauth_scopes_;
 };
@@ -883,8 +915,7 @@
             GetCachedToken(std::string()).status());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       InteractiveLoginCanceled) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveLoginCanceled) {
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
   func->set_login_ui_result(false);
@@ -1372,18 +1403,21 @@
   EXPECT_EQ("client1", func->GetOAuth2ClientId());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiDefaultUser) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) {
   SignIn("primary@example.com");
-  SetAccountState(CreateIds("primary@example.com", "1"), true);
-  SetAccountState(CreateIds("secondary@example.com", "2"), true);
 
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
   func->set_extension(extension.get());
-  func->set_auto_login_access_token(false);
   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
 
+  // Have GetAuthTokenFunction actually make the request for the access token.
+  func->set_auto_login_access_token(false);
+
+  base::RunLoop run_loop;
+  on_access_token_requested_ = run_loop.QuitClosure();
   RunFunctionAsync(func.get(), "[{}]");
+  run_loop.Run();
 
   IssueLoginAccessTokenForAccount("primary@example.com");
 
@@ -1396,7 +1430,63 @@
   EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiPrimaryUser) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
+  SignIn("primary@example.com");
+
+  scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+  func->set_extension(extension.get());
+  func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+
+  // Have GetAuthTokenFunction actually make the request for the access token.
+  func->set_auto_login_access_token(false);
+
+  base::RunLoop run_loop;
+  on_access_token_requested_ = run_loop.QuitClosure();
+  RunFunctionAsync(func.get(), "[{}]");
+  run_loop.Run();
+
+  token_service_->IssueErrorForAllPendingRequestsForAccount(
+      "primary@example.com",
+      GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+
+  EXPECT_EQ(
+      std::string(errors::kAuthFailure) +
+          GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)
+              .ToString(),
+      WaitForError(func.get()));
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+                       MultiDefaultUserManuallyIssueToken) {
+  SignIn("primary@example.com");
+  SetAccountState(CreateIds("primary@example.com", "1"), true);
+  SetAccountState(CreateIds("secondary@example.com", "2"), true);
+
+  scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+  func->set_extension(extension.get());
+  func->set_auto_login_access_token(false);
+  func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+
+  base::RunLoop run_loop;
+  on_access_token_requested_ = run_loop.QuitClosure();
+  RunFunctionAsync(func.get(), "[{}]");
+  run_loop.Run();
+
+  IssueLoginAccessTokenForAccount("primary@example.com");
+
+  std::unique_ptr<base::Value> value(WaitForSingleResult(func.get()));
+  std::string access_token;
+  EXPECT_TRUE(value->GetAsString(&access_token));
+  EXPECT_EQ(std::string(kAccessToken), access_token);
+  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+            GetCachedToken(std::string()).status());
+  EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
+}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+                       MultiPrimaryUserManuallyIssueToken) {
   SignIn("primary@example.com");
   IssueLoginRefreshTokenForAccount("secondary@example.com");
   SetAccountState(CreateIds("primary@example.com", "1"), true);
@@ -1408,7 +1498,10 @@
   func->set_auto_login_access_token(false);
   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
 
+  base::RunLoop run_loop;
+  on_access_token_requested_ = run_loop.QuitClosure();
   RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"1\" } }]");
+  run_loop.Run();
 
   IssueLoginAccessTokenForAccount("primary@example.com");
 
@@ -1421,7 +1514,8 @@
   EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryUser) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+                       MultiSecondaryUserManuallyIssueToken) {
   SignIn("primary@example.com");
   IssueLoginRefreshTokenForAccount("secondary@example.com");
   SetAccountState(CreateIds("primary@example.com", "1"), true);
@@ -1433,7 +1527,10 @@
   func->set_auto_login_access_token(false);
   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
 
+  base::RunLoop run_loop;
+  on_access_token_requested_ = run_loop.QuitClosure();
   RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"2\" } }]");
+  run_loop.Run();
 
   IssueLoginAccessTokenForAccount("secondary@example.com");
 
@@ -1446,7 +1543,8 @@
   EXPECT_EQ("access_token-secondary@example.com", func->login_access_token());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiUnknownUser) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+                       MultiUnknownUserGetTokenFromTokenServiceFailure) {
   SignIn("primary@example.com");
   IssueLoginRefreshTokenForAccount("secondary@example.com");
   SetAccountState(CreateIds("primary@example.com", "1"), true);
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index 4b18566..25a1db9 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -1261,6 +1261,13 @@
   return matched_forms;
 }
 
+std::vector<std::unique_ptr<autofill::PasswordForm>>
+PasswordStoreMac::FillLoginsForSameOrganizationName(
+    const std::string& signon_realm) {
+  // Not implemented.
+  return std::vector<std::unique_ptr<autofill::PasswordForm>>();
+}
+
 bool PasswordStoreMac::FillAutofillableLogins(
     std::vector<std::unique_ptr<PasswordForm>>* forms) {
   DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h
index 95bde26..3395da4 100644
--- a/chrome/browser/password_manager/password_store_mac.h
+++ b/chrome/browser/password_manager/password_store_mac.h
@@ -108,6 +108,8 @@
       base::Time delete_end) override;
   std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
       const FormDigest& form) override;
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
   bool FillAutofillableLogins(
       std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
   bool FillBlacklistLogins(
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.cc b/chrome/browser/password_manager/password_store_proxy_mac.cc
index 84e950a..fb3bf93 100644
--- a/chrome/browser/password_manager/password_store_proxy_mac.cc
+++ b/chrome/browser/password_manager/password_store_proxy_mac.cc
@@ -189,6 +189,12 @@
   return GetBackend()->FillMatchingLogins(form);
 }
 
+std::vector<std::unique_ptr<autofill::PasswordForm>>
+PasswordStoreProxyMac::FillLoginsForSameOrganizationName(
+    const std::string& signon_realm) {
+  return GetBackend()->FillLoginsForSameOrganizationName(signon_realm);
+}
+
 bool PasswordStoreProxyMac::FillAutofillableLogins(
     std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) {
   return GetBackend()->FillAutofillableLogins(forms);
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.h b/chrome/browser/password_manager/password_store_proxy_mac.h
index 2aba5bb..801f81316 100644
--- a/chrome/browser/password_manager/password_store_proxy_mac.h
+++ b/chrome/browser/password_manager/password_store_proxy_mac.h
@@ -95,6 +95,8 @@
       base::Time delete_end) override;
   std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
       const FormDigest& form) override;
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
   bool FillAutofillableLogins(
       std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
   bool FillBlacklistLogins(
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc
index 513a25f9..b802e900 100644
--- a/chrome/browser/password_manager/password_store_x.cc
+++ b/chrome/browser/password_manager/password_store_x.cc
@@ -207,6 +207,13 @@
   return std::vector<std::unique_ptr<PasswordForm>>();
 }
 
+std::vector<std::unique_ptr<PasswordForm>>
+PasswordStoreX::FillLoginsForSameOrganizationName(
+    const std::string& signon_realm) {
+  // Not available on X.
+  return std::vector<std::unique_ptr<PasswordForm>>();
+}
+
 bool PasswordStoreX::FillAutofillableLogins(
     std::vector<std::unique_ptr<PasswordForm>>* forms) {
   CheckMigration();
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h
index daf829c..3d16ecb 100644
--- a/chrome/browser/password_manager/password_store_x.h
+++ b/chrome/browser/password_manager/password_store_x.h
@@ -119,6 +119,8 @@
       const base::Callback<bool(const GURL&)>& origin_filter) override;
   std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
       const FormDigest& form) override;
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
   bool FillAutofillableLogins(
       std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
   bool FillBlacklistLogins(
diff --git a/chrome/browser/profiles/profile_statistics.cc b/chrome/browser/profiles/profile_statistics.cc
index 8cfa7e72..72808da6 100644
--- a/chrome/browser/profiles/profile_statistics.cc
+++ b/chrome/browser/profiles/profile_statistics.cc
@@ -27,19 +27,12 @@
     return;
   DCHECK(!profile_->IsOffTheRecord() && !profile_->IsSystemProfile());
 
-  if (HasAggregator()) {
-    GetAggregator()->AddCallbackAndStartAggregator(callback);
-  } else {
-    // The statistics task may outlive ProfileStatistics in unit tests, so a
-    // weak pointer is used for the callback.
-    scoped_refptr<ProfileStatisticsAggregator> aggregator =
-        new ProfileStatisticsAggregator(
-                profile_,
-                callback,
-                base::Bind(&ProfileStatistics::DeregisterAggregator,
-                           weak_ptr_factory_.GetWeakPtr()));
-    RegisterAggregator(aggregator.get());
+  if (!aggregator_) {
+    aggregator_ = new ProfileStatisticsAggregator(
+        profile_, base::Bind(&ProfileStatistics::DeregisterAggregator,
+                             weak_ptr_factory_.GetWeakPtr()));
   }
+  aggregator_->AddCallbackAndStartAggregator(callback);
 }
 
 bool ProfileStatistics::HasAggregator() const {
@@ -47,12 +40,7 @@
 }
 
 ProfileStatisticsAggregator* ProfileStatistics::GetAggregator() const {
-  return aggregator_;
-}
-
-void ProfileStatistics::RegisterAggregator(
-    ProfileStatisticsAggregator* aggregator) {
-  aggregator_ = aggregator;
+  return aggregator_.get();
 }
 
 void ProfileStatistics::DeregisterAggregator() {
diff --git a/chrome/browser/profiles/profile_statistics.h b/chrome/browser/profiles/profile_statistics.h
index 5ab1717f..7f254f10 100644
--- a/chrome/browser/profiles/profile_statistics.h
+++ b/chrome/browser/profiles/profile_statistics.h
@@ -53,11 +53,10 @@
 
   explicit ProfileStatistics(Profile* profile);
   ~ProfileStatistics() override;
-  void RegisterAggregator(ProfileStatisticsAggregator* const aggregator);
   void DeregisterAggregator();
 
   Profile* profile_;
-  ProfileStatisticsAggregator* aggregator_;
+  scoped_refptr<ProfileStatisticsAggregator> aggregator_;
   base::WeakPtrFactory<ProfileStatistics> weak_ptr_factory_;
 };
 
diff --git a/chrome/browser/profiles/profile_statistics_aggregator.cc b/chrome/browser/profiles/profile_statistics_aggregator.cc
index 26d47ecb..77f1b07b0 100644
--- a/chrome/browser/profiles/profile_statistics_aggregator.cc
+++ b/chrome/browser/profiles/profile_statistics_aggregator.cc
@@ -17,15 +17,19 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_statistics.h"
 #include "chrome/browser/profiles/profile_statistics_factory.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/bookmark_node.h"
+#include "components/browsing_data/core/counters/bookmark_counter.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 
+using browsing_data::BrowsingDataCounter;
+
 namespace {
 
+// Number of statistic categories calculated by StartAggregator.
+const int kProfileStatisticCategories = 4;
+
 // Callback for each pref. Every one that should be counted as a changed
 // user pref will cause *count to be incremented.
 void AccumulatePrefStats(const PrefService* pref_service,
@@ -39,27 +43,8 @@
     ++(*count);
 }
 
-int CountBookmarksFromNode(const bookmarks::BookmarkNode* node) {
-  int count = 0;
-  if (node->is_url()) {
-    ++count;
-  } else {
-    for (int i = 0; i < node->child_count(); ++i)
-      count += CountBookmarksFromNode(node->GetChild(i));
-  }
-  return count;
-}
-
 }  // namespace
 
-void ProfileStatisticsAggregator::BookmarkModelHelper::BookmarkModelLoaded(
-    bookmarks::BookmarkModel* model, bool ids_reassigned) {
-  // Remove observer before release, otherwise it may become a dangling
-  // reference.
-  model->RemoveObserver(this);
-  parent_->CountBookmarks(model);
-  parent_->Release();
-}
 
 void ProfileStatisticsAggregator::PasswordStoreConsumerHelper::
     OnGetPasswordStoreResults(
@@ -69,19 +54,14 @@
 }
 
 ProfileStatisticsAggregator::ProfileStatisticsAggregator(
-    Profile* profile, const profiles::ProfileStatisticsCallback& stats_callback,
-    const base::Closure& destruct_callback)
+    Profile* profile,
+    const base::Closure& done_callback)
     : profile_(profile),
       profile_path_(profile_->GetPath()),
-      destruct_callback_(destruct_callback),
-      password_store_consumer_helper_(this) {
-  AddCallbackAndStartAggregator(stats_callback);
-}
+      done_callback_(done_callback),
+      password_store_consumer_helper_(this) {}
 
-ProfileStatisticsAggregator::~ProfileStatisticsAggregator() {
-  if (!destruct_callback_.is_null())
-    destruct_callback_.Run();
-}
+ProfileStatisticsAggregator::~ProfileStatisticsAggregator() {}
 
 size_t ProfileStatisticsAggregator::GetCallbackCount() {
   return stats_callbacks_.size();
@@ -89,25 +69,39 @@
 
 void ProfileStatisticsAggregator::AddCallbackAndStartAggregator(
     const profiles::ProfileStatisticsCallback& stats_callback) {
-  if (!stats_callback.is_null())
+  if (stats_callback)
     stats_callbacks_.push_back(stats_callback);
   StartAggregator();
 }
 
+void ProfileStatisticsAggregator::AddCounter(
+    std::unique_ptr<BrowsingDataCounter> counter) {
+  counter->InitWithoutPref(
+      base::Time(), base::Bind(&ProfileStatisticsAggregator::OnCounterResult,
+                               base::Unretained(this)));
+  counter->Restart();
+  counters_.push_back(std::move(counter));
+}
+
 void ProfileStatisticsAggregator::StartAggregator() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(g_browser_process->profile_manager()->IsValidProfile(profile_));
   profile_category_stats_.clear();
 
   // Try to cancel tasks from task trackers.
   tracker_.TryCancelAll();
+  counters_.clear();
   password_store_consumer_helper_.cancelable_task_tracker()->TryCancelAll();
 
-  // Initiate bookmark counting (async).
-  tracker_.PostTask(
-      content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
-          .get(),
-      FROM_HERE,
-      base::BindOnce(&ProfileStatisticsAggregator::WaitOrCountBookmarks, this));
+  // Initiate bookmark counting.
+  bookmarks::BookmarkModel* bookmark_model =
+      BookmarkModelFactory::GetForBrowserContextIfExists(profile_);
+  if (bookmark_model) {
+    AddCounter(
+        base::MakeUnique<browsing_data::BookmarkCounter>(bookmark_model));
+  } else {
+    StatisticsCallbackFailure(profiles::kProfileStatisticsBookmarks);
+  }
 
   // Initiate history counting (async).
   history::HistoryService* history_service =
@@ -143,6 +137,22 @@
                  profiles::kProfileStatisticsSettings));
 }
 
+void ProfileStatisticsAggregator::OnCounterResult(
+    std::unique_ptr<BrowsingDataCounter::Result> result) {
+  if (!result->Finished())
+    return;
+  const std::string& pref = result->source()->GetPrefName();
+  auto* finished_result =
+      static_cast<BrowsingDataCounter::FinishedResult*>(result.get());
+  int count = finished_result->Value();
+  if (pref == browsing_data::BookmarkCounter::kPrefName) {
+    StatisticsCallbackSuccess(profiles::kProfileStatisticsBookmarks, count);
+  } else {
+    // TODO(dullweber): Add more cases when the other statistics are replaced.
+    NOTREACHED();
+  }
+}
+
 void ProfileStatisticsAggregator::StatisticsCallback(
     const char* category, ProfileStatValue result) {
   profiles::ProfileCategoryStat datum;
@@ -151,7 +161,7 @@
   datum.success = result.success;
   profile_category_stats_.push_back(datum);
   for (const auto& stats_callback : stats_callbacks_) {
-    DCHECK(!stats_callback.is_null());
+    DCHECK(stats_callback);
     stats_callback.Run(profile_category_stats_);
   }
 
@@ -159,6 +169,10 @@
     ProfileStatistics::SetProfileStatisticsToAttributesStorage(
         profile_path_, datum.category, result.count);
   }
+  if (profile_category_stats_.size() == kProfileStatisticCategories) {
+    if (done_callback_)
+      done_callback_.Run();
+  }
 }
 
 void ProfileStatisticsAggregator::StatisticsCallbackSuccess(
@@ -186,43 +200,6 @@
                      result_converted);
 }
 
-void ProfileStatisticsAggregator::CountBookmarks(
-    bookmarks::BookmarkModel* bookmark_model) {
-  int count = CountBookmarksFromNode(bookmark_model->bookmark_bar_node()) +
-              CountBookmarksFromNode(bookmark_model->other_node()) +
-              CountBookmarksFromNode(bookmark_model->mobile_node());
-
-  StatisticsCallbackSuccess(profiles::kProfileStatisticsBookmarks, count);
-}
-
-void ProfileStatisticsAggregator::WaitOrCountBookmarks() {
-  // The following checks should only fail in unit tests unrelated to gathering
-  // statistics. Do not bother to return failure in any of these cases.
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  if (!profile_manager)
-    return;
-  if (!g_browser_process->profile_manager()->IsValidProfile(profile_))
-    return;
-
-  bookmarks::BookmarkModel* bookmark_model =
-      BookmarkModelFactory::GetForBrowserContextIfExists(profile_);
-
-  if (bookmark_model) {
-    if (bookmark_model->loaded()) {
-      CountBookmarks(bookmark_model);
-    } else if (!bookmark_model_helper_) {
-      // If |bookmark_model_helper_| is not null, it means a previous bookmark
-      // counting task still waiting for the bookmark model to load. Do nothing
-      // and continue to use the old |bookmark_model_helper_| in this case.
-      AddRef();
-      bookmark_model_helper_.reset(new BookmarkModelHelper(this));
-      bookmark_model->AddObserver(bookmark_model_helper_.get());
-    }
-  } else {
-    StatisticsCallbackFailure(profiles::kProfileStatisticsBookmarks);
-  }
-}
-
 ProfileStatisticsAggregator::ProfileStatValue
     ProfileStatisticsAggregator::CountPrefs() const {
   const PrefService* pref_service = profile_->GetPrefs();
diff --git a/chrome/browser/profiles/profile_statistics_aggregator.h b/chrome/browser/profiles/profile_statistics_aggregator.h
index fc45518..03c0cfe 100644
--- a/chrome/browser/profiles/profile_statistics_aggregator.h
+++ b/chrome/browser/profiles/profile_statistics_aggregator.h
@@ -16,7 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/task_runner.h"
 #include "chrome/browser/profiles/profile_statistics_common.h"
-#include "components/bookmarks/browser/bookmark_model_observer.h"
+#include "components/browsing_data/core/counters/browsing_data_counter.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 
@@ -32,13 +32,11 @@
   // logins and preferences are counted.
   //
   // The class is RefCounted because this is needed for CancelableTaskTracker
-  // to function properly. Once all tasks are run (or cancelled) the instance is
-  // automatically destructed.
+  // to function properly.
 
  public:
   ProfileStatisticsAggregator(Profile* profile,
-      const profiles::ProfileStatisticsCallback& stats_callback,
-      const base::Closure& destruct_callback);
+                              const base::Closure& done_callback);
 
   void AddCallbackAndStartAggregator(
       const profiles::ProfileStatisticsCallback& stats_callback);
@@ -69,50 +67,12 @@
   void StatisticsCallbackFailure(const char* category);
   // Callback for history.
   void StatisticsCallbackHistory(history::HistoryCountResult result);
+  // Callback for counters.
+  void OnCounterResult(
+      std::unique_ptr<browsing_data::BrowsingDataCounter::Result> result);
 
-  // Bookmark counting.
-  void WaitOrCountBookmarks();
-  void CountBookmarks(bookmarks::BookmarkModel* bookmark_model);
-
-  class BookmarkModelHelper
-      : public bookmarks::BookmarkModelObserver {
-   public:
-    explicit BookmarkModelHelper(ProfileStatisticsAggregator* parent)
-        : parent_(parent) {}
-
-    void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
-                             bool ids_reassigned) override;
-
-    void BookmarkNodeMoved(bookmarks::BookmarkModel* model,
-                           const bookmarks::BookmarkNode* old_parent,
-                           int old_index,
-                           const bookmarks::BookmarkNode* new_parent,
-                           int new_index) override {}
-
-    void BookmarkNodeAdded(bookmarks::BookmarkModel* model,
-                           const bookmarks::BookmarkNode* parent,
-                           int index) override {}
-
-    void BookmarkNodeRemoved(bookmarks::BookmarkModel* model,
-        const bookmarks::BookmarkNode* parent,
-        int old_index, const bookmarks::BookmarkNode* node,
-        const std::set<GURL>& no_longer_bookmarked) override {}
-
-    void BookmarkNodeChanged(bookmarks::BookmarkModel* model,
-        const bookmarks::BookmarkNode* node) override {}
-
-    void BookmarkNodeFaviconChanged(bookmarks::BookmarkModel* model,
-        const bookmarks::BookmarkNode* node) override {}
-
-    void BookmarkNodeChildrenReordered(bookmarks::BookmarkModel* model,
-        const bookmarks::BookmarkNode* node) override {}
-
-    void BookmarkAllUserNodesRemoved(bookmarks::BookmarkModel* model,
-        const std::set<GURL>& removed_urls) override {}
-
-   private:
-    ProfileStatisticsAggregator* parent_ = nullptr;
-  };
+  // Registers and starts a BrowsingDataCounter.
+  void AddCounter(std::unique_ptr<browsing_data::BrowsingDataCounter> counter);
 
   // Password counting
   class PasswordStoreConsumerHelper
@@ -141,14 +101,12 @@
   // multiple times (once for each statistics).
   std::vector<profiles::ProfileStatisticsCallback> stats_callbacks_;
 
-  // Callback function to be called when the aggregator destructs. Used for
-  // removing expiring references to this aggregator.
-  base::Closure destruct_callback_;
+  // Callback function to be called when all statistics are calculated.
+  base::Closure done_callback_;
 
   base::CancelableTaskTracker tracker_;
 
-  // Bookmark counting
-  std::unique_ptr<BookmarkModelHelper> bookmark_model_helper_;
+  std::vector<std::unique_ptr<browsing_data::BrowsingDataCounter>> counters_;
 
   // Password counting.
   PasswordStoreConsumerHelper password_store_consumer_helper_;
diff --git a/chrome/browser/profiles/profile_statistics_unittest.cc b/chrome/browser/profiles/profile_statistics_unittest.cc
index 700b1fe..72c7334a 100644
--- a/chrome/browser/profiles/profile_statistics_unittest.cc
+++ b/chrome/browser/profiles/profile_statistics_unittest.cc
@@ -149,20 +149,16 @@
   ASSERT_TRUE(bookmark_model);
 
   // Run ProfileStatisticsAggregator::WaitOrCountBookmarks.
-  ProfileStatisticsAggregator* aggregator;
   BookmarkStatHelper bookmark_stat_helper;
-  base::RunLoop run_loop_aggregator_destruction;
-  // The following should run inside a scope, so the scoped_refptr gets deleted
-  // immediately.
-  {
-    scoped_refptr<ProfileStatisticsAggregator> aggregator_scoped =
-        new ProfileStatisticsAggregator(
-                profile,
-                base::Bind(&BookmarkStatHelper::StatsCallback,
-                           base::Unretained(&bookmark_stat_helper)),
-                run_loop_aggregator_destruction.QuitClosure());
-    aggregator = aggregator_scoped.get();
-  }
+  base::RunLoop run_loop_aggregator_done;
+
+  scoped_refptr<ProfileStatisticsAggregator> aggregator =
+      new ProfileStatisticsAggregator(profile,
+                                      run_loop_aggregator_done.QuitClosure());
+  aggregator->AddCallbackAndStartAggregator(
+      base::Bind(&BookmarkStatHelper::StatsCallback,
+                 base::Unretained(&bookmark_stat_helper)));
+
   // Wait until ProfileStatisticsAggregator::WaitOrCountBookmarks is run.
   base::RunLoop run_loop1;
   run_loop1.RunUntilIdle();
@@ -180,6 +176,6 @@
   // observer added by WaitOrCountBookmarks is run.
   LoadBookmarkModel(profile, bookmark_model);
 
-  run_loop_aggregator_destruction.Run();
+  run_loop_aggregator_done.Run();
   EXPECT_EQ(1, bookmark_stat_helper.GetNumOfTimesCalled());
 }
diff --git a/chrome/browser/resources/md_history/history_item.js b/chrome/browser/resources/md_history/history_item.js
index 0415d72..646493b 100644
--- a/chrome/browser/resources/md_history/history_item.js
+++ b/chrome/browser/resources/md_history/history_item.js
@@ -66,6 +66,10 @@
      * @return {boolean} Whether the event was handled.
      */
     onKeydown: function(row, e) {
+      // Allow Home and End to move the history list.
+      if (e.key == 'Home' || e.key == 'End')
+        return true;
+
       // Prevent iron-list from changing the focus on enter.
       if (e.key == 'Enter')
         e.stopPropagation();
diff --git a/chrome/browser/ui/webui/omnibox/BUILD.gn b/chrome/browser/ui/webui/omnibox/BUILD.gn
index bf547a0..30f9b31 100644
--- a/chrome/browser/ui/webui/omnibox/BUILD.gn
+++ b/chrome/browser/ui/webui/omnibox/BUILD.gn
@@ -8,4 +8,7 @@
   sources = [
     "omnibox.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/chrome/browser/ui/webui/usb_internals/BUILD.gn b/chrome/browser/ui/webui/usb_internals/BUILD.gn
index 1774bc0..99f9375 100644
--- a/chrome/browser/ui/webui/usb_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/usb_internals/BUILD.gn
@@ -16,4 +16,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index 7f8ecf12..f019dab 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -60,7 +60,7 @@
 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx
 // The "Most visited" and "Recently closed" category titles always take 2 slots.
 // For the remaining 8 slots, we allocate 5 slots to "most-visited" items and 3
-// slots to"recently-closed" items, respectively.
+// slots to "recently-closed" items, respectively.
 constexpr size_t kMostVisitedItems = 5;
 constexpr size_t kRecentlyClosedItems = 3;
 
@@ -686,8 +686,11 @@
                               JumpListCategory category) {
   int icons_created = 0;
 
-  // Maximum number of icon files that each JumpList icon folder may hold.
-  size_t icon_limit = (category == JumpListCategory::kMostVisited) ? 10 : 6;
+  // Maximum number of icon files that each JumpList icon folder may hold, which
+  // is set to 2 times the normal amount.
+  size_t icon_limit =
+      2 * ((category == JumpListCategory::kMostVisited) ? kMostVisitedItems
+                                                        : kRecentlyClosedItems);
 
   // Clear the JumpList icon folder at |icon_dir| and the cache when
   // 1) "Most visited" category updates for the 1st time after Chrome is
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js b/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js
index bf78eb4..8c08f428 100644
--- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js
+++ b/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js
@@ -89,11 +89,14 @@
   var contents =
       METADATA[openedFiles[options.openRequestId]].contents;
 
+  var remaining = Math.max(0, contents.length - options.offset);
+  var length = Math.min(remaining, options.length);
+
   // Write the contents as ASCII text.
-  var buffer = new ArrayBuffer(options.length);
+  var buffer = new ArrayBuffer(length);
   var bufferView = new Uint8Array(buffer);
-  for (var i = 0; i < options.length; i++) {
-    bufferView[i] = contents.charCodeAt(i);
+  for (var i = 0; i < length; i++) {
+    bufferView[i] = contents.charCodeAt(i + options.offset);
   }
 
   onSuccess(buffer, false /* Last call. */);
diff --git a/chrome/common/media_router/mojo/BUILD.gn b/chrome/common/media_router/mojo/BUILD.gn
index 939e8555..8b1e6114 100644
--- a/chrome/common/media_router/mojo/BUILD.gn
+++ b/chrome/common/media_router/mojo/BUILD.gn
@@ -26,6 +26,9 @@
   public_deps = [
     "//mojo/common:common_custom_types",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("media_router") {
@@ -43,6 +46,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("media_router_test_interfaces") {
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index f6d1a254..4ecc55c 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -387,9 +387,11 @@
   }
 
   void ClearUsernameAndPasswordFields() {
-    username_element_.SetValue("");
+    username_element_.SetValue(WebString());
+    username_element_.SetSuggestedValue(WebString());
     username_element_.SetAutofilled(false);
-    password_element_.SetValue("");
+    password_element_.SetValue(WebString());
+    password_element_.SetSuggestedValue(WebString());
     password_element_.SetAutofilled(false);
   }
 
@@ -426,13 +428,18 @@
                                        const WebInputElement& password_element,
                                        const std::string& password,
                                        bool password_autofilled,
-                                       bool checkSuggestedValue) {
-    EXPECT_EQ(username, username_element.Value().Utf8());
+                                       bool check_suggested_username,
+                                       bool check_suggested_password) {
+    EXPECT_EQ(username, check_suggested_username
+                            ? username_element.SuggestedValue().Utf8()
+                            : username_element.Value().Utf8())
+        << "check_suggested_username == " << check_suggested_username;
     EXPECT_EQ(username_autofilled, username_element.IsAutofilled());
-    EXPECT_EQ(password, checkSuggestedValue
+
+    EXPECT_EQ(password, check_suggested_password
                             ? password_element.SuggestedValue().Utf8()
                             : password_element.Value().Utf8())
-        << "checkSuggestedValue == " << checkSuggestedValue;
+        << "check_suggested_password == " << check_suggested_password;
     EXPECT_EQ(password_autofilled, password_element.IsAutofilled());
   }
 
@@ -442,13 +449,10 @@
                             bool username_autofilled,
                             const std::string& password,
                             bool password_autofilled) {
-    CheckTextFieldsStateForElements(username_element_,
-                                    username,
-                                    username_autofilled,
-                                    password_element_,
-                                    password,
-                                    password_autofilled,
-                                    true);
+    CheckTextFieldsStateForElements(
+        username_element_, username, username_autofilled, password_element_,
+        password, password_autofilled, false /* check_suggested_username */,
+        true /* check_suggested_password */);
   }
 
   // Checks the DOM-accessible value of the username element and the
@@ -457,13 +461,30 @@
                                bool username_autofilled,
                                const std::string& password,
                                bool password_autofilled) {
-    CheckTextFieldsStateForElements(username_element_,
-                                    username,
-                                    username_autofilled,
-                                    password_element_,
-                                    password,
-                                    password_autofilled,
-                                    false);
+    CheckTextFieldsStateForElements(
+        username_element_, username, username_autofilled, password_element_,
+        password, password_autofilled, false /* check_suggested_username */,
+        false /* check_suggested_password */);
+  }
+
+  // Checks the suggested values of the |username| and |password| elements.
+  void CheckTextFieldsSuggestedState(const std::string& username,
+                                     bool username_autofilled,
+                                     const std::string& password,
+                                     bool password_autofilled) {
+    CheckTextFieldsStateForElements(
+        username_element_, username, username_autofilled, password_element_,
+        password, password_autofilled, true /* check_suggested_username */,
+        true /* check_suggested_password */);
+  }
+
+  void ResetFieldState(WebInputElement* element,
+                       const std::string& value = std::string(),
+                       bool is_autofilled = false) {
+    element->SetValue(WebString::FromUTF8(value));
+    element->SetSuggestedValue(WebString());
+    element->SetAutofilled(is_autofilled);
+    element->SetSelectionRange(value.size(), value.size());
   }
 
   void CheckUsernameSelection(int start, int end) {
@@ -1128,100 +1149,155 @@
   fill_data_.wait_for_username = true;
   SimulateOnFillPasswordForm(fill_data_);
 
-  // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    // Neither field should be autocompleted.
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
 
-  // If the password field is not autocompletable, it should not be affected.
-  SetElementReadOnly(password_element_, true);
-  EXPECT_FALSE(password_autofill_agent_->FillSuggestion(
-      username_element_, ASCIIToUTF16(kAliceUsername),
-      ASCIIToUTF16(kAlicePassword)));
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
-  SetElementReadOnly(password_element_, false);
+    // If the password field is not autocompletable, it should not be affected.
+    SetElementReadOnly(password_element_, true);
+    EXPECT_FALSE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kAliceUsername),
+        ASCIIToUTF16(kAlicePassword)));
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+    SetElementReadOnly(password_element_, false);
 
-  // After filling with the suggestion, both fields should be autocompleted.
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      username_element_, ASCIIToUTF16(kAliceUsername),
-      ASCIIToUTF16(kAlicePassword)));
-  CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
-  int username_length = strlen(kAliceUsername);
-  CheckUsernameSelection(username_length, username_length);
+    // After filling with the suggestion, both fields should be autocompleted.
+    EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kAliceUsername),
+        ASCIIToUTF16(kAlicePassword)));
+    CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
+    int username_length = strlen(kAliceUsername);
+    CheckUsernameSelection(username_length, username_length);
 
-  // Try Filling with a suggestion with password different from the one that was
-  // initially sent to the renderer.
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      username_element_, ASCIIToUTF16(kBobUsername),
-      ASCIIToUTF16(kCarolPassword)));
-  CheckTextFieldsDOMState(kBobUsername, true, kCarolPassword, true);
-  username_length = strlen(kBobUsername);
-  CheckUsernameSelection(username_length, username_length);
+    // Try Filling with a suggestion with password different from the one that
+    // was initially sent to the renderer.
+    EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kBobUsername),
+        ASCIIToUTF16(kCarolPassword)));
+    CheckTextFieldsDOMState(kBobUsername, true, kCarolPassword, true);
+    username_length = strlen(kBobUsername);
+    CheckUsernameSelection(username_length, username_length);
+
+    ClearUsernameAndPasswordFields();
+  }
 }
 
-// Tests that |FillSuggestion| properly fills the password if username is
-// read-only.
+// Tests that |FillSuggestion| doesn't change non-empty non-autofilled username
+// when interacting with the password field.
+TEST_F(PasswordAutofillAgentTest,
+       FillSuggestionFromPasswordFieldWithUsernameManuallyFilled) {
+  username_element_.SetValue(WebString::FromUTF8("user1"));
+
+  // Simulate the browser sending the login info, but set |wait_for_username| to
+  // prevent the form from being immediately filled.
+  fill_data_.wait_for_username = true;
+  SimulateOnFillPasswordForm(fill_data_);
+  // Neither field should have been autocompleted.
+  CheckTextFieldsDOMState("user1", false, std::string(), false);
+
+  // Only password field should be autocompleted.
+  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+      password_element_, ASCIIToUTF16(kAliceUsername),
+      ASCIIToUTF16(kAlicePassword)));
+  CheckTextFieldsDOMState("user1", false, kAlicePassword, true);
+
+  // Try Filling with a different password. Only password should be changed.
+  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+      password_element_, ASCIIToUTF16(kBobUsername),
+      ASCIIToUTF16(kCarolPassword)));
+  CheckTextFieldsDOMState("user1", false, kCarolPassword, true);
+}
+
+// Tests that |FillSuggestion| properly fills the password if the username field
+// is read-only.
 TEST_F(PasswordAutofillAgentTest, FillSuggestionIfUsernameReadOnly) {
   // Simulate the browser sending the login info.
   SetElementReadOnly(username_element_, true);
   SimulateOnFillPasswordForm(fill_data_);
 
-  // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    // Neither field should be autocompleted.
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
 
-  // Username field is not autocompletable, it should not be affected.
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      password_element_, ASCIIToUTF16(kAliceUsername),
-      ASCIIToUTF16(kAlicePassword)));
-  CheckTextFieldsDOMState(std::string(), false, kAlicePassword, true);
+    // Username field is not autocompletable, it should not be affected.
+    EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kAliceUsername),
+        ASCIIToUTF16(kAlicePassword)));
+    CheckTextFieldsDOMState(std::string(), false, kAlicePassword, true);
 
-  // Try Filling with a suggestion with password different from the one that was
-  // initially sent to the renderer.
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      password_element_, ASCIIToUTF16(kBobUsername),
-      ASCIIToUTF16(kCarolPassword)));
-  CheckTextFieldsDOMState(std::string(), false, kCarolPassword, true);
+    // Try Filling with a suggestion with password different from the one that
+    // was initially sent to the renderer.
+    EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kBobUsername),
+        ASCIIToUTF16(kCarolPassword)));
+    CheckTextFieldsDOMState(std::string(), false, kCarolPassword, true);
+
+    ClearUsernameAndPasswordFields();
+  }
 }
 
 // Tests that |PreviewSuggestion| properly previews the username and password.
 TEST_F(PasswordAutofillAgentTest, PreviewSuggestion) {
-  // Simulate the browser sending the login info, but set |wait_for_username|
-  // to prevent the form from being immediately filled.
+  // Simulate the browser sending the login info, but set |wait_for_username| to
+  // prevent the form from being immediately filled.
   fill_data_.wait_for_username = true;
   SimulateOnFillPasswordForm(fill_data_);
 
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    // Neither field should be autocompleted.
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+
+    // If the password field is not autocompletable, it should not be affected.
+    SetElementReadOnly(password_element_, true);
+    EXPECT_FALSE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    CheckTextFieldsSuggestedState(std::string(), false, std::string(), false);
+    SetElementReadOnly(password_element_, false);
+
+    // After selecting the suggestion, both fields should be previewed with
+    // suggested values.
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    CheckTextFieldsSuggestedState(kAliceUsername, true, kAlicePassword, true);
+    int username_length = strlen(kAliceUsername);
+    CheckUsernameSelection(0, username_length);
+
+    // Try previewing with a password different from the one that was initially
+    // sent to the renderer.
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kBobUsername, kCarolPassword));
+    CheckTextFieldsSuggestedState(kBobUsername, true, kCarolPassword, true);
+    username_length = strlen(kBobUsername);
+    CheckUsernameSelection(0, username_length);
+
+    ClearUsernameAndPasswordFields();
+  }
+}
+
+// Tests that |PreviewSuggestion| doesn't change non-empty non-autofilled
+// username when previewing autofills on interacting with the password field.
+TEST_F(PasswordAutofillAgentTest,
+       PreviewSuggestionFromPasswordFieldWithUsernameManuallyFilled) {
+  username_element_.SetValue(WebString::FromUTF8("user1"));
+
+  // Simulate the browser sending the login info, but set |wait_for_username| to
+  // prevent the form from being immediately filled.
+  fill_data_.wait_for_username = true;
+  SimulateOnFillPasswordForm(fill_data_);
   // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+  CheckTextFieldsDOMState("user1", false, std::string(), false);
 
-  // If the password field is not autocompletable, it should not be affected.
-  SetElementReadOnly(password_element_, true);
-  EXPECT_FALSE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
-  EXPECT_EQ(std::string(), username_element_.SuggestedValue().Utf8());
-  EXPECT_FALSE(username_element_.IsAutofilled());
-  EXPECT_EQ(std::string(), password_element_.SuggestedValue().Utf8());
-  EXPECT_FALSE(password_element_.IsAutofilled());
-  SetElementReadOnly(password_element_, false);
-
-  // After selecting the suggestion, both fields should be previewed
-  // with suggested values.
+  // Only password field should be autocompleted.
   EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
-  EXPECT_EQ(kAliceUsername, username_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(username_element_.IsAutofilled());
-  EXPECT_EQ(kAlicePassword, password_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(password_element_.IsAutofilled());
-  int username_length = strlen(kAliceUsername);
-  CheckUsernameSelection(0, username_length);
+      password_element_, kAliceUsername, kAlicePassword));
+  CheckTextFieldsSuggestedState(std::string(), false, kAlicePassword, true);
+  CheckTextFieldsDOMState("user1", false, std::string(), true);
 
-  // Try previewing with a password different from the one that was initially
-  // sent to the renderer.
+  // Try previewing with a different password. Only password should be changed.
   EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kBobUsername, kCarolPassword));
-  EXPECT_EQ(kBobUsername, username_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(username_element_.IsAutofilled());
-  EXPECT_EQ(kCarolPassword, password_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(password_element_.IsAutofilled());
-  username_length = strlen(kBobUsername);
-  CheckUsernameSelection(0, username_length);
+      password_element_, kBobUsername, kCarolPassword));
+  CheckTextFieldsSuggestedState(std::string(), false, kCarolPassword, true);
+  CheckTextFieldsDOMState("user1", false, std::string(), true);
 }
 
 // Tests that |PreviewSuggestion| properly previews the password if username is
@@ -1231,57 +1307,49 @@
   SetElementReadOnly(username_element_, true);
   SimulateOnFillPasswordForm(fill_data_);
 
-  // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    // Neither field should be autocompleted.
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
 
-  // Username field is not autocompletable, it should not be affected.
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      password_element_, kAliceUsername, kAlicePassword));
-  EXPECT_EQ(std::string(), username_element_.SuggestedValue().Utf8());
-  EXPECT_FALSE(username_element_.IsAutofilled());
+    // Username field is not autocompletable, it should not be affected.
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    // Password field must be autofilled.
+    CheckTextFieldsSuggestedState(std::string(), false, kAlicePassword, true);
 
-  // Password field must be autofilled.
-  EXPECT_EQ(kAlicePassword, password_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(password_element_.IsAutofilled());
+    // Try previewing with a password different from the one that was initially
+    // sent to the renderer.
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kBobUsername, kCarolPassword));
+    CheckTextFieldsSuggestedState(std::string(), false, kCarolPassword, true);
 
-  // Try previewing with a password different from the one that was initially
-  // sent to the renderer.
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      password_element_, kBobUsername, kCarolPassword));
-  EXPECT_EQ(std::string(), username_element_.SuggestedValue().Utf8());
-  EXPECT_FALSE(username_element_.IsAutofilled());
-  EXPECT_EQ(kCarolPassword, password_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(password_element_.IsAutofilled());
+    ClearUsernameAndPasswordFields();
+  }
 }
 
 // Tests that |PreviewSuggestion| properly sets the username selection range.
 TEST_F(PasswordAutofillAgentTest, PreviewSuggestionSelectionRange) {
-  username_element_.SetValue(WebString::FromUTF8("ali"));
-  username_element_.SetSelectionRange(3, 3);
-  username_element_.SetAutofilled(true);
-
-  CheckTextFieldsDOMState("ali", true, std::string(), false);
-
   // Simulate the browser sending the login info, but set |wait_for_username|
   // to prevent the form from being immediately filled.
   fill_data_.wait_for_username = true;
   SimulateOnFillPasswordForm(fill_data_);
 
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
-  EXPECT_EQ(kAliceUsername, username_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(username_element_.IsAutofilled());
-  EXPECT_EQ(kAlicePassword, password_element_.SuggestedValue().Utf8());
-  EXPECT_TRUE(password_element_.IsAutofilled());
-  int username_length = strlen(kAliceUsername);
-  CheckUsernameSelection(3, username_length);
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    ResetFieldState(&username_element_, "ali", true);
+    ResetFieldState(&password_element_);
+
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    CheckTextFieldsSuggestedState(kAliceUsername, true, kAlicePassword, true);
+    int username_length = strlen(kAliceUsername);
+    CheckUsernameSelection(3, username_length);
+  }
 }
 
 // Tests that |ClearPreview| properly clears previewed username and password
 // with password being previously autofilled.
 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithPasswordAutofilled) {
-  password_element_.SetValue(WebString::FromUTF8("sec"));
-  password_element_.SetAutofilled(true);
+  ResetFieldState(&password_element_, "sec", true);
 
   // Simulate the browser sending the login info, but set |wait_for_username|
   // to prevent the form from being immediately filled.
@@ -1290,27 +1358,24 @@
 
   CheckTextFieldsDOMState(std::string(), false, "sec", true);
 
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    EXPECT_TRUE(
+        password_autofill_agent_->DidClearAutofillSelection(selected_element));
 
-  EXPECT_TRUE(
-      password_autofill_agent_->DidClearAutofillSelection(username_element_));
-
-  EXPECT_TRUE(username_element_.Value().IsEmpty());
-  EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
-  EXPECT_FALSE(username_element_.IsAutofilled());
-  EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.Value().Utf16());
-  EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
-  EXPECT_TRUE(password_element_.IsAutofilled());
-  CheckUsernameSelection(0, 0);
+    EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
+    EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
+    CheckTextFieldsDOMState(std::string(), false, "sec", true);
+    CheckUsernameSelection(0, 0);
+  }
 }
 
 // Tests that |ClearPreview| properly clears previewed username and password
 // with username being previously autofilled.
 TEST_F(PasswordAutofillAgentTest, ClearPreviewWithUsernameAutofilled) {
-  username_element_.SetValue(WebString::FromUTF8("ali"));
+  ResetFieldState(&username_element_, "ali", true);
   username_element_.SetSelectionRange(3, 3);
-  username_element_.SetAutofilled(true);
 
   // Simulate the browser sending the login info, but set |wait_for_username|
   // to prevent the form from being immediately filled.
@@ -1319,30 +1384,25 @@
 
   CheckTextFieldsDOMState("ali", true, std::string(), false);
 
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    EXPECT_TRUE(
+        password_autofill_agent_->DidClearAutofillSelection(selected_element));
 
-  EXPECT_TRUE(
-      password_autofill_agent_->DidClearAutofillSelection(username_element_));
-
-  EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.Value().Utf16());
-  EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
-  EXPECT_TRUE(username_element_.IsAutofilled());
-  EXPECT_TRUE(password_element_.Value().IsEmpty());
-  EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
-  EXPECT_FALSE(password_element_.IsAutofilled());
-  CheckUsernameSelection(3, 3);
+    EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
+    EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
+    CheckTextFieldsDOMState("ali", true, std::string(), false);
+    CheckUsernameSelection(3, 3);
+  }
 }
 
 // Tests that |ClearPreview| properly clears previewed username and password
 // with username and password being previously autofilled.
 TEST_F(PasswordAutofillAgentTest,
        ClearPreviewWithAutofilledUsernameAndPassword) {
-  username_element_.SetValue(WebString::FromUTF8("ali"));
-  username_element_.SetSelectionRange(3, 3);
-  username_element_.SetAutofilled(true);
-  password_element_.SetValue(WebString::FromUTF8("sec"));
-  password_element_.SetAutofilled(true);
+  ResetFieldState(&username_element_, "ali", true);
+  ResetFieldState(&password_element_, "sec", true);
 
   // Simulate the browser sending the login info, but set |wait_for_username|
   // to prevent the form from being immediately filled.
@@ -1351,19 +1411,17 @@
 
   CheckTextFieldsDOMState("ali", true, "sec", true);
 
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    EXPECT_TRUE(
+        password_autofill_agent_->DidClearAutofillSelection(selected_element));
 
-  EXPECT_TRUE(
-      password_autofill_agent_->DidClearAutofillSelection(username_element_));
-
-  EXPECT_EQ(ASCIIToUTF16("ali"), username_element_.Value().Utf16());
-  EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
-  EXPECT_TRUE(username_element_.IsAutofilled());
-  EXPECT_EQ(ASCIIToUTF16("sec"), password_element_.Value().Utf16());
-  EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
-  EXPECT_TRUE(password_element_.IsAutofilled());
-  CheckUsernameSelection(3, 3);
+    EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
+    EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
+    CheckTextFieldsDOMState("ali", true, "sec", true);
+    CheckUsernameSelection(3, 3);
+  }
 }
 
 // Tests that |ClearPreview| properly clears previewed username and password
@@ -1377,19 +1435,17 @@
 
   CheckTextFieldsDOMState(std::string(), false, std::string(), false);
 
-  EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
-      username_element_, kAliceUsername, kAlicePassword));
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    EXPECT_TRUE(password_autofill_agent_->PreviewSuggestion(
+        selected_element, kAliceUsername, kAlicePassword));
+    EXPECT_TRUE(
+        password_autofill_agent_->DidClearAutofillSelection(selected_element));
 
-  EXPECT_TRUE(
-      password_autofill_agent_->DidClearAutofillSelection(username_element_));
-
-  EXPECT_TRUE(username_element_.Value().IsEmpty());
-  EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
-  EXPECT_FALSE(username_element_.IsAutofilled());
-  EXPECT_TRUE(password_element_.Value().IsEmpty());
-  EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
-  EXPECT_FALSE(password_element_.IsAutofilled());
-  CheckUsernameSelection(0, 0);
+    EXPECT_TRUE(username_element_.SuggestedValue().IsEmpty());
+    EXPECT_TRUE(password_element_.SuggestedValue().IsEmpty());
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+    CheckUsernameSelection(0, 0);
+  }
 }
 
 // Tests that logging is off by default.
@@ -2165,35 +2221,17 @@
   fill_data_.is_possible_change_password_form = true;
   SimulateOnFillPasswordForm(fill_data_);
 
-  // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
+  for (const auto& selected_element : {username_element_, password_element_}) {
+    // Neither field should be autocompleted.
+    CheckTextFieldsDOMState(std::string(), false, std::string(), false);
 
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      username_element_, ASCIIToUTF16(kAliceUsername),
-      ASCIIToUTF16(kAlicePassword)));
-  CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
-}
+    EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
+        selected_element, ASCIIToUTF16(kAliceUsername),
+        ASCIIToUTF16(kAlicePassword)));
+    CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
 
-// Tests that a password change form is properly filled with the password when
-// the user click on the password field.
-TEST_F(PasswordAutofillAgentTest,
-       FillSuggestionPasswordChangeFormsOnlyPassword) {
-  LoadHTML(kPasswordChangeFormHTML);
-  UpdateOriginForHTML(kPasswordChangeFormHTML);
-  UpdateUsernameAndPasswordElements();
-  // Simulate the browser sending the login info, but set |wait_for_username|
-  // to prevent the form from being immediately filled.
-  fill_data_.wait_for_username = true;
-  fill_data_.is_possible_change_password_form = true;
-  SimulateOnFillPasswordForm(fill_data_);
-
-  // Neither field should have been autocompleted.
-  CheckTextFieldsDOMState(std::string(), false, std::string(), false);
-
-  EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
-      password_element_, ASCIIToUTF16(kAliceUsername),
-      ASCIIToUTF16(kAlicePassword)));
-  CheckTextFieldsDOMState("", false, kAlicePassword, true);
+    ClearUsernameAndPasswordFields();
+  }
 }
 
 // Tests that one user click on a username field is sufficient to bring up a
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ae524d7c..e0cb84f5 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2986,6 +2986,7 @@
     "../browser/bookmarks/managed_bookmark_service_unittest.cc",
     "../browser/browser_about_handler_unittest.cc",
     "../browser/browser_process_impl_unittest.cc",
+    "../browser/browsing_data/bookmark_counter_unittest.cc",
     "../browser/browsing_data/browsing_data_appcache_helper_unittest.cc",
     "../browser/browsing_data/browsing_data_cache_storage_helper_unittest.cc",
     "../browser/browsing_data/browsing_data_channel_id_helper_unittest.cc",
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 642f6ff8..952ba4f5 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -281,6 +281,20 @@
   return IsElementEditable(element);
 }
 
+// Returns whether the |username_element| is allowed to be autofilled.
+//
+// Note that if the user interacts with the |password_field| and the
+// |username_element| is user-defined (i.e., non-empty and non-autofilled), then
+// this function returns false. This is a precaution, to not override the field
+// if it has been classified as username by accident.
+bool IsUsernameAmendable(const blink::WebInputElement& username_element,
+                         bool is_password_field_selected) {
+  return !username_element.IsNull() &&
+         IsElementAutocompletable(username_element) &&
+         (!is_password_field_selected || username_element.IsAutofilled() ||
+          username_element.Value().IsEmpty());
+}
+
 // Return true if either password_value or new_password_value is not empty and
 // not default.
 bool FormContainsNonDefaultPasswordValue(const PasswordForm& password_form) {
@@ -773,8 +787,9 @@
   if (element->IsPasswordField()) {
     password_info->password_field_suggestion_was_accepted = true;
     password_info->password_field = password_element;
-  } else if (!username_element.IsNull() &&
-             IsElementAutocompletable(username_element)) {
+  }
+
+  if (IsUsernameAmendable(username_element, element->IsPasswordField())) {
     username_element.SetAutofillValue(blink::WebString::FromUTF16(username));
     username_element.SetAutofilled(true);
     UpdateFieldValueAndPropertiesMaskMap(username_element, &username,
@@ -814,8 +829,7 @@
     return false;
   }
 
-  if (!element->IsPasswordField() && !username_element.IsNull() &&
-      IsElementAutocompletable(username_element)) {
+  if (IsUsernameAmendable(username_element, element->IsPasswordField())) {
     if (username_query_prefix_.empty())
       username_query_prefix_ = username_element.Value().Utf16();
 
@@ -843,8 +857,9 @@
   PasswordInfo* password_info;
 
   if (!FindPasswordInfoForElement(*element, &username_element,
-                                  &password_element, &password_info))
+                                  &password_element, &password_info)) {
     return false;
+  }
 
   ClearPreview(&username_element, &password_element);
   return true;
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn
index c2761d7..c3fb039a 100644
--- a/components/browsing_data/core/BUILD.gn
+++ b/components/browsing_data/core/BUILD.gn
@@ -13,6 +13,8 @@
     "clear_browsing_data_tab.h",
     "counters/autofill_counter.cc",
     "counters/autofill_counter.h",
+    "counters/bookmark_counter.cc",
+    "counters/bookmark_counter.h",
     "counters/browsing_data_counter.cc",
     "counters/browsing_data_counter.h",
     "counters/history_counter.cc",
@@ -30,12 +32,13 @@
   deps = [
     "//base",
     "//components/autofill/core/browser",
-    "//components/content_settings/core/browser:browser",
-    "//components/content_settings/core/common:common",
+    "//components/bookmarks/browser",
+    "//components/content_settings/core/browser",
+    "//components/content_settings/core/common",
     "//components/history/core/browser",
     "//components/password_manager/core/browser",
-    "//components/pref_registry:pref_registry",
-    "//components/prefs:prefs",
+    "//components/pref_registry",
+    "//components/prefs",
     "//components/strings",
     "//components/sync",
     "//components/version_info",
diff --git a/components/browsing_data/core/DEPS b/components/browsing_data/core/DEPS
index c8a900d..17612bf 100644
--- a/components/browsing_data/core/DEPS
+++ b/components/browsing_data/core/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/autofill/core/browser",
+  "+components/bookmarks/browser",
   "+components/browser_sync",
   "+components/content_settings",
   "+components/history/core/browser",
diff --git a/components/browsing_data/core/clear_browsing_data_tab.h b/components/browsing_data/core/clear_browsing_data_tab.h
index c6c0b5bc..cca479e 100644
--- a/components/browsing_data/core/clear_browsing_data_tab.h
+++ b/components/browsing_data/core/clear_browsing_data_tab.h
@@ -11,6 +11,8 @@
 // advanced tab and manage their state separately. It is important that all
 // preferences and the timeperiod selection have the same type. The default
 // value for dialogs without separate tabs is advanced.
+// TODO(dullweber): Maybe rename "ADVANCED" to "DEFAULT" because it is used in
+//   multiple places without a differentiation between advanced and basic.
 //
 // A Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.browsing_data
diff --git a/components/browsing_data/core/counters/bookmark_counter.cc b/components/browsing_data/core/counters/bookmark_counter.cc
new file mode 100644
index 0000000..03681a6d
--- /dev/null
+++ b/components/browsing_data/core/counters/bookmark_counter.cc
@@ -0,0 +1,102 @@
+// 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/browsing_data/core/counters/bookmark_counter.h"
+
+#include "base/memory/ptr_util.h"
+#include "components/bookmarks/browser/base_bookmark_model_observer.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node.h"
+
+namespace {
+
+int CountBookmarksFromNode(const bookmarks::BookmarkNode* node,
+                           base::Time period_start) {
+  int count = 0;
+  if (node->is_url()) {
+    if (node->date_added() >= period_start)
+      ++count;
+  } else {
+    for (int i = 0; i < node->child_count(); ++i)
+      count += CountBookmarksFromNode(node->GetChild(i), period_start);
+  }
+  return count;
+}
+
+using BookmarkModelCallback =
+    base::OnceCallback<void(const bookmarks::BookmarkModel*)>;
+
+// This class waits for the |bookmark_model| to load, then executes |callback|
+// and destroys itself afterwards.
+class BookmarkModelHelper : public bookmarks::BaseBookmarkModelObserver {
+ public:
+  BookmarkModelHelper(bookmarks::BookmarkModel* bookmark_model,
+                      BookmarkModelCallback callback)
+      : bookmark_model_(bookmark_model), callback_(std::move(callback)) {
+    DCHECK(!bookmark_model_->loaded());
+    bookmark_model_->AddObserver(this);
+  }
+
+  void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
+                           bool ids_reassigned) override {
+    std::move(callback_).Run(model);
+    delete this;
+  };
+
+  void BookmarkModelBeingDeleted(
+      bookmarks::BookmarkModel* bookmark_model) override {
+    // Don't leak this instance if the BookmarkModel never loads.
+    delete this;
+  }
+
+  void BookmarkModelChanged() override {}
+
+ private:
+  ~BookmarkModelHelper() override { bookmark_model_->RemoveObserver(this); }
+
+  bookmarks::BookmarkModel* bookmark_model_;
+  BookmarkModelCallback callback_;
+};
+
+}  // namespace
+
+namespace browsing_data {
+
+const char BookmarkCounter::kPrefName[] =
+    "browser.clear_data.fake.pref.bookmarks";
+
+BookmarkCounter::BookmarkCounter(bookmarks::BookmarkModel* bookmark_model)
+    : bookmark_model_(bookmark_model), weak_ptr_factory_(this) {
+  DCHECK(bookmark_model);
+}
+
+BookmarkCounter::~BookmarkCounter() {}
+
+void BookmarkCounter::OnInitialized() {}
+
+const char* BookmarkCounter::GetPrefName() const {
+  return kPrefName;
+}
+
+void BookmarkCounter::Count() {
+  if (bookmark_model_->loaded()) {
+    CountBookmarks(bookmark_model_);
+  } else {
+    new BookmarkModelHelper(bookmark_model_,
+                            base::BindOnce(&BookmarkCounter::CountBookmarks,
+                                           weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void BookmarkCounter::CountBookmarks(
+    const bookmarks::BookmarkModel* bookmark_model) {
+  base::Time start = GetPeriodStart();
+  int count =
+      CountBookmarksFromNode(bookmark_model->bookmark_bar_node(), start) +
+      CountBookmarksFromNode(bookmark_model->other_node(), start) +
+      CountBookmarksFromNode(bookmark_model->mobile_node(), start);
+  ReportResult(count);
+}
+
+}  // namespace browsing_data
diff --git a/components/browsing_data/core/counters/bookmark_counter.h b/components/browsing_data/core/counters/bookmark_counter.h
new file mode 100644
index 0000000..59f09f6
--- /dev/null
+++ b/components/browsing_data/core/counters/bookmark_counter.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BROWSING_DATA_CORE_COUNTERS_BOOKMARK_COUNTER_H_
+#define COMPONENTS_BROWSING_DATA_CORE_COUNTERS_BOOKMARK_COUNTER_H_
+
+#include <memory>
+
+#include "components/browsing_data/core/counters/browsing_data_counter.h"
+
+namespace bookmarks {
+class BookmarkModel;
+}
+
+namespace browsing_data {
+
+class BookmarkCounter : public browsing_data::BrowsingDataCounter {
+ public:
+  // This is not a registered preference. It is here because a pref_name
+  // is required for mapping a counter to ui elements.
+  static const char kPrefName[];
+
+  explicit BookmarkCounter(bookmarks::BookmarkModel* bookmark_model);
+  ~BookmarkCounter() override;
+
+  void OnInitialized() override;
+
+  const char* GetPrefName() const override;
+
+ private:
+  void Count() override;
+  void CountBookmarks(const bookmarks::BookmarkModel* bookmark_model);
+
+  bookmarks::BookmarkModel* bookmark_model_;
+  base::WeakPtrFactory<BookmarkCounter> weak_ptr_factory_;
+};
+
+}  // namespace browsing_data
+
+#endif  // COMPONENTS_BROWSING_DATA_CORE_COUNTERS_BOOKMARK_COUNTER_H_
diff --git a/components/browsing_data/core/counters/browsing_data_counter.cc b/components/browsing_data/core/counters/browsing_data_counter.cc
index bc26908d..243eee8 100644
--- a/components/browsing_data/core/counters/browsing_data_counter.cc
+++ b/components/browsing_data/core/counters/browsing_data_counter.cc
@@ -40,9 +40,21 @@
   OnInitialized();
 }
 
+void BrowsingDataCounter::InitWithoutPref(base::Time begin_time,
+                                          const Callback& callback) {
+  DCHECK(!initialized_);
+  callback_ = callback;
+  clear_browsing_data_tab_ = ClearBrowsingDataTab::ADVANCED;
+  begin_time_ = begin_time;
+  initialized_ = true;
+  OnInitialized();
+}
+
 void BrowsingDataCounter::OnInitialized() {}
 
 base::Time BrowsingDataCounter::GetPeriodStart() {
+  if (period_.GetPrefName().empty())
+    return begin_time_;
   return CalculateBeginDeleteTime(static_cast<TimePeriod>(*period_));
 }
 
diff --git a/components/browsing_data/core/counters/browsing_data_counter.h b/components/browsing_data/core/counters/browsing_data_counter.h
index a6cb288..bb180b46 100644
--- a/components/browsing_data/core/counters/browsing_data_counter.h
+++ b/components/browsing_data/core/counters/browsing_data_counter.h
@@ -107,6 +107,10 @@
             ClearBrowsingDataTab clear_browsing_data_tab,
             const Callback& callback);
 
+  // Can be called instead of |Init()|, to create a counter that doesn't
+  // observe pref changes and counts data that was changed since |begin_time|.
+  void InitWithoutPref(base::Time begin_time, const Callback& callback);
+
   // Name of the preference associated with this counter.
   virtual const char* GetPrefName() const = 0;
 
@@ -168,6 +172,9 @@
   // is to be deleted.
   IntegerPrefMember period_;
 
+  // This time period is used when |period_| is not initialized.
+  base::Time begin_time_;
+
   // Whether this class was properly initialized by calling |Init|.
   bool initialized_;
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index e4084a63..8b7b55f 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -141,10 +141,14 @@
   // If this is a non-secure Web origin (i.e. HTTP), kick off the discovery of
   // credentials stored for the secure version of this origin (i.e. HTTPS),
   // regardless of whether there are some precisely matching |results|.
+  //
+  // These results are used only for recording metrics at PasswordFormManager
+  // desctruction time, this is why they are requested so late.
   if (should_query_suppressed_https_forms_ &&
+      form_digest_.scheme == PasswordForm::SCHEME_HTML &&
       form_digest_.origin.SchemeIs(url::kHttpScheme)) {
     suppressed_https_form_fetcher_ =
-        base::MakeUnique<SuppressedHTTPSFormFetcher>(form_digest_.origin,
+        base::MakeUnique<SuppressedHTTPSFormFetcher>(form_digest_.signon_realm,
                                                      client_, this);
   }
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 6373db354..0b6096b5 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -44,11 +44,15 @@
 
 namespace {
 
-const char kTestHttpRealm[] = "http://accounts.google.com/";
-const char kTestHttpURL[] = "http://accounts.google.com/a/LoginAuth";
+constexpr const char kTestHttpRealm[] = "http://example.in/";
+constexpr const char kTestHttpActionURL[] = "http://login.example.org";
+constexpr const char kTestHttpLoginURL[] = "http://example.in";
 
-const char kTestHttpsRealm[] = "https://accounts.google.com/";
-const char kTestHttpsURL[] = "https://accounts.google.com/a/LoginAuth";
+constexpr const char kTestHttpsRealm[] = "https://example.in/";
+constexpr const char kTestHttpsActionURL[] = "https://login.example.org";
+constexpr const char kTestHttpsLoginURL[] = "https://example.in";
+
+constexpr const char kTestFederationURL[] = "https://accounts.google.com/";
 
 class MockConsumer : public FormFetcher::Consumer {
  public:
@@ -111,9 +115,9 @@
 // Creates a dummy non-federated form with some basic arbitrary values.
 PasswordForm CreateNonFederated() {
   PasswordForm form;
-  form.origin = GURL("https://example.in");
-  form.signon_realm = form.origin.spec();
-  form.action = GURL("https://login.example.org");
+  form.origin = GURL(kTestHttpsLoginURL);
+  form.signon_realm = kTestHttpsRealm;
+  form.action = GURL(kTestHttpsActionURL);
   form.username_value = ASCIIToUTF16("user");
   form.password_value = ASCIIToUTF16("password");
   return form;
@@ -122,9 +126,9 @@
 // Creates a dummy non-federated HTTP form with some basic arbitrary values.
 PasswordForm CreateHTTPNonFederated() {
   PasswordForm form;
-  form.origin = GURL("http://example.in");
-  form.signon_realm = form.origin.spec();
-  form.action = GURL("http://login.example.org");
+  form.origin = GURL(kTestHttpLoginURL);
+  form.signon_realm = kTestHttpRealm;
+  form.action = GURL(kTestHttpActionURL);
   form.username_value = ASCIIToUTF16("user");
   form.password_value = ASCIIToUTF16("password");
   return form;
@@ -134,7 +138,7 @@
 PasswordForm CreateFederated() {
   PasswordForm form = CreateNonFederated();
   form.password_value.clear();
-  form.federation_origin = url::Origin(GURL(kTestHttpsRealm));
+  form.federation_origin = url::Origin(GURL(kTestFederationURL));
   return form;
 }
 
@@ -169,7 +173,7 @@
   FormFetcherImplTest()
       : form_digest_(PasswordForm::SCHEME_HTML,
                      kTestHttpRealm,
-                     GURL(kTestHttpURL)) {
+                     GURL(kTestHttpLoginURL)) {
     mock_store_ = new MockPasswordStore();
     client_.set_store(mock_store_.get());
 
@@ -204,18 +208,21 @@
 
   // Simulates a call to Fetch(), and supplies |simulated_matches| as the
   // PasswordStore results. Expects that this will trigger the querying of
-  // suppressed HTTPS forms by means of a GetLogins call being issued against
-  // the |expected_form_digest|. Call CompleteQueryingSuppressedHTTPSForms with
-  // the emitted |consumer_ptr| to complete the query.
+  // suppressed HTTPS forms by means of a GetLoginsForSameOrganizationName call
+  // being issued against the |expected_signon_realm|.
+  //
+  // Call CompleteQueryingSuppressedHTTPSForms with the emitted |consumer_ptr|
+  // to complete the query.
   void SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
       const std::vector<PasswordForm>& simulated_http_matches,
-      const PasswordStore::FormDigest expected_form_digest,
+      const std::string& expected_signon_realm,
       base::WeakPtr<PasswordStoreConsumer>* consumer_ptr /* out */) {
     ASSERT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
 
     Fetch();
 
-    EXPECT_CALL(*mock_store_, GetLogins(expected_form_digest, _))
+    EXPECT_CALL(*mock_store_,
+                GetLoginsForSameOrganizationName(expected_signon_realm, _))
         .WillOnce(::testing::WithArg<1>(GetAndAssignWeakPtr(consumer_ptr)));
     const size_t num_matches = simulated_http_matches.size();
     EXPECT_CALL(consumer_, ProcessMatches(::testing::SizeIs(num_matches), 0u));
@@ -612,13 +619,10 @@
 
   // The matching PasswordStore results coming in should trigger another
   // GetLogins request to fetcht the suppressed HTTPS forms.
-  const PasswordStore::FormDigest https_version_of_form_digest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
   const PasswordForm matching_http_form = CreateHTTPNonFederated();
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      {matching_http_form}, https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      {matching_http_form}, kTestHttpRealm, &https_form_fetcher_ptr));
 
   EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
   EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(), IsEmpty());
@@ -638,12 +642,9 @@
 TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_RequeriedOnRefetch) {
   RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
 
-  const PasswordStore::FormDigest https_version_of_form_digest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr));
   ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
       std::vector<PasswordForm>(), https_form_fetcher_ptr));
 
@@ -651,8 +652,7 @@
   // credentials as well.
   const PasswordForm suppressed_https_form = CreateNonFederated();
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr));
   ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
       {suppressed_https_form}, https_form_fetcher_ptr));
 
@@ -663,21 +663,17 @@
 TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_NeverWiped) {
   RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
 
-  const PasswordStore::FormDigest https_version_of_form_digest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
   const PasswordForm suppressed_https_form = CreateNonFederated();
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr));
   ASSERT_NO_FATAL_FAILURE(CompleteQueryingSuppressedHTTPSForms(
       {suppressed_https_form}, https_form_fetcher_ptr));
 
   // Ensure that calling Fetch() does not wipe (even temporarily) the previously
   // fetched list of suppressed HTTPS credentials. Stale is better than nothing.
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr));
 
   EXPECT_TRUE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
   EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(),
@@ -688,12 +684,9 @@
        SuppressedHTTPSForms_FormFetcherDestroyedWhileQuerying) {
   RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
 
-  const PasswordStore::FormDigest https_version_of_form_digest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr = nullptr;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr));
 
   EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
 
@@ -708,17 +701,13 @@
 TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_SimultaneousQueries) {
   RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
 
-  const PasswordStore::FormDigest https_version_of_form_digest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr1;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr1));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr1));
 
   base::WeakPtr<PasswordStoreConsumer> https_form_fetcher_ptr2;
   ASSERT_NO_FATAL_FAILURE(SimulateFetchAndExpectQueryingSuppressedHTTPSForms(
-      std::vector<PasswordForm>(), https_version_of_form_digest,
-      &https_form_fetcher_ptr2));
+      std::vector<PasswordForm>(), kTestHttpRealm, &https_form_fetcher_ptr2));
 
   EXPECT_FALSE(form_fetcher_->DidCompleteQueryingSuppressedHTTPSForms());
   EXPECT_THAT(form_fetcher_->GetSuppressedHTTPSForms(), IsEmpty());
@@ -736,7 +725,7 @@
 
 TEST_F(FormFetcherImplTest, SuppressedHTTPSForms_NotQueriedForHTTPSOrigins) {
   form_digest_ = PasswordStore::FormDigest(
-      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsURL));
+      PasswordForm::SCHEME_HTML, kTestHttpsRealm, GURL(kTestHttpsLoginURL));
   RecreateFormFetcherWithQueryingSuppressedHTTPSForms();
   Fetch();
 
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 5de021e..e2067b6 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -30,12 +30,14 @@
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/psl_matching_helper.h"
 #include "components/password_manager/core/browser/sql_table_builder.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
 #include "sql/transaction.h"
+#include "third_party/re2/src/re2/re2.h"
 #include "url/origin.h"
 #include "url/url_constants.h"
 
@@ -1133,6 +1135,48 @@
   return false;
 }
 
+bool LoginDatabase::GetLoginsForSameOrganizationName(
+    const std::string& signon_realm,
+    std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) const {
+  DCHECK(forms);
+  forms->clear();
+
+  GURL signon_realm_as_url(signon_realm);
+  if (!signon_realm_as_url.SchemeIsHTTPOrHTTPS())
+    return true;
+
+  std::string organization_name =
+      GetOrganizationIdentifyingName(signon_realm_as_url);
+  if (organization_name.empty())
+    return true;
+
+  // SQLite does not provide a function to escape special characters, but
+  // seemingly uses POSIX Extended Regular Expressions (ERE), and so does RE2.
+  // In the worst case the bogus results will be filtered out below.
+  static constexpr char kRESchemeAndSubdomains[] = "^https?://([\\w+%-]+\\.)*";
+  static constexpr char kREDotAndEffectiveTLD[] = "(\\.[\\w+%-]+)+/$";
+  const std::string signon_realms_with_same_organization_name_regexp =
+      kRESchemeAndSubdomains + RE2::QuoteMeta(organization_name) +
+      kREDotAndEffectiveTLD;
+  sql::Statement s(db_.GetCachedStatement(
+      SQL_FROM_HERE, get_same_organization_name_logins_statement_.c_str()));
+  s.BindString(0, signon_realms_with_same_organization_name_regexp);
+
+  bool success = StatementToForms(&s, nullptr, forms);
+
+  using PasswordFormPtr = std::unique_ptr<autofill::PasswordForm>;
+  base::EraseIf(*forms, [&organization_name](const PasswordFormPtr& form) {
+    GURL candidate_signon_realm_as_url(form->signon_realm);
+    DCHECK_EQ(form->scheme, PasswordForm::SCHEME_HTML);
+    DCHECK(candidate_signon_realm_as_url.SchemeIsHTTPOrHTTPS());
+    std::string candidate_form_organization_name =
+        GetOrganizationIdentifyingName(candidate_signon_realm_as_url);
+    return candidate_form_organization_name != organization_name;
+  });
+
+  return success;
+}
+
 bool LoginDatabase::GetLoginsCreatedBetween(
     const base::Time begin,
     const base::Time end,
@@ -1315,6 +1359,11 @@
   DCHECK(get_statement_psl_federated_.empty());
   get_statement_psl_federated_ =
       get_statement_ + psl_statement + psl_federated_statement;
+  DCHECK(get_same_organization_name_logins_statement_.empty());
+  get_same_organization_name_logins_statement_ =
+      "SELECT " + all_column_names +
+      " FROM LOGINS"
+      " WHERE scheme == 0 AND signon_realm REGEXP ?";
   DCHECK(created_statement_.empty());
   created_statement_ =
       "SELECT " + all_column_names +
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h
index c6cf73dc..ed53b3a8 100644
--- a/components/password_manager/core/browser/login_database.h
+++ b/components/password_manager/core/browser/login_database.h
@@ -91,6 +91,18 @@
                  std::vector<std::unique_ptr<autofill::PasswordForm>>* forms)
       const WARN_UNUSED_RESULT;
 
+  // Retrieves all stored credentials with SCHEME_HTTP that have a realm whose
+  // organization-identifying name -- that is, the first domain name label below
+  // the effective TLD -- matches that of |signon_realm|. Return value indicates
+  // a successful query (but potentially no results).
+  //
+  // For example, the organization-identifying name of "https://foo.example.org"
+  // is `example`, and logins will be returned for "http://bar.example.co.uk",
+  // but not for "http://notexample.com" or "https://example.foo.com".
+  bool GetLoginsForSameOrganizationName(
+      const std::string& signon_realm,
+      std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) const;
+
   // Gets all logins created from |begin| onwards (inclusive) and before |end|.
   // You may use a null Time value to do an unbounded search in either
   // direction.
@@ -224,6 +236,7 @@
   std::string get_statement_psl_;
   std::string get_statement_federated_;
   std::string get_statement_psl_federated_;
+  std::string get_same_organization_name_logins_statement_;
   std::string created_statement_;
   std::string synced_statement_;
   std::string blacklisted_statement_;
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index b15468f..f219fd8 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -21,6 +21,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/os_crypt/os_crypt_mocker.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
 #include "components/password_manager/core/browser/psl_matching_helper.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
@@ -789,6 +790,146 @@
   EXPECT_EQ(0U, result.size());
 }
 
+TEST_F(LoginDatabaseTest,
+       GetLoginsForSameOrganizationName_OnlyWebHTTPFormsAreConsidered) {
+  static constexpr const struct {
+    const PasswordFormData form_data;
+    const char* other_queried_signon_realm;
+    bool expected_matches_itself;
+    bool expected_matches_other_realm;
+  } kTestCases[] = {
+      {{PasswordForm::SCHEME_HTML, "https://example.com/",
+        "https://example.com/origin", "", L"", L"", L"", L"u", L"p", false, 1},
+       nullptr,
+       true,
+       true},
+      {{PasswordForm::SCHEME_BASIC, "http://example.com/realm",
+        "http://example.com/", "", L"", L"", L"", L"u", L"p", false, 1},
+       nullptr,
+       false,
+       false},
+      {{PasswordForm::SCHEME_OTHER, "ftp://example.com/realm",
+        "ftp://example.com/", "", L"", L"", L"", L"u", L"p", false, 1},
+       "http://example.com/realm",
+       false,
+       false},
+      {{PasswordForm::SCHEME_HTML,
+        "federation://example.com/accounts.google.com",
+        "https://example.com/orgin", "", L"", L"", L"", L"u",
+        kTestingFederatedLoginMarker, false, 1},
+       "http://example.com/",
+       false,
+       false},
+      {{PasswordForm::SCHEME_HTML, "android://hash@example.com/",
+        "android://hash@example.com/", "", L"", L"", L"", L"u", L"p", false, 1},
+       "http://example.com/",
+       false,
+       false},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(test_case.form_data.signon_realm);
+
+    std::unique_ptr<PasswordForm> form =
+        CreatePasswordFormFromDataForTesting(test_case.form_data);
+    ASSERT_EQ(AddChangeForForm(*form), db().AddLogin(*form));
+
+    std::vector<std::unique_ptr<PasswordForm>> same_organization_forms;
+    EXPECT_TRUE(db().GetLoginsForSameOrganizationName(
+        form->signon_realm, &same_organization_forms));
+    EXPECT_EQ(test_case.expected_matches_itself ? 1u : 0u,
+              same_organization_forms.size());
+
+    if (test_case.other_queried_signon_realm) {
+      same_organization_forms.clear();
+      EXPECT_TRUE(db().GetLoginsForSameOrganizationName(
+          test_case.other_queried_signon_realm, &same_organization_forms));
+      EXPECT_EQ(test_case.expected_matches_other_realm ? 1u : 0u,
+                same_organization_forms.size());
+    }
+
+    ASSERT_TRUE(db().RemoveLogin(*form));
+  }
+}
+
+TEST_F(LoginDatabaseTest, GetLoginsForSameOrganizationName_DetailsOfMatching) {
+  const struct {
+    const char* saved_signon_realm;
+    const char* queried_signon_realm;
+    bool expected_matches;
+  } kTestCases[] = {
+      // PSL matches are also same-organization-name matches.
+      {"http://psl.example.com/", "http://example.com/", true},
+      {"http://example.com/", "http://sub.example.com/", true},
+      {"https://a.b.example.co.uk/", "https://c.d.e.example.co.uk/", true},
+
+      // Non-PSL but same-organization-name matches. Also an illustration why it
+      // would be unsafe to offer these credentials for filling.
+      {"https://example.com/", "https://example.co.uk/", true},
+      {"https://example.co.uk/", "https://example.com/", true},
+      {"https://a.example.appspot.com/", "https://b.example.co.uk/", true},
+
+      // Same-organization-name matches are HTTP/HTTPS-agnostic.
+      {"https://example.com/", "http://example.com/", true},
+      {"http://example.com/", "https://example.com/", true},
+
+      {"http://www.foo-bar.com/", "http://sub.foo-bar.com", true},
+      {"http://www.foo_bar.com/", "http://sub.foo_bar.com", true},
+      {"http://www.foo-bar.com/", "http://sub.foo%2Dbar.com", true},
+      {"http://www.foo%21bar.com/", "http://sub.foo!bar.com", true},
+      {"http://a.xn--sztr-7na0i.co.uk/", "http://xn--sztr-7na0i.com/", true},
+      {"http://a.xn--sztr-7na0i.co.uk/", "http://www.sz\xc3\xb3t\xc3\xa1r.com/",
+       true},
+
+      {"http://www.foo+bar.com/", "http://sub.foo+bar.com", true},
+      {"http://www.foooobar.com/", "http://sub.foo+bar.com", false},
+      {"http://www.fobar.com/", "http://sub.foo?bar.com", false},
+      {"http://www.foozbar.com/", "http://sub.foo.bar.com", false},
+      {"http://www.foozbar.com/", "http://sub.foo[a-z]bar.com", false},
+
+      {"https://notexample.com/", "https://example.com/", false},
+      {"https://a.notexample.com/", "https://example.com/", false},
+      {"https://example.com/", "https://notexample.com/", false},
+      {"https://example.com/", "https://example.bar.com/", false},
+      {"https://example.foo.com/", "https://example.com/", false},
+      {"https://example.foo.com/", "https://example.bar.com/", false},
+
+      // URLs without host portions, hosts without registry controlled domains
+      // or hosts consisting of a registry.
+      {"http://localhost/", "http://localhost/", false},
+      {"https://example/", "https://example/", false},
+      {"https://co.uk/", "https://co.uk/", false},
+      {"https://example/", "https://example.com/", false},
+      {"https://a.example/", "https://example.com/", false},
+      {"https://example.com/", "https://example/", false},
+      {"https://127.0.0.1/", "https://127.0.0.1/", false},
+      {"https:/[3ffe:2a00:100:7031::1]/", "https:/[3ffe:2a00:100:7031::1]/",
+       false},
+
+      // Queried |signon-realms| are invalid URIs.
+      {"https://example.com/", "", false},
+      {"https://example.com/", "bad url", false},
+      {"https://example.com/", "https://", false},
+      {"https://example.com/", "http://www.foo;bar.com", false},
+      {"https://example.com/", "example", false},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(test_case.saved_signon_realm);
+    SCOPED_TRACE(test_case.queried_signon_realm);
+
+    std::unique_ptr<PasswordForm> form = CreatePasswordFormFromDataForTesting(
+        {PasswordForm::SCHEME_HTML, test_case.saved_signon_realm,
+         test_case.saved_signon_realm, "", L"", L"", L"", L"u", L"p", true, 1});
+    std::vector<std::unique_ptr<PasswordForm>> result;
+    ASSERT_EQ(AddChangeForForm(*form), db().AddLogin(*form));
+    EXPECT_TRUE(db().GetLoginsForSameOrganizationName(
+        test_case.queried_signon_realm, &result));
+    EXPECT_EQ(test_case.expected_matches ? 1u : 0u, result.size());
+    ASSERT_TRUE(db().RemoveLogin(*form));
+  }
+}
+
 static bool AddTimestampedLogin(LoginDatabase* db,
                                 std::string url,
                                 const std::string& unique_string,
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h
index afc92cc..fe210f3d 100644
--- a/components/password_manager/core/browser/mock_password_store.h
+++ b/components/password_manager/core/browser/mock_password_store.h
@@ -28,6 +28,8 @@
   MOCK_METHOD1(RemoveLogin, void(const autofill::PasswordForm&));
   MOCK_METHOD2(GetLogins,
                void(const PasswordStore::FormDigest&, PasswordStoreConsumer*));
+  MOCK_METHOD2(GetLoginsForSameOrganizationName,
+               void(const std::string&, PasswordStoreConsumer*));
   MOCK_METHOD1(AddLogin, void(const autofill::PasswordForm&));
   MOCK_METHOD1(UpdateLogin, void(const autofill::PasswordForm&));
   MOCK_METHOD2(UpdateLoginWithPrimaryKey,
@@ -60,6 +62,10 @@
       const PasswordStore::FormDigest& form) override {
     return std::vector<std::unique_ptr<autofill::PasswordForm>>();
   }
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override {
+    return std::vector<std::unique_ptr<autofill::PasswordForm>>();
+  }
   MOCK_METHOD1(FillAutofillableLogins,
                bool(std::vector<std::unique_ptr<autofill::PasswordForm>>*));
   MOCK_METHOD1(FillBlacklistLogins,
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 734d2e5..d0895e8c8 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -119,6 +119,8 @@
   void SetUp() override {
     store_ = new testing::StrictMock<MockPasswordStore>;
     EXPECT_CALL(*store_, ReportMetrics(_, _)).Times(AnyNumber());
+    EXPECT_CALL(*store_, GetLoginsForSameOrganizationName(_, _))
+        .Times(AnyNumber());
     CHECK(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));
 
     EXPECT_CALL(client_, GetPasswordStore())
@@ -339,8 +341,7 @@
   observed.push_back(form);
   EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(existing_different)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(existing_different)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
   EXPECT_CALL(client_, IsSavingAndFillingEnabledForCurrentPage())
@@ -498,8 +499,7 @@
   observed.push_back(form);
   EXPECT_CALL(driver_, FillPasswordForm(_));
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(form)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   observed.clear();
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
@@ -516,8 +516,7 @@
   observed.push_back(form);
   EXPECT_CALL(driver_, FillPasswordForm(_));
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(form)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
 }
 
@@ -858,8 +857,7 @@
   form.new_password_value.clear();
   observed.push_back(form);
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .Times(2)
-      .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 
@@ -892,8 +890,7 @@
   PasswordForm form(MakeSimpleFormWithOnlyPasswordField());
   observed.push_back(form);
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .Times(2)
-      .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 
@@ -925,8 +922,7 @@
   observed.push_back(form);
   EXPECT_CALL(driver_, FillPasswordForm(_));
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(form)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
 
   // Now the form will be seen the second time, in a different frame. The driver
@@ -945,8 +941,7 @@
   PasswordForm form(MakeSimpleForm());
   observed.push_back(form);
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .Times(2)
-      .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 
@@ -976,8 +971,7 @@
   blacklisted_form.username_value = ASCIIToUTF16("");
   blacklisted_form.blacklisted_by_user = true;
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(blacklisted_form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(blacklisted_form)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 
@@ -1149,8 +1143,7 @@
   observed.push_back(form);
   EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(form)));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 
@@ -1183,7 +1176,7 @@
 
   // No call-back from store after GetLogins is called emulates that
   // PasswordStore did not fetch a form in time before submission.
-  EXPECT_CALL(*store_, GetLogins(_, _)).Times(2);
+  EXPECT_CALL(*store_, GetLogins(_, _));
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
   ASSERT_EQ(1u, manager()->pending_login_managers().size());
@@ -1413,10 +1406,12 @@
     if (found_matched_logins_in_store) {
       EXPECT_CALL(*store_, GetLogins(_, _))
           .WillRepeatedly(WithArg<1>(InvokeConsumer(form)));
+      EXPECT_CALL(*store_, GetLoginsForSameOrganizationName(_, _));
       EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
     } else {
       EXPECT_CALL(*store_, GetLogins(_, _))
           .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      EXPECT_CALL(*store_, GetLoginsForSameOrganizationName(_, _));
     }
     std::unique_ptr<PasswordFormManager> form_manager;
     if (found_matched_logins_in_store) {
@@ -1575,8 +1570,7 @@
   autofill::PasswordFormFillData form_data;
   EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data));
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(android_form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(android_form)));
   manager()->OnPasswordFormsParsed(&driver_, observed_forms);
   observed_forms.clear();
   manager()->OnPasswordFormsRendered(&driver_, observed_forms, true);
@@ -1622,8 +1616,7 @@
   autofill::PasswordFormFillData form_data;
   EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data));
   EXPECT_CALL(*store_, GetLogins(_, _))
-      .WillOnce(WithArg<1>(InvokeConsumer(android_form)))
-      .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms()));
+      .WillOnce(WithArg<1>(InvokeConsumer(android_form)));
   manager()->OnPasswordFormsParsed(&driver_, observed_forms);
   observed_forms.clear();
   manager()->OnPasswordFormsRendered(&driver_, observed_forms, true);
@@ -1666,7 +1659,7 @@
   observed.push_back(form);
 
   // Emulate page load.
-  EXPECT_CALL(*store_, GetLogins(_, _)).Times(3);
+  EXPECT_CALL(*store_, GetLogins(_, _)).Times(2);
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
   ASSERT_EQ(1u, manager()->pending_login_managers().size());
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index a9d543a4..0575e5d 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -225,6 +225,14 @@
   }
 }
 
+void PasswordStore::GetLoginsForSameOrganizationName(
+    const std::string& signon_realm,
+    PasswordStoreConsumer* consumer) {
+  std::unique_ptr<GetLoginsRequest> request(new GetLoginsRequest(consumer));
+  ScheduleTask(base::Bind(&PasswordStore::GetLoginsForSameOrganizationNameImpl,
+                          this, signon_realm, base::Passed(&request)));
+}
+
 void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
   Schedule(&PasswordStore::GetAutofillableLoginsImpl, consumer);
 }
@@ -499,6 +507,13 @@
     main_thread_runner_->PostTask(FROM_HERE, completion);
 }
 
+void PasswordStore::GetLoginsForSameOrganizationNameImpl(
+    const std::string& signon_realm,
+    std::unique_ptr<GetLoginsRequest> request) {
+  request->NotifyConsumerWithResults(
+      FillLoginsForSameOrganizationName(signon_realm));
+}
+
 void PasswordStore::GetAutofillableLoginsImpl(
     std::unique_ptr<GetLoginsRequest> request) {
   std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index b405e2f..6c2f104 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -182,6 +182,21 @@
   virtual void GetLogins(const FormDigest& form,
                          PasswordStoreConsumer* consumer);
 
+  // Returns all stored credentials with SCHEME_HTTP that have a realm whose
+  // organization-identifying name -- that is, the first domain name label below
+  // the effective TLD -- matches that of |signon_realm|. Notifies |consumer| on
+  // completion. The request will be cancelled if the consumer is destroyed.
+  //
+  // WARNING: This is *NOT* PSL (Public Suffix List) matching. The logins
+  // returned by this method are not safe to be filled into the observed form.
+  //
+  // For example, the organization-identifying name of "https://foo.example.org"
+  // is `example`, and logins will be returned for "http://bar.example.co.uk",
+  // but not for "http://notexample.com" or "https://example.foo.com".
+  virtual void GetLoginsForSameOrganizationName(
+      const std::string& signon_realm,
+      PasswordStoreConsumer* consumer);
+
   // Gets the complete list of PasswordForms that are not blacklist entries--and
   // are thus auto-fillable. |consumer| will be notified on completion.
   // The request will be cancelled if the consumer is destroyed.
@@ -374,6 +389,11 @@
   virtual std::vector<std::unique_ptr<autofill::PasswordForm>>
   FillMatchingLogins(const FormDigest& form) = 0;
 
+  // Finds and returns all organization-name-matching logins, or returns an
+  // empty list on error.
+  virtual std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) = 0;
+
   // Synchronous implementation for manipulating with statistics.
   virtual void AddSiteStatsImpl(const InteractionsStats& stats) = 0;
   virtual void RemoveSiteStatsImpl(const GURL& origin_domain) = 0;
@@ -464,6 +484,12 @@
       const base::Callback<bool(const GURL&)>& origin_filter,
       const base::Closure& completion);
 
+  // Finds all logins organization-name-matching |signon_realm| and notifies the
+  // consumer.
+  void GetLoginsForSameOrganizationNameImpl(
+      const std::string& signon_realm,
+      std::unique_ptr<GetLoginsRequest> request);
+
   // Finds all non-blacklist PasswordForms, and notifies the consumer.
   void GetAutofillableLoginsImpl(std::unique_ptr<GetLoginsRequest> request);
 
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc
index 037f961..2e05c0a 100644
--- a/components/password_manager/core/browser/password_store_default.cc
+++ b/components/password_manager/core/browser/password_store_default.cc
@@ -182,6 +182,16 @@
   return matched_forms;
 }
 
+std::vector<std::unique_ptr<PasswordForm>>
+PasswordStoreDefault::FillLoginsForSameOrganizationName(
+    const std::string& signon_realm) {
+  std::vector<std::unique_ptr<PasswordForm>> forms;
+  if (login_db_ &&
+      !login_db_->GetLoginsForSameOrganizationName(signon_realm, &forms))
+    return std::vector<std::unique_ptr<PasswordForm>>();
+  return forms;
+}
+
 bool PasswordStoreDefault::FillAutofillableLogins(
     std::vector<std::unique_ptr<PasswordForm>>* forms) {
   DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h
index af6da12..0c7faebe 100644
--- a/components/password_manager/core/browser/password_store_default.h
+++ b/components/password_manager/core/browser/password_store_default.h
@@ -70,6 +70,8 @@
       base::Time delete_end) override;
   std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
       const FormDigest& form) override;
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
   bool FillAutofillableLogins(
       std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
   bool FillBlacklistLogins(
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index c47de36..5383526 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -47,24 +47,32 @@
 
 namespace {
 
-const char kTestWebRealm1[] = "https://one.example.com/";
-const char kTestWebOrigin1[] = "https://one.example.com/origin";
-const char kTestWebRealm2[] = "https://two.example.com/";
-const char kTestWebOrigin2[] = "https://two.example.com/origin";
-const char kTestWebRealm3[] = "https://three.example.com/";
-const char kTestWebOrigin3[] = "https://three.example.com/origin";
-const char kTestWebRealm5[] = "https://five.example.com/";
-const char kTestWebOrigin5[] = "https://five.example.com/origin";
-const char kTestPSLMatchingWebRealm[] = "https://psl.example.com/";
-const char kTestPSLMatchingWebOrigin[] = "https://psl.example.com/origin";
-const char kTestUnrelatedWebRealm[] = "https://notexample.com/";
-const char kTestUnrelatedWebOrigin[] = "https:/notexample.com/origin";
-const char kTestInsecureWebRealm[] = "http://one.example.com/";
-const char kTestInsecureWebOrigin[] = "http://one.example.com/origin";
-const char kTestAndroidRealm1[] = "android://hash@com.example.android/";
-const char kTestAndroidRealm2[] = "android://hash@com.example.two.android/";
-const char kTestAndroidRealm3[] = "android://hash@com.example.three.android/";
-const char kTestUnrelatedAndroidRealm[] =
+constexpr const char kTestWebRealm1[] = "https://one.example.com/";
+constexpr const char kTestWebOrigin1[] = "https://one.example.com/origin";
+constexpr const char kTestWebRealm2[] = "https://two.example.com/";
+constexpr const char kTestWebOrigin2[] = "https://two.example.com/origin";
+constexpr const char kTestWebRealm3[] = "https://three.example.com/";
+constexpr const char kTestWebOrigin3[] = "https://three.example.com/origin";
+constexpr const char kTestWebRealm5[] = "https://five.example.com/";
+constexpr const char kTestWebOrigin5[] = "https://five.example.com/origin";
+constexpr const char kTestPSLMatchingWebRealm[] = "https://psl.example.com/";
+constexpr const char kTestPSLMatchingWebOrigin[] =
+    "https://psl.example.com/origin";
+constexpr const char kTestUnrelatedWebRealm[] = "https://notexample.com/";
+constexpr const char kTestUnrelatedWebOrigin[] = "https:/notexample.com/origin";
+constexpr const char kTestSameOrganizationNameWebRealm[] =
+    "https://example.appspot.com/";
+constexpr const char kTestSameOrganizationNameWebOrigin[] =
+    "https://example.appspot.com/origin";
+constexpr const char kTestInsecureWebRealm[] = "http://one.example.com/";
+constexpr const char kTestInsecureWebOrigin[] = "http://one.example.com/origin";
+constexpr const char kTestAndroidRealm1[] =
+    "android://hash@com.example.android/";
+constexpr const char kTestAndroidRealm2[] =
+    "android://hash@com.example.two.android/";
+constexpr const char kTestAndroidRealm3[] =
+    "android://hash@com.example.three.android/";
+constexpr const char kTestUnrelatedAndroidRealm[] =
     "android://hash@com.notexample.android/";
 
 class MockPasswordStoreConsumer : public PasswordStoreConsumer {
@@ -851,6 +859,61 @@
   }
 }
 
+TEST_F(PasswordStoreTest, GetLoginsForSameOrganizationName) {
+  static constexpr const PasswordFormData kSameOrganizationCredentials[] = {
+      // Credential that is an exact match of the observed form.
+      {PasswordForm::SCHEME_HTML, kTestWebRealm1, kTestWebOrigin1, "", L"", L"",
+       L"", L"username_value_1", L"", true, 1},
+      // Credential that is a PSL match of the observed form.
+      {PasswordForm::SCHEME_HTML, kTestPSLMatchingWebRealm,
+       kTestPSLMatchingWebOrigin, "", L"", L"", L"", L"username_value_2", L"",
+       true, 1},
+      // Credential for the HTTP version of the observed form. (Should not be
+      // filled, but returned as part of same-organization-name matches).
+      {PasswordForm::SCHEME_HTML, kTestInsecureWebRealm, kTestInsecureWebOrigin,
+       "", L"", L"", L"", L"username_value_3", L"", true, 1},
+      // Credential for a signon realm with a different TLD, but same
+      // organization identifying name.
+      {PasswordForm::SCHEME_HTML, kTestSameOrganizationNameWebRealm,
+       kTestSameOrganizationNameWebOrigin, "", L"", L"", L"",
+       L"username_value_4", L"", true, 1},
+  };
+
+  static constexpr const PasswordFormData kNotSameOrganizationCredentials[] = {
+      // Unrelated Web credential.
+      {PasswordForm::SCHEME_HTML, kTestUnrelatedWebRealm,
+       kTestUnrelatedWebOrigin, "", L"", L"", L"", L"username_value_5", L"",
+       true, 1},
+      // Credential for an affiliated Android application.
+      {PasswordForm::SCHEME_HTML, kTestAndroidRealm1, "", "", L"", L"", L"",
+       L"username_value_6", L"", true, 1}};
+
+  scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
+      base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(),
+      base::MakeUnique<LoginDatabase>(test_login_db_file_path())));
+  store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
+
+  std::vector<std::unique_ptr<PasswordForm>> expected_results;
+  for (const auto& form_data : kSameOrganizationCredentials) {
+    expected_results.push_back(CreatePasswordFormFromDataForTesting(form_data));
+    store->AddLogin(*expected_results.back());
+  }
+
+  for (const auto& form_data : kNotSameOrganizationCredentials) {
+    store->AddLogin(*CreatePasswordFormFromDataForTesting(form_data));
+  }
+
+  const std::string observed_form_realm = kTestWebRealm1;
+  MockPasswordStoreConsumer mock_consumer;
+  EXPECT_CALL(mock_consumer,
+              OnGetPasswordStoreResultsConstRef(
+                  UnorderedPasswordFormElementsAre(&expected_results)));
+  store->GetLoginsForSameOrganizationName(observed_form_realm, &mock_consumer);
+  base::RunLoop().RunUntilIdle();
+  store->ShutdownOnUIThread();
+  base::RunLoop().RunUntilIdle();
+}
+
 // TODO(crbug.com/706392): Fix password reuse detection for Android.
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 TEST_F(PasswordStoreTest, CheckPasswordReuse) {
diff --git a/components/password_manager/core/browser/psl_matching_helper.cc b/components/password_manager/core/browser/psl_matching_helper.cc
index b4c4bef1..6cbb305 100644
--- a/components/password_manager/core/browser/psl_matching_helper.cc
+++ b/components/password_manager/core/browser/psl_matching_helper.cc
@@ -116,4 +116,28 @@
       signon_realm,
       net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
 }
+
+std::string GetOrganizationIdentifyingName(const GURL& url) {
+  if (!url.is_valid())
+    return std::string();
+
+  const std::string organization_and_registrar =
+      net::registry_controlled_domains::GetDomainAndRegistry(
+          url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+  const size_t registrar_length =
+      net::registry_controlled_domains::GetRegistryLength(
+          url, net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+
+  if (organization_and_registrar.empty() || !registrar_length ||
+      registrar_length == std::string::npos) {
+    return std::string();
+  }
+
+  // No CHECK, std::string::substr gracefully handles an underflow there.
+  DCHECK_LT(registrar_length, organization_and_registrar.size());
+  return organization_and_registrar.substr(
+      0, organization_and_registrar.size() - registrar_length - 1);
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/psl_matching_helper.h b/components/password_manager/core/browser/psl_matching_helper.h
index ed10f30..1d0e659 100644
--- a/components/password_manager/core/browser/psl_matching_helper.h
+++ b/components/password_manager/core/browser/psl_matching_helper.h
@@ -76,6 +76,11 @@
 // registry-controlled domain part.
 std::string GetRegistryControlledDomain(const GURL& signon_realm);
 
+// Returns the organization-identifying name of the host of |url|, that is, the
+// first domain name label below the effective TLD. Returns the empty string for
+// URLs where these concepts are ill-defined, as well as for invalid URLs.
+std::string GetOrganizationIdentifyingName(const GURL& url);
+
 }  // namespace password_manager
 
 #endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PSL_MATCHING_HELPER_H_
diff --git a/components/password_manager/core/browser/psl_matching_helper_unittest.cc b/components/password_manager/core/browser/psl_matching_helper_unittest.cc
index 66c798df..3f6a25b 100644
--- a/components/password_manager/core/browser/psl_matching_helper_unittest.cc
+++ b/components/password_manager/core/browser/psl_matching_helper_unittest.cc
@@ -5,10 +5,15 @@
 #include "components/password_manager/core/browser/psl_matching_helper.h"
 
 #include <stddef.h>
+#include <cctype>
 
 #include "base/macros.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "components/autofill/core/common/password_form.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace password_manager {
 
@@ -387,6 +392,102 @@
   }
 }
 
+TEST(PSLMatchingUtilsTest, GetOrganizationIdentifyingName) {
+  static constexpr const struct {
+    const char* url;
+    const char* expected_organization_name;
+  } kTestCases[] = {
+      {"http://example.com/login", "example"},
+      {"https://example.com", "example"},
+      {"ftp://example.com/ftp_realm", "example"},
+
+      {"http://foo.bar.example.com", "example"},
+      {"http://example.co.uk", "example"},
+      {"http://bar.example.appspot.com", "example"},
+      {"http://foo.bar", "foo"},
+      {"https://user:pass@www.example.com:80/path?query#ref", "example"},
+
+      {"http://www.foo+bar.com", "foo+bar"},
+      {"http://www.foo-bar.com", "foo-bar"},
+      {"https://foo_bar.com", "foo_bar"},
+      {"http://www.foo%2Bbar.com", "foo+bar"},
+      {"http://www.foo%2Dbar.com", "foo-bar"},
+      {"https://foo%5Fbar.com", "foo_bar"},
+      {"http://www.foo%2Ebar.com", "bar"},
+
+      // Internationalized Domain Names: each dot-separated label of the domain
+      // name is individually Punycode-encoded, so the organization-identifying
+      // name is still well-defined and can be determined as normal.
+      //       , ,
+      //     szotar = sz\xc3\xb3t\xc3\xa1r (UTF-8) = xn--sztr-7na0i (IDN)
+      //       | |
+      //  U+00E1 U+00F3
+      {"https://www.sz\xc3\xb3t\xc3\xa1r.appspot.com", "xn--sztr-7na0i"},
+
+      {"http://www.foo!bar.com", "foo%21bar"},
+      {"http://www.foo%21bar.com", "foo%21bar"},
+      {"http://www.foo$bar.com", "foo%24bar"},
+      {"http://www.foo&bar.com", "foo%26bar"},
+      {"http://www.foo\'bar.com", "foo%27bar"},
+      {"http://www.foo(bar.com", "foo%28bar"},
+      {"http://www.foo)bar.com", "foo%29bar"},
+      {"http://www.foo*bar.com", "foo%2Abar"},
+      {"http://www.foo,bar.com", "foo%2Cbar"},
+      {"http://www.foo=bar.com", "foo%3Dbar"},
+
+      // URLs without host portions, hosts without registry controlled domains
+      // should, or hosts consisting of a registry yield the empty string.
+      {"http://localhost", ""},
+      {"http://co.uk", ""},
+      {"http://google", ""},
+      {"http://127.0.0.1", ""},
+      {"file:///usr/bin/stuff", ""},
+      {"federation://example.com/google.com", ""},
+      {"android://hash@com.example/", ""},
+      {"http://[1080:0:0:0:8:800:200C:417A]/", ""},
+      {"http://[3ffe:2a00:100:7031::1]", ""},
+      {"http://[::192.9.5.5]/", ""},
+
+      // Invalid URLs should yield the empty string.
+      {"", ""},
+      {"http://", ""},
+      {"bad url", ""},
+      {"http://www.example.com/%00", ""},
+      {"http://www.foo;bar.com", ""},
+      {"http://www.foo~bar.com", ""},
+  };
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(test_case.url);
+    GURL url(test_case.url);
+    EXPECT_EQ(test_case.expected_organization_name,
+              GetOrganizationIdentifyingName(url));
+  }
+}
+
+// Apart from alphanumeric characters and '.', only |kExpectedUnescapedChars|
+// are expected to appear without percent-encoding in the domain of a valid,
+// canonicalized URL.
+//
+// The purpose of this test is to ensure that the test cases around unescaped
+// special characters in `GetOrganizationIdentifyingName` are exhaustive.
+TEST(PSLMatchingUtilsTest,
+     GetOrganizationIdentifyingName_UnescapedSpecialChars) {
+  static constexpr const char kExpectedNonAlnumChars[] = {'+', '-', '_', '.'};
+  for (int chr = 0; chr <= 255; ++chr) {
+    const auto percent_encoded = base::StringPrintf("http://a%%%02Xb.hu/", chr);
+    const GURL url(percent_encoded);
+    if (isalnum(chr) || base::ContainsValue(kExpectedNonAlnumChars, chr)) {
+      ASSERT_TRUE(url.is_valid());
+      const auto percent_decoded = base::StringPrintf(
+          "http://a%cb.hu/", base::ToLowerASCII(static_cast<char>(chr)));
+      EXPECT_EQ(percent_decoded, url.spec());
+    } else if (url.is_valid()) {
+      EXPECT_EQ(percent_encoded, url.spec());
+    }
+  }
+}
+
 }  // namespace
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/suppressed_https_form_fetcher.cc b/components/password_manager/core/browser/suppressed_https_form_fetcher.cc
index d3111ad..79e9dd52 100644
--- a/components/password_manager/core/browser/suppressed_https_form_fetcher.cc
+++ b/components/password_manager/core/browser/suppressed_https_form_fetcher.cc
@@ -13,23 +13,17 @@
 namespace password_manager {
 
 SuppressedHTTPSFormFetcher::SuppressedHTTPSFormFetcher(
-    const GURL& http_origin,
+    const std::string& observed_signon_realm,
     const PasswordManagerClient* client,
     Consumer* consumer)
-    : client_(client), consumer_(consumer) {
+    : client_(client),
+      consumer_(consumer),
+      observed_signon_realm_as_url_(observed_signon_realm) {
   DCHECK(client_);
   DCHECK(consumer_);
-  DCHECK(http_origin.is_valid());
-  DCHECK(http_origin.SchemeIs(url::kHttpScheme));
-
-  GURL::Replacements scheme_to_https;
-  scheme_to_https.SetSchemeStr(url::kHttpsScheme);
-  GURL https_origin = http_origin.ReplaceComponents(scheme_to_https);
-  PasswordStore::FormDigest synthetic_form_digest(
-      autofill::PasswordForm::SCHEME_HTML, https_origin.GetOrigin().spec(),
-      https_origin);
-
-  client_->GetPasswordStore()->GetLogins(synthetic_form_digest, this);
+  DCHECK(observed_signon_realm_as_url_.SchemeIs(url::kHttpScheme));
+  client_->GetPasswordStore()->GetLoginsForSameOrganizationName(
+      observed_signon_realm, this);
 }
 
 SuppressedHTTPSFormFetcher::~SuppressedHTTPSFormFetcher() = default;
@@ -37,8 +31,11 @@
 void SuppressedHTTPSFormFetcher::OnGetPasswordStoreResults(
     std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
   base::EraseIf(
-      results, [](const std::unique_ptr<autofill::PasswordForm>& form) {
-        return form->is_public_suffix_match || form->is_affiliation_based_match;
+      results, [this](const std::unique_ptr<autofill::PasswordForm>& form) {
+        GURL candidate_signon_realm_as_url(form->signon_realm);
+        return !candidate_signon_realm_as_url.SchemeIs(url::kHttpsScheme) ||
+               candidate_signon_realm_as_url.host() !=
+                   observed_signon_realm_as_url_.host();
       });
 
   consumer_->ProcessSuppressedHTTPSForms(std::move(results));
diff --git a/components/password_manager/core/browser/suppressed_https_form_fetcher.h b/components/password_manager/core/browser/suppressed_https_form_fetcher.h
index 26b9639..b812368 100644
--- a/components/password_manager/core/browser/suppressed_https_form_fetcher.h
+++ b/components/password_manager/core/browser/suppressed_https_form_fetcher.h
@@ -12,14 +12,13 @@
 #include "base/macros.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
-
-class GURL;
+#include "url/gurl.h"
 
 namespace password_manager {
 
 class PasswordManagerClient;
 
-// Fetches credentials saved for the HTTPS counterpart of the given HTTP origin.
+// Fetches credentials saved for the HTTPS counterpart of the given HTTP realm.
 //
 // Filling these HTTPS credentials into forms served over HTTP is obviously
 // suppressed, the purpose of doing such a query is to collect metrics on how
@@ -36,7 +35,7 @@
         std::vector<std::unique_ptr<autofill::PasswordForm>> forms) = 0;
   };
 
-  SuppressedHTTPSFormFetcher(const GURL& http_origin,
+  SuppressedHTTPSFormFetcher(const std::string& observed_signon_realm,
                              const PasswordManagerClient* client,
                              Consumer* consumer);
   ~SuppressedHTTPSFormFetcher() override;
@@ -54,6 +53,8 @@
   const PasswordManagerClient* client_;
   Consumer* consumer_;
 
+  const GURL observed_signon_realm_as_url_;
+
   DISALLOW_COPY_AND_ASSIGN(SuppressedHTTPSFormFetcher);
 };
 
diff --git a/components/password_manager/core/browser/suppressed_https_form_fetcher_unittest.cc b/components/password_manager/core/browser/suppressed_https_form_fetcher_unittest.cc
index 6dfc3b51..f4f2e59 100644
--- a/components/password_manager/core/browser/suppressed_https_form_fetcher_unittest.cc
+++ b/components/password_manager/core/browser/suppressed_https_form_fetcher_unittest.cc
@@ -19,10 +19,13 @@
 using autofill::PasswordForm;
 using testing::_;
 
-const char kTestHttpsURL[] = "https://one.example.com/";
-const char kTestPSLMatchingHttpsURL[] = "https://psl.example.com/";
-const char kTestHttpURL[] = "http://one.example.com/";
-const char kTestAndroidRealmURI[] = "android://hash@com.example.one.android/";
+constexpr const char kTestHttpURL[] = "http://one.example.com/";
+constexpr const char kTestHttpsURL[] = "https://one.example.com/";
+constexpr const char kTestPSLMatchingHttpURL[] = "http://psl.example.com/";
+constexpr const char kTestPSLMatchingHttpsURL[] = "https://psl.example.com/";
+constexpr const char kTestHttpSameOrgNameURL[] = "http://login.example.co.uk/";
+constexpr const char kTestHttpsSameOrgNameURL[] =
+    "https://login.example.co.uk/";
 
 class MockConsumer : public SuppressedHTTPSFormFetcher::Consumer {
  public:
@@ -85,62 +88,66 @@
 };
 
 TEST_F(SuppressedHTTPSFormFetcherTest, EmptyStore) {
-  PasswordStore::FormDigest observed_form_digest(
-      autofill::PasswordForm::SCHEME_HTML, kTestHttpURL, GURL(kTestHttpURL));
-  PasswordStore::FormDigest https_form_digest(
-      autofill::PasswordForm::SCHEME_HTML, kTestHttpsURL, GURL(kTestHttpsURL));
-
-  EXPECT_CALL(*mock_store(), GetLogins(https_form_digest, _));
+  EXPECT_CALL(*mock_store(), GetLoginsForSameOrganizationName(kTestHttpURL, _));
+  SuppressedHTTPSFormFetcher suppressed_form_fetcher(
+      kTestHttpURL, mock_client(), mock_consumer());
   EXPECT_CALL(*mock_consumer(),
               ProcessSuppressedHTTPSFormsConstRef(::testing::IsEmpty()));
-  SuppressedHTTPSFormFetcher suppressed_form_fetcher(
-      observed_form_digest.origin, mock_client(), mock_consumer());
   suppressed_form_fetcher.OnGetPasswordStoreResults(
       std::vector<std::unique_ptr<PasswordForm>>());
 }
 
 TEST_F(SuppressedHTTPSFormFetcherTest, FullStore) {
-  static const PasswordFormData kTestCredentials[] = {
+  static constexpr const PasswordFormData kSuppressedHTTPSCredentials[] = {
       // Credential that is for the HTTPS counterpart of the observed form.
       {PasswordForm::SCHEME_HTML, kTestHttpsURL, kTestHttpsURL, "", L"", L"",
        L"", L"username_value_1", L"password_value_1", true, 1},
-      // Another credential for the HTTPS counterpart of the observed form.
+      // Once again, but with a different username/password.
       {PasswordForm::SCHEME_HTML, kTestHttpsURL, kTestHttpsURL, "", L"", L"",
        L"", L"username_value_2", L"password_value_2", true, 1},
-      // A PSL match of the HTTPS counterpart of the observed form.
+  };
+
+  static constexpr const PasswordFormData kOtherCredentials[] = {
+      // Credential exactly matching the observed form.
+      {PasswordForm::SCHEME_HTML, kTestHttpURL, kTestHttpURL, "", L"", L"", L"",
+       L"username_value_1", L"password_value_1", true, 1},
+      // A PSL match to the observed form.
+      {PasswordForm::SCHEME_HTML, kTestPSLMatchingHttpURL,
+       kTestPSLMatchingHttpURL, "", L"", L"", L"", L"username_value_2",
+       L"password_value_2", true, 1},
+      // A PSL match to the HTTPS counterpart of the observed form.
       {PasswordForm::SCHEME_HTML, kTestPSLMatchingHttpsURL,
        kTestPSLMatchingHttpsURL, "", L"", L"", L"", L"username_value_3",
        L"password_value_3", true, 1},
-      // Credential for an affiliated Android application.
-      {PasswordForm::SCHEME_HTML, kTestAndroidRealmURI, kTestAndroidRealmURI,
-       "", L"", L"", L"", L"username_value_4", L"password_value_4", true, 1}};
+      // Credentials for a HTTP origin with the same organization
+      // identifying name.
+      {PasswordForm::SCHEME_HTML, kTestHttpSameOrgNameURL,
+       kTestHttpSameOrgNameURL, "", L"", L"", L"", L"username_value_4",
+       L"password_value_4", true, 1},
+      // Credentials for a HTTPS origin with the same organization
+      // identifying name.
+      {PasswordForm::SCHEME_HTML, kTestHttpsSameOrgNameURL,
+       kTestHttpsSameOrgNameURL, "", L"", L"", L"", L"username_value_5",
+       L"password_value_5", true, 1}};
 
   std::vector<std::unique_ptr<PasswordForm>> simulated_store_results;
-  for (const auto& form_data : kTestCredentials)
+  std::vector<std::unique_ptr<PasswordForm>> expected_results;
+  for (const auto& form_data : kSuppressedHTTPSCredentials) {
+    expected_results.push_back(CreatePasswordFormFromDataForTesting(form_data));
     simulated_store_results.push_back(
         CreatePasswordFormFromDataForTesting(form_data));
-  ASSERT_EQ(4u, simulated_store_results.size());
-  simulated_store_results[2]->is_public_suffix_match = true;
-  simulated_store_results[3]->is_affiliation_based_match = true;
+  }
+  for (const auto& form_data : kOtherCredentials) {
+    simulated_store_results.push_back(
+        CreatePasswordFormFromDataForTesting(form_data));
+  }
 
-  // The PSL and affiliated matches should be filtered out.
-  std::vector<std::unique_ptr<PasswordForm>> expected_results;
-  expected_results.push_back(
-      base::MakeUnique<PasswordForm>(*simulated_store_results[0]));
-  expected_results.push_back(
-      base::MakeUnique<PasswordForm>(*simulated_store_results[1]));
-
-  PasswordStore::FormDigest observed_form_digest(
-      autofill::PasswordForm::SCHEME_HTML, kTestHttpURL, GURL(kTestHttpURL));
-  PasswordStore::FormDigest https_form_digest(
-      autofill::PasswordForm::SCHEME_HTML, kTestHttpsURL, GURL(kTestHttpsURL));
-
-  EXPECT_CALL(*mock_store(), GetLogins(https_form_digest, _));
+  EXPECT_CALL(*mock_store(), GetLoginsForSameOrganizationName(kTestHttpURL, _));
+  SuppressedHTTPSFormFetcher suppressed_form_fetcher(
+      kTestHttpURL, mock_client(), mock_consumer());
   EXPECT_CALL(*mock_consumer(),
               ProcessSuppressedHTTPSFormsConstRef(
                   UnorderedPasswordFormElementsAre(&expected_results)));
-  SuppressedHTTPSFormFetcher suppressed_form_fetcher(
-      observed_form_digest.origin, mock_client(), mock_consumer());
   suppressed_form_fetcher.OnGetPasswordStoreResults(
       std::move(simulated_store_results));
 }
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc
index 5e502f3..1e11a32 100644
--- a/components/password_manager/core/browser/test_password_store.cc
+++ b/components/password_manager/core/browser/test_password_store.cc
@@ -112,6 +112,13 @@
   return matched_forms;
 }
 
+std::vector<std::unique_ptr<autofill::PasswordForm>>
+TestPasswordStore::FillLoginsForSameOrganizationName(
+    const std::string& signon_realm) {
+  // TODO: Implement when needed.
+  return std::vector<std::unique_ptr<autofill::PasswordForm>>();
+}
+
 void TestPasswordStore::ReportMetricsImpl(const std::string& sync_username,
                                           bool custom_passphrase_sync_enabled) {
 }
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h
index 8a644a6..837dfaa 100644
--- a/components/password_manager/core/browser/test_password_store.h
+++ b/components/password_manager/core/browser/test_password_store.h
@@ -46,6 +46,8 @@
       const autofill::PasswordForm& form) override;
   std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
       const FormDigest& form) override;
+  std::vector<std::unique_ptr<autofill::PasswordForm>>
+  FillLoginsForSameOrganizationName(const std::string& signon_realm) override;
 
   // Unused portions of PasswordStore interface
   void ReportMetricsImpl(const std::string& sync_username,
diff --git a/components/payments/mojom/BUILD.gn b/components/payments/mojom/BUILD.gn
index 9268a07..fc51993 100644
--- a/components/payments/mojom/BUILD.gn
+++ b/components/payments/mojom/BUILD.gn
@@ -8,6 +8,9 @@
   sources = [
     "payment_request.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("mojom_parser") {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 501316c..41eeec9 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -927,6 +927,7 @@
     "loader/upload_progress_tracker.h",
     "loader/url_loader_factory_impl.cc",
     "loader/url_loader_factory_impl.h",
+    "loader/url_loader_request_handler.h",
     "loader/wake_lock_resource_throttle.cc",
     "loader/wake_lock_resource_throttle.h",
     "loader_delegate_impl.cc",
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 6b0b706..172a84b 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -774,10 +774,11 @@
   DCHECK(channel_requests_.front().Equals(callback));
   channel_requests_.pop();
 
+  auto* gpu_data_manager = GpuDataManagerImpl::GetInstance();
   // Currently if any of the GPU features are blacklisted, we don't establish a
   // GPU channel.
   if (channel_handle.is_valid() &&
-      !GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr)) {
+      !gpu_data_manager->GpuAccessAllowed(nullptr)) {
     gpu_service_ptr_->CloseChannel(client_id);
     callback.Run(IPC::ChannelHandle(), gpu::GPUInfo(),
                  EstablishChannelStatus::GPU_ACCESS_DENIED);
@@ -786,8 +787,8 @@
     return;
   }
 
-  callback.Run(IPC::ChannelHandle(channel_handle.release()), gpu_info_,
-               EstablishChannelStatus::SUCCESS);
+  callback.Run(IPC::ChannelHandle(channel_handle.release()),
+               gpu_data_manager->GetGPUInfo(), EstablishChannelStatus::SUCCESS);
 }
 
 void GpuProcessHost::OnGpuMemoryBufferCreated(
@@ -846,11 +847,8 @@
   initialized_ = true;
   GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
   if (!gpu_data_manager->ShouldUseSwiftShader()) {
-    gpu_info_ = gpu_info;
     gpu_data_manager->UpdateGpuInfo(gpu_info);
     gpu_data_manager->UpdateGpuFeatureInfo(gpu_feature_info);
-  } else {
-    gpu_info_ = gpu_data_manager->GetGPUInfo();
   }
 }
 
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index bd98b70..7572b2c9 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -249,10 +249,6 @@
   bool swiftshader_rendering_;
   GpuProcessKind kind_;
 
-  // The GPUInfo for the connected process. Only valid after initialized_ is
-  // true.
-  gpu::GPUInfo gpu_info_;
-
   std::unique_ptr<base::Thread> in_process_gpu_thread_;
 
   // Whether we actually launched a GPU process.
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc
index f32156a..49b37ab1 100644
--- a/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -15,6 +15,7 @@
 #include "content/browser/loader/navigation_resource_handler.h"
 #include "content/browser/loader/navigation_resource_throttle.h"
 #include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/browser/resource_context_impl.h"
 #include "content/browser/service_worker/service_worker_navigation_handle.h"
 #include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -54,73 +55,140 @@
   return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
 }
 
-void PrepareNavigationStartOnIO(
-    std::unique_ptr<ResourceRequest> resource_request,
-    ResourceContext* resource_context,
-    ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
-    AppCacheNavigationHandleCore* appcache_handle_core,
-    NavigationRequestInfo* request_info,
-    mojom::URLLoaderFactoryPtrInfo factory_from_ui,
-    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-    const base::Callback<WebContents*(void)>& web_contents_getter,
-    mojom::URLLoaderAssociatedRequest url_loader_request,
-    mojom::URLLoaderClientPtr url_loader_client_to_pass,
-    std::unique_ptr<service_manager::Connector> connector) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  const ResourceType resource_type = request_info->is_main_frame
-                                         ? RESOURCE_TYPE_MAIN_FRAME
-                                         : RESOURCE_TYPE_SUB_FRAME;
-
-  if (resource_request->request_body) {
-    AttachRequestBodyBlobDataHandles(resource_request->request_body.get(),
-                                     resource_context);
-  }
-
-  mojom::URLLoaderFactoryPtr url_loader_factory_ptr;
-  if (service_worker_navigation_handle_core) {
-    RequestContextFrameType frame_type =
-        request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
-                                    : REQUEST_CONTEXT_FRAME_TYPE_NESTED;
-
-    storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
-        GetChromeBlobStorageContextForResourceContext(resource_context));
-    url_loader_factory_ptr =
-        ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
-            *resource_request, resource_context,
-            service_worker_navigation_handle_core, blob_storage_context,
-            request_info->begin_params.skip_service_worker, resource_type,
-            request_info->begin_params.request_context_type, frame_type,
-            request_info->are_ancestors_secure,
-            request_info->common_params.post_data, web_contents_getter);
-  }
-
-  // If we haven't gotten one from the above, then use the one the UI thread
-  // gave us, or otherwise fallback to the default.
-  mojom::URLLoaderFactory* factory;
-  if (url_loader_factory_ptr) {
-    factory = url_loader_factory_ptr.get();
-  } else {
-    if (factory_from_ui.is_valid()) {
-      url_loader_factory_ptr.Bind(std::move(factory_from_ui));
-      factory = url_loader_factory_ptr.get();
-    } else {
-      if (appcache_handle_core) {
-        factory = url_loader_factory_getter->GetAppCacheFactory()->get();
-      } else {
-        factory = url_loader_factory_getter->GetNetworkFactory()->get();
-      }
-    }
-  }
-
-  factory->CreateLoaderAndStart(
-      std::move(url_loader_request), 0 /* routing_id? */, 0 /* request_id? */,
-      mojom::kURLLoadOptionSendSSLInfo, *resource_request,
-      std::move(url_loader_client_to_pass));
-}
-
 }  // namespace
 
+// Kept around during the lifetime of the navigation request, and is
+// responsible for dispatching a ResourceRequest to the appropriate
+// URLLoaderFactory.  In order to get the right URLLoaderFactory it
+// builds a vector of URLLoaderRequestHandler's and successively calls
+// MaybeCreateLoaderFactory on each until the request is successfully
+// handled. The same sequence may be performed multiple times when
+// redirects happen.
+class NavigationURLLoaderNetworkService::URLLoaderRequestController {
+ public:
+  URLLoaderRequestController(std::unique_ptr<ResourceRequest> resource_request,
+                             ResourceContext* resource_context)
+      : resource_request_(std::move(resource_request)),
+        resource_context_(resource_context),
+        network_factory_(nullptr) {}
+
+  virtual ~URLLoaderRequestController() {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  }
+
+  void Start(
+      ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
+      AppCacheNavigationHandleCore* appcache_handle_core,
+      std::unique_ptr<NavigationRequestInfo> request_info,
+      mojom::URLLoaderFactoryPtrInfo factory_for_webui,
+      scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+      const base::Callback<WebContents*(void)>& web_contents_getter,
+      mojom::URLLoaderAssociatedRequest url_loader_request,
+      mojom::URLLoaderClientPtr url_loader_client_ptr,
+      std::unique_ptr<service_manager::Connector> connector) {
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    const ResourceType resource_type = request_info->is_main_frame
+                                           ? RESOURCE_TYPE_MAIN_FRAME
+                                           : RESOURCE_TYPE_SUB_FRAME;
+
+    if (resource_request_->request_body) {
+      AttachRequestBodyBlobDataHandles(resource_request_->request_body.get(),
+                                       resource_context_);
+    }
+
+    // Requests to WebUI scheme won't get redirected to/from other schemes
+    // or be intercepted, so we just let it go here.
+    if (factory_for_webui.is_valid()) {
+      mojom::URLLoaderFactoryPtr factory_ptr;
+      factory_ptr.Bind(std::move(factory_for_webui));
+      factory_ptr->CreateLoaderAndStart(
+          std::move(url_loader_request), 0 /* routing_id? */,
+          0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo,
+          *resource_request_, std::move(url_loader_client_ptr));
+      return;
+    }
+
+    DCHECK(handlers_.empty());
+    if (service_worker_navigation_handle_core) {
+      RequestContextFrameType frame_type =
+          request_info->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
+                                      : REQUEST_CONTEXT_FRAME_TYPE_NESTED;
+
+      storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
+          GetChromeBlobStorageContextForResourceContext(resource_context_));
+      std::unique_ptr<URLLoaderRequestHandler> service_worker_handler =
+          ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
+              *resource_request_, resource_context_,
+              service_worker_navigation_handle_core, blob_storage_context,
+              request_info->begin_params.skip_service_worker, resource_type,
+              request_info->begin_params.request_context_type, frame_type,
+              request_info->are_ancestors_secure,
+              request_info->common_params.post_data, web_contents_getter);
+      if (service_worker_handler)
+        handlers_.push_back(std::move(service_worker_handler));
+    }
+
+    if (appcache_handle_core) {
+      // TODO: add appcache code here.
+    }
+
+    DCHECK(!network_factory_);
+    network_factory_ = url_loader_factory_getter->GetNetworkFactory()->get();
+
+    Restart(std::move(url_loader_request), std::move(url_loader_client_ptr));
+  }
+
+  // This could be called multiple times.
+  void Restart(mojom::URLLoaderAssociatedRequest url_loader_request,
+               mojom::URLLoaderClientPtr url_loader_client_ptr) {
+    url_loader_request_ = std::move(url_loader_request);
+    url_loader_client_ptr_ = std::move(url_loader_client_ptr);
+    handler_index_ = 0;
+    MaybeStartLoader(nullptr);
+  }
+
+  void MaybeStartLoader(mojom::URLLoaderFactory* factory) {
+    DCHECK(url_loader_client_ptr_.is_bound());
+
+    if (factory) {
+      factory->CreateLoaderAndStart(
+          std::move(url_loader_request_), 0 /* routing_id? */,
+          0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo,
+          *resource_request_, std::move(url_loader_client_ptr_));
+      return;
+    }
+
+    if (handler_index_ < handlers_.size()) {
+      handlers_[handler_index_++]->MaybeCreateLoaderFactory(
+          *resource_request_, resource_context_,
+          base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
+                         base::Unretained(this)));
+      return;
+    }
+
+    DCHECK_EQ(handlers_.size(), handler_index_);
+    DCHECK(network_factory_ != nullptr);
+    MaybeStartLoader(network_factory_);
+  }
+
+ private:
+  std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_;
+  size_t handler_index_ = 0;
+
+  std::unique_ptr<ResourceRequest> resource_request_;
+  ResourceContext* resource_context_;
+
+  // The factory for doing a vanilla network request, called when
+  // any of other request handlers handle the given request.
+  mojom::URLLoaderFactory* network_factory_;
+
+  // Kept around until we create a loader.
+  mojom::URLLoaderAssociatedRequest url_loader_request_;
+  mojom::URLLoaderClientPtr url_loader_client_ptr_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
+};
+
 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
     ResourceContext* resource_context,
     StoragePartition* storage_partition,
@@ -129,36 +197,34 @@
     ServiceWorkerNavigationHandle* service_worker_navigation_handle,
     AppCacheNavigationHandle* appcache_handle,
     NavigationURLLoaderDelegate* delegate)
-    : delegate_(delegate),
-      binding_(this),
-      request_info_(std::move(request_info)) {
+    : delegate_(delegate), binding_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
       "navigation", "Navigation timeToResponseStarted", this,
-      request_info_->common_params.navigation_start, "FrameTreeNode id",
-      request_info_->frame_tree_node_id);
+      request_info->common_params.navigation_start, "FrameTreeNode id",
+      request_info->frame_tree_node_id);
 
   // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
   auto new_request = base::MakeUnique<ResourceRequest>();
 
-  new_request->method = request_info_->common_params.method;
-  new_request->url = request_info_->common_params.url;
-  new_request->first_party_for_cookies = request_info_->first_party_for_cookies;
+  new_request->method = request_info->common_params.method;
+  new_request->url = request_info->common_params.url;
+  new_request->first_party_for_cookies = request_info->first_party_for_cookies;
   new_request->priority = net::HIGHEST;
 
   // The code below to set fields like request_initiator, referrer, etc has
   // been copied from ResourceDispatcherHostImpl. We did not refactor the
   // common code into a function, because RDHI uses accessor functions on the
   // URLRequest class to set these fields. whereas we use ResourceRequest here.
-  new_request->request_initiator = request_info_->begin_params.initiator_origin;
-  new_request->referrer = request_info_->common_params.referrer.url;
-  new_request->referrer_policy = request_info_->common_params.referrer.policy;
-  new_request->headers = request_info_->begin_params.headers;
+  new_request->request_initiator = request_info->begin_params.initiator_origin;
+  new_request->referrer = request_info->common_params.referrer.url;
+  new_request->referrer_policy = request_info->common_params.referrer.policy;
+  new_request->headers = request_info->begin_params.headers;
 
-  int load_flags = request_info_->begin_params.load_flags;
+  int load_flags = request_info->begin_params.load_flags;
   load_flags |= net::LOAD_VERIFY_EV_CERT;
-  if (request_info_->is_main_frame)
+  if (request_info->is_main_frame)
     load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
 
   // Sync loads should have maximum priority and should be the only
@@ -167,7 +233,9 @@
 
   new_request->load_flags = load_flags;
 
-  new_request->request_body = request_info_->common_params.post_data.get();
+  new_request->request_body = request_info->common_params.post_data.get();
+
+  int frame_tree_node_id = request_info->frame_tree_node_id;
 
   mojom::URLLoaderAssociatedRequest loader_associated_request =
       mojo::MakeRequest(&url_loader_associated_ptr_);
@@ -175,39 +243,45 @@
   binding_.Bind(mojo::MakeRequest(&url_loader_client_ptr_to_pass));
 
   // Check if a web UI scheme wants to handle this request.
-  mojom::URLLoaderFactoryPtrInfo factory_ptr_info;
-
+  mojom::URLLoaderFactoryPtrInfo factory_for_webui;
   const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
   if (std::find(schemes.begin(), schemes.end(), new_request->url.scheme()) !=
       schemes.end()) {
     FrameTreeNode* frame_tree_node =
-        FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id);
-    factory_ptr_info = GetWebUIURLLoader(frame_tree_node).PassInterface();
+        FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+    factory_for_webui = GetWebUIURLLoader(frame_tree_node).PassInterface();
   }
 
   g_next_request_id--;
 
+  DCHECK(!request_controller_);
+  request_controller_ = base::MakeUnique<URLLoaderRequestController>(
+      std::move(new_request), resource_context);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&PrepareNavigationStartOnIO,
-                 base::Passed(std::move(new_request)), resource_context,
-                 service_worker_navigation_handle
-                     ? service_worker_navigation_handle->core()
-                     : nullptr,
-                 appcache_handle ? appcache_handle->core() : nullptr,
-                 request_info_.get(), base::Passed(std::move(factory_ptr_info)),
-                 static_cast<StoragePartitionImpl*>(storage_partition)
-                     ->url_loader_factory_getter(),
-                 base::Bind(&GetWebContentsFromFrameTreeNodeID,
-                            request_info_->frame_tree_node_id),
-                 base::Passed(std::move(loader_associated_request)),
-                 base::Passed(std::move(url_loader_client_ptr_to_pass)),
-                 base::Passed(ServiceManagerConnection::GetForProcess()
-                                  ->GetConnector()
-                                  ->Clone())));
+      base::Bind(
+          &URLLoaderRequestController::Start,
+          base::Unretained(request_controller_.get()),
+          service_worker_navigation_handle
+              ? service_worker_navigation_handle->core()
+              : nullptr,
+          appcache_handle ? appcache_handle->core() : nullptr,
+          base::Passed(std::move(request_info)),
+          base::Passed(std::move(factory_for_webui)),
+          static_cast<StoragePartitionImpl*>(storage_partition)
+              ->url_loader_factory_getter(),
+          base::Bind(&GetWebContentsFromFrameTreeNodeID, frame_tree_node_id),
+          base::Passed(std::move(loader_associated_request)),
+          base::Passed(std::move(url_loader_client_ptr_to_pass)),
+          base::Passed(ServiceManagerConnection::GetForProcess()
+                           ->GetConnector()
+                           ->Clone())));
 }
 
-NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {}
+NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {
+  BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
+                            request_controller_.release());
+}
 
 void NavigationURLLoaderNetworkService::FollowRedirect() {
   url_loader_associated_ptr_->FollowRedirect();
@@ -232,6 +306,8 @@
     const net::RedirectInfo& redirect_info,
     const ResourceResponseHead& head) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // TODO(kinuko): Perform the necessary check and call
+  // URLLoaderRequestController::Restart with the new URL??
   scoped_refptr<ResourceResponse> response(new ResourceResponse());
   response->head = head;
   delegate_->OnRequestRedirected(redirect_info, response);
diff --git a/content/browser/loader/navigation_url_loader_network_service.h b/content/browser/loader/navigation_url_loader_network_service.h
index 9e7af00..bee6717 100644
--- a/content/browser/loader/navigation_url_loader_network_service.h
+++ b/content/browser/loader/navigation_url_loader_network_service.h
@@ -60,14 +60,18 @@
       const ResourceRequestCompletionStatus& completion_status) override;
 
  private:
+  class URLLoaderRequestController;
+
   NavigationURLLoaderDelegate* delegate_;
 
   mojo::Binding<mojom::URLLoaderClient> binding_;
-  std::unique_ptr<NavigationRequestInfo> request_info_;
   mojom::URLLoaderAssociatedPtr url_loader_associated_ptr_;
   scoped_refptr<ResourceResponse> response_;
   SSLStatus ssl_status_;
 
+  // Lives on the IO thread.
+  std::unique_ptr<URLLoaderRequestController> request_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderNetworkService);
 };
 
diff --git a/content/browser/loader/url_loader_request_handler.h b/content/browser/loader/url_loader_request_handler.h
new file mode 100644
index 0000000..f72cc2a
--- /dev/null
+++ b/content/browser/loader/url_loader_request_handler.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
+#define CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "content/common/url_loader_factory.mojom.h"
+
+namespace content {
+
+class ResourceContext;
+struct ResourceRequest;
+
+using LoaderFactoryCallback =
+    base::OnceCallback<void(mojom::URLLoaderFactory*)>;
+
+// An instance of this class is a per-request object and kept around during
+// the lifetime of a request (including multiple redirect legs) on IO thread.
+class CONTENT_EXPORT URLLoaderRequestHandler {
+ public:
+  URLLoaderRequestHandler() = default;
+  virtual ~URLLoaderRequestHandler() = default;
+
+  // Calls |callback| with non-null factory if this handler can handle
+  // the request, calls it with nullptr otherwise.
+  // Some implementation notes:
+  // 1) The returned pointer needs to be valid only until a single
+  // CreateLoaderAndStart call is made, and it is okay to do CHECK(false) for
+  // any subsequent calls.
+  // 2) The implementor is not supposed to set up and return URLLoaderFactory
+  // until it finds out that the handler is really going to handle the
+  // request. (For example ServiceWorker's request handler would not need to
+  // call the callback until it gets response from SW, and it may still
+  // call the callback with nullptr if it turns out that it needs to fallback
+  // to the network.)
+  virtual void MaybeCreateLoaderFactory(const ResourceRequest& resource_request,
+                                        ResourceContext* resource_context,
+                                        LoaderFactoryCallback callback) = 0;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 69492d5..07b4f108 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -159,6 +159,45 @@
   return job.release();
 }
 
+void ServiceWorkerControlleeRequestHandler::MaybeCreateLoaderFactory(
+    const ResourceRequest& resource_request,
+    ResourceContext* resource_context,
+    base::OnceCallback<void(mojom::URLLoaderFactory*)> factory_callback) {
+  DCHECK(is_main_resource_load_);
+  ClearJob();
+
+  // TODO(kinuko): Keep ServiceWorkerResponseInfo somewhere around
+  // and reset the data every time we restart.
+
+  if (!context_ || !provider_host_) {
+    // We can't do anything other than to fall back to network.
+    std::move(factory_callback).Run(nullptr);
+    return;
+  }
+
+  // In fallback cases we basically 'forward' the request, so we should
+  // never see use_network_ gets true.
+  DCHECK(!use_network_);
+
+  url_job_ =
+      base::MakeUnique<ServiceWorkerURLJobWrapper>(std::move(factory_callback));
+
+  resource_context_ = resource_context;
+
+  PrepareForMainResource(resource_request.url,
+                         resource_request.first_party_for_cookies);
+
+  if (url_job_->ShouldFallbackToNetwork()) {
+    // We're falling back to the next URLLoaderRequestHandler, forward
+    // the request and clear job now.
+    url_job_->FallbackToNetwork();
+    ClearJob();
+    return;
+  }
+
+  // We will asynchronously continue on DidLookupRegistrationForMainResource.
+}
+
 void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
     const GURL& url,
     const GURL& first_party_for_cookies) {
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h
index 329edcfd..24a06a08 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -53,11 +53,25 @@
   ~ServiceWorkerControlleeRequestHandler() override;
 
   // Called via custom URLRequestJobFactory.
+  // Returning a nullptr indicates that the request is not handled by
+  // this handler.
+  // This could get called multiple times during the lifetime.
   net::URLRequestJob* MaybeCreateJob(
       net::URLRequest* request,
       net::NetworkDelegate* network_delegate,
       ResourceContext* resource_context) override;
 
+  // Used only for PlzNavigate and --enable-network-service cases.
+  // This will replace MaybeCreateJob() once NetworkService is enabled.
+  // This could get called multiple times during the lifetime in redirect
+  // cases. (In fallback-to-network cases we basically forward the request
+  // to the request to the next request handler)
+  // URLLoaderRequestHandler overrides:
+  void MaybeCreateLoaderFactory(
+      const ResourceRequest& request,
+      ResourceContext* resource_context,
+      base::OnceCallback<void(mojom::URLLoaderFactory*)> callback) override;
+
  private:
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
                            ActivateWaitingVersion);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index d00f76f..4dd89cd 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -97,9 +97,11 @@
   // Generate a new browser-assigned id for the host.
   int provider_id = g_next_navigation_provider_id--;
   auto host = base::WrapUnique(new ServiceWorkerProviderHost(
-      ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE, provider_id,
-      SERVICE_WORKER_PROVIDER_FOR_WINDOW, are_ancestors_secure, context,
-      nullptr));
+      ChildProcessHost::kInvalidUniqueID,
+      ServiceWorkerProviderHostInfo(provider_id, MSG_ROUTING_NONE,
+                                    SERVICE_WORKER_PROVIDER_FOR_WINDOW,
+                                    are_ancestors_secure),
+      context, nullptr));
   host->web_contents_getter_ = web_contents_getter;
   return host;
 }
@@ -111,8 +113,7 @@
     base::WeakPtr<ServiceWorkerContextCore> context,
     ServiceWorkerDispatcherHost* dispatcher_host) {
   return base::WrapUnique(new ServiceWorkerProviderHost(
-      process_id, info.route_id, info.provider_id, info.type,
-      info.is_parent_frame_secure, context, dispatcher_host));
+      process_id, std::move(info), context, dispatcher_host));
 }
 
 void ServiceWorkerProviderHost::BindWorkerFetchContext(
@@ -142,29 +143,23 @@
 
 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
     int render_process_id,
-    int route_id,
-    int provider_id,
-    ServiceWorkerProviderType provider_type,
-    bool is_parent_frame_secure,
+    ServiceWorkerProviderHostInfo info,
     base::WeakPtr<ServiceWorkerContextCore> context,
     ServiceWorkerDispatcherHost* dispatcher_host)
     : client_uuid_(base::GenerateGUID()),
       render_process_id_(render_process_id),
-      route_id_(route_id),
       render_thread_id_(kDocumentMainThreadId),
-      provider_id_(provider_id),
-      provider_type_(provider_type),
-      is_parent_frame_secure_(is_parent_frame_secure),
+      info_(std::move(info)),
       context_(context),
       dispatcher_host_(dispatcher_host),
       allow_association_(true) {
-  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_);
+  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, info_.type);
 
   // PlzNavigate
   CHECK(render_process_id != ChildProcessHost::kInvalidUniqueID ||
         IsBrowserSideNavigationEnabled());
 
-  if (provider_type_ == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
+  if (info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER) {
     // Actual thread id is set when the service worker context gets started.
     render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
   }
@@ -188,8 +183,8 @@
 }
 
 int ServiceWorkerProviderHost::frame_id() const {
-  if (provider_type_ == SERVICE_WORKER_PROVIDER_FOR_WINDOW)
-    return route_id_;
+  if (info_.type == SERVICE_WORKER_PROVIDER_FOR_WINDOW)
+    return info_.route_id;
   return MSG_ROUTING_NONE;
 }
 
@@ -304,7 +299,7 @@
 }
 
 bool ServiceWorkerProviderHost::IsProviderForClient() const {
-  switch (provider_type_) {
+  switch (info_.type) {
     case SERVICE_WORKER_PROVIDER_FOR_WINDOW:
     case SERVICE_WORKER_PROVIDER_FOR_WORKER:
     case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER:
@@ -312,15 +307,15 @@
     case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
       return false;
     case SERVICE_WORKER_PROVIDER_UNKNOWN:
-      NOTREACHED() << provider_type_;
+      NOTREACHED() << info_.type;
   }
-  NOTREACHED() << provider_type_;
+  NOTREACHED() << info_.type;
   return false;
 }
 
 blink::WebServiceWorkerClientType ServiceWorkerProviderHost::client_type()
     const {
-  switch (provider_type_) {
+  switch (info_.type) {
     case SERVICE_WORKER_PROVIDER_FOR_WINDOW:
       return blink::kWebServiceWorkerClientTypeWindow;
     case SERVICE_WORKER_PROVIDER_FOR_WORKER:
@@ -329,9 +324,9 @@
       return blink::kWebServiceWorkerClientTypeSharedWorker;
     case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
     case SERVICE_WORKER_PROVIDER_UNKNOWN:
-      NOTREACHED() << provider_type_;
+      NOTREACHED() << info_.type;
   }
-  NOTREACHED() << provider_type_;
+  NOTREACHED() << info_.type;
   return blink::kWebServiceWorkerClientTypeWindow;
 }
 
@@ -537,14 +532,13 @@
 std::unique_ptr<ServiceWorkerProviderHost>
 ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
   DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_);
-  DCHECK_NE(MSG_ROUTING_NONE, route_id_);
+  DCHECK_NE(MSG_ROUTING_NONE, info_.route_id);
   DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
-  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_);
+  DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, info_.type);
 
   std::unique_ptr<ServiceWorkerProviderHost> provisional_host =
       base::WrapUnique(new ServiceWorkerProviderHost(
-          process_id(), frame_id(), provider_id(), provider_type(),
-          is_parent_frame_secure(), context_, dispatcher_host()));
+          process_id(), std::move(info_), context_, dispatcher_host()));
 
   for (const GURL& pattern : associated_patterns_)
     DecreaseProcessReference(pattern);
@@ -560,10 +554,7 @@
   }
 
   render_process_id_ = ChildProcessHost::kInvalidUniqueID;
-  route_id_ = MSG_ROUTING_NONE;
   render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
-  provider_id_ = kInvalidServiceWorkerProviderId;
-  provider_type_ = SERVICE_WORKER_PROVIDER_UNKNOWN;
   dispatcher_host_ = nullptr;
   return provisional_host;
 }
@@ -575,11 +566,9 @@
   DCHECK_NE(MSG_ROUTING_NONE, provisional_host->frame_id());
 
   render_thread_id_ = kDocumentMainThreadId;
-  provider_id_ = provisional_host->provider_id();
-  provider_type_ = provisional_host->provider_type();
+  info_ = std::move(provisional_host->info_);
 
   FinalizeInitialization(provisional_host->process_id(),
-                         provisional_host->frame_id(),
                          provisional_host->dispatcher_host());
 }
 
@@ -590,13 +579,14 @@
     ServiceWorkerDispatcherHost* dispatcher_host) {
   CHECK(IsBrowserSideNavigationEnabled());
   DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
-  DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, provider_type_);
+  DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, info_.type);
   DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
 
   DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
   DCHECK_NE(MSG_ROUTING_NONE, frame_routing_id);
 
-  FinalizeInitialization(process_id, frame_routing_id, dispatcher_host);
+  info_.route_id = frame_routing_id;
+  FinalizeInitialization(process_id, dispatcher_host);
 }
 
 void ServiceWorkerProviderHost::SendUpdateFoundMessage(
@@ -765,10 +755,8 @@
 
 void ServiceWorkerProviderHost::FinalizeInitialization(
     int process_id,
-    int frame_routing_id,
     ServiceWorkerDispatcherHost* dispatcher_host) {
   render_process_id_ = process_id;
-  route_id_ = frame_routing_id;
   dispatcher_host_ = dispatcher_host;
 
   for (const GURL& pattern : associated_patterns_)
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 8c074f0f..4aa814af 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -88,14 +88,14 @@
 
   const std::string& client_uuid() const { return client_uuid_; }
   int process_id() const { return render_process_id_; }
-  int provider_id() const { return provider_id_; }
+  int provider_id() const { return info_.provider_id; }
   int frame_id() const;
-  int route_id() const { return route_id_; }
+  int route_id() const { return info_.route_id; }
   const WebContentsGetter& web_contents_getter() const {
     return web_contents_getter_;
   }
 
-  bool is_parent_frame_secure() const { return is_parent_frame_secure_; }
+  bool is_parent_frame_secure() const { return info_.is_parent_frame_secure; }
 
   // Returns whether this provider host is secure enough to have a service
   // worker controller.
@@ -157,7 +157,7 @@
   ServiceWorkerVersion* running_hosted_version() const {
     // Only providers for controllers can host a running version.
     DCHECK(!running_hosted_version_ ||
-           provider_type_ == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER);
+           info_.type == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER);
     return running_hosted_version_.get();
   }
 
@@ -170,7 +170,7 @@
   void SetTopmostFrameUrl(const GURL& url);
   const GURL& topmost_frame_url() const { return topmost_frame_url_; }
 
-  ServiceWorkerProviderType provider_type() const { return provider_type_; }
+  ServiceWorkerProviderType provider_type() const { return info_.type; }
   bool IsProviderForClient() const;
   blink::WebServiceWorkerClientType client_type() const;
 
@@ -319,10 +319,7 @@
   };
 
   ServiceWorkerProviderHost(int render_process_id,
-                            int route_id,
-                            int provider_id,
-                            ServiceWorkerProviderType provider_type,
-                            bool is_parent_frame_secure,
+                            ServiceWorkerProviderHostInfo info,
                             base::WeakPtr<ServiceWorkerContextCore> context,
                             ServiceWorkerDispatcherHost* dispatcher_host);
 
@@ -361,7 +358,6 @@
 
   // Finalizes cross-site transfers and navigation-initalized hosts.
   void FinalizeInitialization(int process_id,
-                              int frame_routing_id,
                               ServiceWorkerDispatcherHost* dispatcher_host);
 
   // Clears the information of the ServiceWorkerWorkerClient of dedicated (or
@@ -371,25 +367,20 @@
   std::string client_uuid_;
   int render_process_id_;
 
-  // See the constructor's documentation.
-  int route_id_;
-
   // For provider hosts that are hosting a running service worker, the id of the
   // service worker thread. Otherwise, |kDocumentMainThreadId|. May be
   // |kInvalidEmbeddedWorkerThreadId| before the hosted service worker starts
   // up, or during cross-site transfers.
   int render_thread_id_;
 
-  // Unique within the renderer process.
-  int provider_id_;
+  // Keeps the basic provider's info provided from the renderer side.
+  ServiceWorkerProviderHostInfo info_;
 
   // PlzNavigate
   // Only set when this object is pre-created for a navigation. It indicates the
   // tab where the navigation occurs.
   WebContentsGetter web_contents_getter_;
 
-  ServiceWorkerProviderType provider_type_;
-  const bool is_parent_frame_secure_;
   GURL document_url_;
   GURL topmost_frame_url_;
 
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index ce0560b..b41b982 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/url_schemes.h"
+#include "content/public/common/child_process_host.h"
 #include "content/public/common/origin_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
@@ -224,4 +225,48 @@
       provider_host_insecure_parent->IsContextSecureForServiceWorker());
 }
 
+TEST_F(ServiceWorkerProviderHostTest, CrossSiteTransfer) {
+  ServiceWorkerProviderHost* provider_host =
+      CreateProviderHost(GURL("https://www.example.com/example.html"));
+  const int process_id = provider_host->process_id();
+  const int provider_id = provider_host->provider_id();
+  const int frame_id = provider_host->frame_id();
+  const ServiceWorkerProviderType type = provider_host->provider_type();
+  const bool is_parent_frame_secure = provider_host->is_parent_frame_secure();
+  const ServiceWorkerDispatcherHost* dispatcher_host =
+      provider_host->dispatcher_host();
+
+  std::unique_ptr<ServiceWorkerProviderHost> provisional_host =
+      provider_host->PrepareForCrossSiteTransfer();
+
+  EXPECT_EQ(process_id, provisional_host->process_id());
+  EXPECT_EQ(provider_id, provisional_host->provider_id());
+  EXPECT_EQ(frame_id, provisional_host->frame_id());
+  EXPECT_EQ(type, provisional_host->provider_type());
+  EXPECT_EQ(is_parent_frame_secure, provisional_host->is_parent_frame_secure());
+  EXPECT_EQ(dispatcher_host, provisional_host->dispatcher_host());
+
+  EXPECT_EQ(ChildProcessHost::kInvalidUniqueID, provider_host->process_id());
+  EXPECT_EQ(kInvalidServiceWorkerProviderId, provider_host->provider_id());
+  EXPECT_EQ(MSG_ROUTING_NONE, provider_host->frame_id());
+  EXPECT_EQ(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_host->provider_type());
+  EXPECT_FALSE(provider_host->is_parent_frame_secure());
+  EXPECT_EQ(nullptr, provider_host->dispatcher_host());
+
+  provider_host->CompleteCrossSiteTransfer(provisional_host.get());
+
+  EXPECT_EQ(process_id, provider_host->process_id());
+  EXPECT_EQ(provider_id, provider_host->provider_id());
+  EXPECT_EQ(frame_id, provider_host->frame_id());
+  EXPECT_EQ(type, provider_host->provider_type());
+  EXPECT_EQ(is_parent_frame_secure, provider_host->is_parent_frame_secure());
+  EXPECT_EQ(dispatcher_host, provider_host->dispatcher_host());
+
+  EXPECT_EQ(kInvalidServiceWorkerProviderId, provisional_host->provider_id());
+  EXPECT_EQ(MSG_ROUTING_NONE, provisional_host->frame_id());
+  EXPECT_EQ(SERVICE_WORKER_PROVIDER_UNKNOWN, provisional_host->provider_type());
+  EXPECT_FALSE(provisional_host->is_parent_frame_secure());
+  EXPECT_EQ(nullptr, provisional_host->dispatcher_host());
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc
index ac4edb27..b1240cf 100644
--- a/content/browser/service_worker/service_worker_request_handler.cc
+++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -57,29 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor);
 };
 
-void FinalizeHandlerInitialization(
-    net::URLRequest* request,
-    ServiceWorkerProviderHost* provider_host,
-    storage::BlobStorageContext* blob_storage_context,
-    bool skip_service_worker,
-    FetchRequestMode request_mode,
-    FetchCredentialsMode credentials_mode,
-    FetchRedirectMode redirect_mode,
-    ResourceType resource_type,
-    RequestContextType request_context_type,
-    RequestContextFrameType frame_type,
-    scoped_refptr<ResourceRequestBodyImpl> body) {
-  std::unique_ptr<ServiceWorkerRequestHandler> handler(
-      provider_host->CreateRequestHandler(
-          request_mode, credentials_mode, redirect_mode, resource_type,
-          request_context_type, frame_type, blob_storage_context->AsWeakPtr(),
-          body, skip_service_worker));
-  if (!handler)
-    return;
-
-  request->SetUserData(&kUserDataKey, std::move(handler));
-}
-
 }  // namespace
 
 // PlzNavigate
@@ -119,11 +97,14 @@
           navigation_handle_core->context_wrapper()->context()->AsWeakPtr(),
           is_parent_frame_secure, web_contents_getter);
 
-  FinalizeHandlerInitialization(
-      request, provider_host.get(), blob_storage_context, skip_service_worker,
-      FETCH_REQUEST_MODE_NAVIGATE, FETCH_CREDENTIALS_MODE_INCLUDE,
-      FetchRedirectMode::MANUAL_MODE, resource_type, request_context_type,
-      frame_type, body);
+  std::unique_ptr<ServiceWorkerRequestHandler> handler(
+      provider_host->CreateRequestHandler(
+          FETCH_REQUEST_MODE_NAVIGATE, FETCH_CREDENTIALS_MODE_INCLUDE,
+          FetchRedirectMode::MANUAL_MODE, resource_type, request_context_type,
+          frame_type, blob_storage_context->AsWeakPtr(), body,
+          skip_service_worker));
+  if (handler)
+    request->SetUserData(&kUserDataKey, std::move(handler));
 
   // Transfer ownership to the ServiceWorkerNavigationHandleCore.
   // In the case of a successful navigation, the SWProviderHost will be
@@ -135,7 +116,7 @@
 
 // PlzNavigate and --enable-network-service.
 // static
-mojom::URLLoaderFactoryPtr
+std::unique_ptr<URLLoaderRequestHandler>
 ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
     const ResourceRequest& resource_request,
     ResourceContext* resource_context,
@@ -151,8 +132,41 @@
   DCHECK(IsBrowserSideNavigationEnabled() &&
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              switches::kEnableNetworkService));
-  // TODO(scottmg): Currently being implemented. See https://crbug.com/715640.
-  return mojom::URLLoaderFactoryPtr();
+  DCHECK(navigation_handle_core);
+
+  // Create the handler even for insecure HTTP since it's used in the
+  // case of redirect to HTTPS.
+  if (!resource_request.url.SchemeIsHTTPOrHTTPS() &&
+      !OriginCanAccessServiceWorkers(resource_request.url)) {
+    return nullptr;
+  }
+
+  if (!navigation_handle_core->context_wrapper() ||
+      !navigation_handle_core->context_wrapper()->context()) {
+    return nullptr;
+  }
+
+  // Initialize the SWProviderHost.
+  std::unique_ptr<ServiceWorkerProviderHost> provider_host =
+      ServiceWorkerProviderHost::PreCreateNavigationHost(
+          navigation_handle_core->context_wrapper()->context()->AsWeakPtr(),
+          is_parent_frame_secure, web_contents_getter);
+
+  std::unique_ptr<ServiceWorkerRequestHandler> handler(
+      provider_host->CreateRequestHandler(
+          FETCH_REQUEST_MODE_NAVIGATE, FETCH_CREDENTIALS_MODE_INCLUDE,
+          FetchRedirectMode::MANUAL_MODE, resource_type, request_context_type,
+          frame_type, blob_storage_context->AsWeakPtr(), body,
+          skip_service_worker));
+
+  // Transfer ownership to the ServiceWorkerNavigationHandleCore.
+  // In the case of a successful navigation, the SWProviderHost will be
+  // transferred to its "final" destination in the OnProviderCreated handler. If
+  // the navigation fails, it will be destroyed along with the
+  // ServiceWorkerNavigationHandleCore.
+  navigation_handle_core->DidPreCreateProviderHost(std::move(provider_host));
+
+  return base::WrapUnique<URLLoaderRequestHandler>(handler.release());
 }
 
 void ServiceWorkerRequestHandler::InitializeHandler(
@@ -186,10 +200,13 @@
   if (!provider_host || !provider_host->IsContextAlive())
     return;
 
-  FinalizeHandlerInitialization(request, provider_host, blob_storage_context,
-                                skip_service_worker, request_mode,
-                                credentials_mode, redirect_mode, resource_type,
-                                request_context_type, frame_type, body);
+  std::unique_ptr<ServiceWorkerRequestHandler> handler(
+      provider_host->CreateRequestHandler(
+          request_mode, credentials_mode, redirect_mode, resource_type,
+          request_context_type, frame_type, blob_storage_context->AsWeakPtr(),
+          body, skip_service_worker));
+  if (handler)
+    request->SetUserData(&kUserDataKey, std::move(handler));
 }
 
 ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler(
@@ -220,6 +237,14 @@
   return handler ? handler->provider_host_.get() : nullptr;
 }
 
+void ServiceWorkerRequestHandler::MaybeCreateLoaderFactory(
+    const ResourceRequest& request,
+    ResourceContext* resource_context,
+    LoaderFactoryCallback callback) {
+  NOTREACHED();
+  std::move(callback).Run(nullptr);
+}
+
 void ServiceWorkerRequestHandler::PrepareForCrossSiteTransfer(
     int old_process_id) {
   CHECK(!IsBrowserSideNavigationEnabled());
diff --git a/content/browser/service_worker/service_worker_request_handler.h b/content/browser/service_worker/service_worker_request_handler.h
index 98d24569..b6adb61 100644
--- a/content/browser/service_worker/service_worker_request_handler.h
+++ b/content/browser/service_worker/service_worker_request_handler.h
@@ -12,10 +12,10 @@
 #include "base/memory/weak_ptr.h"
 #include "base/supports_user_data.h"
 #include "base/time/time.h"
+#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_status_code.h"
 #include "content/common/service_worker/service_worker_types.h"
-#include "content/common/url_loader_factory.mojom.h"
 #include "content/public/common/request_context_frame_type.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
@@ -44,7 +44,8 @@
 // Abstract base class for routing network requests to ServiceWorkers.
 // Created one per URLRequest and attached to each request.
 class CONTENT_EXPORT ServiceWorkerRequestHandler
-    : public base::SupportsUserData::Data {
+    : public base::SupportsUserData::Data,
+      public URLLoaderRequestHandler {
  public:
   // PlzNavigate
   // Attaches a newly created handler if the given |request| needs to be handled
@@ -63,8 +64,9 @@
 
   // PlzNavigate and --enable-network-service.
   // Same as InitializeForNavigation() but instead of attaching to a URLRequest,
-  // returns a URLLoaderFactoryPtrInfo if the request needs to be handled.
-  static mojom::URLLoaderFactoryPtr InitializeForNavigationNetworkService(
+  // just creates a URLLoaderRequestHandler and returns it.
+  static std::unique_ptr<URLLoaderRequestHandler>
+  InitializeForNavigationNetworkService(
       const ResourceRequest& resource_request,
       ResourceContext* resource_context,
       ServiceWorkerNavigationHandleCore* navigation_handle_core,
@@ -126,6 +128,11 @@
       net::NetworkDelegate* network_delegate,
       ResourceContext* context) = 0;
 
+  // URLLoaderRequestHandler overrides.
+  void MaybeCreateLoaderFactory(const ResourceRequest& request,
+                                ResourceContext* resource_context,
+                                LoaderFactoryCallback callback) override;
+
   // Methods to support cross site navigations.
   void PrepareForCrossSiteTransfer(int old_process_id);
   void CompleteCrossSiteTransfer(int new_process_id,
diff --git a/content/browser/service_worker/service_worker_response_type.h b/content/browser/service_worker/service_worker_response_type.h
new file mode 100644
index 0000000..c8e15b9
--- /dev/null
+++ b/content/browser/service_worker/service_worker_response_type.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESPONSE_TYPE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESPONSE_TYPE_H_
+
+namespace content {
+
+// Response handling type, used in URL {request,loader} jobs.
+enum ServiceWorkerResponseType {
+  NOT_DETERMINED,
+  FAIL_DUE_TO_LOST_CONTROLLER,
+  FALLBACK_TO_NETWORK,
+  FALLBACK_TO_RENDERER,  // Use this when falling back with CORS check
+  FORWARD_TO_SERVICE_WORKER
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESPONSE_TYPE_H_
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index e843910..5b0ee5d9 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -15,7 +15,7 @@
     int provider_id,
     bool is_parent_frame_secure,
     base::WeakPtr<ServiceWorkerContextCore> context) {
-  ServiceWorkerProviderHostInfo info(provider_id, MSG_ROUTING_NONE,
+  ServiceWorkerProviderHostInfo info(provider_id, 1 /* route_id */,
                                      SERVICE_WORKER_PROVIDER_FOR_WINDOW,
                                      is_parent_frame_secure);
   return ServiceWorkerProviderHost::Create(process_id, std::move(info),
diff --git a/content/browser/service_worker/service_worker_url_job_wrapper.cc b/content/browser/service_worker/service_worker_url_job_wrapper.cc
index 7761fc7..41dbc205 100644
--- a/content/browser/service_worker/service_worker_url_job_wrapper.cc
+++ b/content/browser/service_worker/service_worker_url_job_wrapper.cc
@@ -5,6 +5,7 @@
 #include "content/browser/service_worker/service_worker_url_job_wrapper.h"
 
 #include "base/command_line.h"
+#include "content/browser/service_worker/service_worker_response_type.h"
 #include "content/public/browser/resource_request_info.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_switches.h"
@@ -13,11 +14,15 @@
 
 ServiceWorkerURLJobWrapper::ServiceWorkerURLJobWrapper(
     base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job)
-    : url_request_job_(std::move(url_request_job)), url_loader_(nullptr) {}
+    : job_type_(JobType::kURLRequest),
+      url_request_job_(std::move(url_request_job)),
+      weak_factory_(this) {}
 
 ServiceWorkerURLJobWrapper::ServiceWorkerURLJobWrapper(
-    ServiceWorkerControlleeURLLoader* url_loader)
-    : url_loader_(url_loader) {
+    LoaderFactoryCallback callback)
+    : job_type_(JobType::kURLLoader),
+      loader_factory_callback_(std::move(callback)),
+      weak_factory_(this) {
   DCHECK(IsBrowserSideNavigationEnabled() &&
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              switches::kEnableNetworkService));
@@ -26,40 +31,48 @@
 ServiceWorkerURLJobWrapper::~ServiceWorkerURLJobWrapper() {}
 
 void ServiceWorkerURLJobWrapper::FallbackToNetwork() {
-  if (url_loader_) {
-    NOTIMPLEMENTED();
+  if (job_type_ == JobType::kURLLoader) {
+    response_type_ = FALLBACK_TO_NETWORK;
+    // This could be called multiple times in some cases because we simply
+    // call this synchronously here and don't wait for a separate async
+    // StartRequest cue like what URLRequestJob case does.
+    // TODO(kinuko): Make sure this is ok or we need to make this async.
+    if (!loader_factory_callback_.is_null()) {
+      std::move(loader_factory_callback_).Run(nullptr);
+    }
   } else {
     url_request_job_->FallbackToNetwork();
   }
 }
 
 void ServiceWorkerURLJobWrapper::FallbackToNetworkOrRenderer() {
-  if (url_loader_) {
-    NOTIMPLEMENTED();
+  if (job_type_ == JobType::kURLLoader) {
+    // TODO(kinuko): Implement this. Now we always fallback to network.
+    FallbackToNetwork();
   } else {
     url_request_job_->FallbackToNetworkOrRenderer();
   }
 }
 
 void ServiceWorkerURLJobWrapper::ForwardToServiceWorker() {
-  if (url_loader_) {
-    NOTIMPLEMENTED();
+  if (job_type_ == JobType::kURLLoader) {
+    response_type_ = FORWARD_TO_SERVICE_WORKER;
+    StartRequest();
   } else {
     url_request_job_->ForwardToServiceWorker();
   }
 }
 
 bool ServiceWorkerURLJobWrapper::ShouldFallbackToNetwork() {
-  if (url_loader_) {
-    NOTIMPLEMENTED();
-    return false;
+  if (job_type_ == JobType::kURLLoader) {
+    return response_type_ == FALLBACK_TO_NETWORK;
   } else {
     return url_request_job_->ShouldFallbackToNetwork();
   }
 }
 
 ui::PageTransition ServiceWorkerURLJobWrapper::GetPageTransition() {
-  if (url_loader_) {
+  if (job_type_ == JobType::kURLLoader) {
     NOTIMPLEMENTED();
     return ui::PAGE_TRANSITION_LINK;
   } else {
@@ -73,7 +86,7 @@
 }
 
 size_t ServiceWorkerURLJobWrapper::GetURLChainSize() const {
-  if (url_loader_) {
+  if (job_type_ == JobType::kURLLoader) {
     NOTIMPLEMENTED();
     return 0;
   } else {
@@ -82,7 +95,7 @@
 }
 
 void ServiceWorkerURLJobWrapper::FailDueToLostController() {
-  if (url_loader_) {
+  if (job_type_ == JobType::kURLLoader) {
     NOTIMPLEMENTED();
   } else {
     url_request_job_->FailDueToLostController();
@@ -90,12 +103,20 @@
 }
 
 bool ServiceWorkerURLJobWrapper::WasCanceled() const {
-  if (url_loader_) {
-    NOTIMPLEMENTED();
-    return true;
+  if (job_type_ == JobType::kURLLoader) {
+    return loader_factory_callback_.is_null();
   } else {
     return !url_request_job_;
   }
 }
 
+void ServiceWorkerURLJobWrapper::StartRequest() {
+  DCHECK_EQ(FORWARD_TO_SERVICE_WORKER, response_type_);
+  // TODO(kinuko): Implement. For now we just exercise async fall back path
+  // to the network.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::Bind(&ServiceWorkerURLJobWrapper::FallbackToNetwork,
+                            weak_factory_.GetWeakPtr()));
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_url_job_wrapper.h b/content/browser/service_worker/service_worker_url_job_wrapper.h
index bfb21835..36b8626 100644
--- a/content/browser/service_worker/service_worker_url_job_wrapper.h
+++ b/content/browser/service_worker/service_worker_url_job_wrapper.h
@@ -6,19 +6,18 @@
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_JOB_WRAPPER_H_
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/service_worker/service_worker_response_type.h"
 #include "content/browser/service_worker/service_worker_url_request_job.h"
 
 namespace content {
 
-// TODO(scottmg): Not yet implemented. See https://crbug.com/715640.
-class ServiceWorkerControlleeURLLoader;
-
 // This class is a helper to support having
 // ServiceWorkerControlleeRequestHandler work with both URLRequestJobs and
 // mojom::URLLoaderFactorys (that is, both with and without
 // --enable-network-service). It wraps either a ServiceWorkerURLRequestJob or a
-// ServiceWorkerControlleeRequestHandler and forwards to the underlying
-// implementation.
+// callback for URLLoaderFactory and forwards to the underlying implementation.
 class ServiceWorkerURLJobWrapper {
  public:
   // Non-network service case.
@@ -26,8 +25,9 @@
       base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job);
 
   // With --enable-network-service.
-  explicit ServiceWorkerURLJobWrapper(
-      ServiceWorkerControlleeURLLoader* url_loader);
+  // TODO(kinuko): Implement this as a separate job class rather
+  // than in a wrapper.
+  ServiceWorkerURLJobWrapper(LoaderFactoryCallback loader_factory_callback);
 
   ~ServiceWorkerURLJobWrapper();
 
@@ -57,8 +57,21 @@
   bool WasCanceled() const;
 
  private:
+  enum class JobType { kURLRequest, kURLLoader };
+
+  // Used only for URLLoader case.
+  // TODO(kinuko): Implement this in a separate job class rather
+  // than in a wrapper.
+  void StartRequest();
+
+  JobType job_type_;
+
+  ServiceWorkerResponseType response_type_ = NOT_DETERMINED;
+  LoaderFactoryCallback loader_factory_callback_;
+
   base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job_;
-  ServiceWorkerControlleeURLLoader* url_loader_;
+
+  base::WeakPtrFactory<ServiceWorkerURLJobWrapper> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLJobWrapper);
 };
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h
index bd4a021..05c56d4 100644
--- a/content/browser/service_worker/service_worker_url_request_job.h
+++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/browser/service_worker/service_worker_response_type.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_event_dispatcher.mojom.h"
 #include "content/common/service_worker/service_worker_status_code.h"
@@ -153,13 +154,7 @@
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
                            LostActiveVersion);
 
-  enum ResponseType {
-    NOT_DETERMINED,
-    FAIL_DUE_TO_LOST_CONTROLLER,
-    FALLBACK_TO_NETWORK,
-    FALLBACK_TO_RENDERER,  // Use this when falling back with CORS check
-    FORWARD_TO_SERVICE_WORKER
-  };
+  using ResponseType = ServiceWorkerResponseType;
 
   enum ResponseBodyType {
     UNKNOWN,
diff --git a/content/common/service_worker/service_worker_provider_host_info.cc b/content/common/service_worker/service_worker_provider_host_info.cc
index 04a1887..d1cc98a 100644
--- a/content/common/service_worker/service_worker_provider_host_info.cc
+++ b/content/common/service_worker/service_worker_provider_host_info.cc
@@ -4,16 +4,35 @@
 
 #include "content/common/service_worker/service_worker_provider_host_info.h"
 
+#include "ipc/ipc_message.h"
+
 namespace content {
 
-ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo() {}
+namespace {
+
+void SetDefaultValues(ServiceWorkerProviderHostInfo* info) {
+  info->provider_id = kInvalidServiceWorkerProviderId;
+  info->route_id = MSG_ROUTING_NONE;
+  info->type = SERVICE_WORKER_PROVIDER_UNKNOWN;
+  info->is_parent_frame_secure = false;
+}
+
+}  // namespace
+
+ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo()
+    : provider_id(kInvalidServiceWorkerProviderId),
+      route_id(MSG_ROUTING_NONE),
+      type(SERVICE_WORKER_PROVIDER_UNKNOWN),
+      is_parent_frame_secure(false) {}
 
 ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo(
     ServiceWorkerProviderHostInfo&& other)
     : provider_id(other.provider_id),
       route_id(other.route_id),
       type(other.type),
-      is_parent_frame_secure(other.is_parent_frame_secure) {}
+      is_parent_frame_secure(other.is_parent_frame_secure) {
+  SetDefaultValues(&other);
+}
 
 ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo(
     int provider_id,
@@ -27,4 +46,15 @@
 
 ServiceWorkerProviderHostInfo::~ServiceWorkerProviderHostInfo() {}
 
+ServiceWorkerProviderHostInfo& ServiceWorkerProviderHostInfo::operator=(
+    ServiceWorkerProviderHostInfo&& other) {
+  provider_id = other.provider_id;
+  route_id = other.route_id;
+  type = other.type;
+  is_parent_frame_secure = other.is_parent_frame_secure;
+
+  SetDefaultValues(&other);
+  return *this;
+}
+
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_provider_host_info.h b/content/common/service_worker/service_worker_provider_host_info.h
index 106fb62..b89e2cdf 100644
--- a/content/common/service_worker/service_worker_provider_host_info.h
+++ b/content/common/service_worker/service_worker_provider_host_info.h
@@ -9,6 +9,7 @@
 
 namespace content {
 
+// Container object to create a ServiceWorkerProviderHost.
 struct CONTENT_EXPORT ServiceWorkerProviderHostInfo {
   ServiceWorkerProviderHostInfo();
   ServiceWorkerProviderHostInfo(ServiceWorkerProviderHostInfo&& other);
@@ -18,6 +19,9 @@
                                 bool is_parent_frame_secure);
   ~ServiceWorkerProviderHostInfo();
 
+  ServiceWorkerProviderHostInfo& operator=(
+      ServiceWorkerProviderHostInfo&& other);
+
   // This is unique within its child process except for PlzNavigate. When
   // PlzNavigate is on, |provider_id| is managed on the browser process and it
   // will be unique among all of providers.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index c6fb195..bcc2e91 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -472,6 +472,9 @@
   sources = [
     "data/web_ui_test_mojo_bindings.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 static_library("layouttest_support") {
diff --git a/device/bluetooth/public/interfaces/BUILD.gn b/device/bluetooth/public/interfaces/BUILD.gn
index 4ef85b8..0d2867d 100644
--- a/device/bluetooth/public/interfaces/BUILD.gn
+++ b/device/bluetooth/public/interfaces/BUILD.gn
@@ -8,6 +8,9 @@
   sources = [
     "uuid.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("fake_bluetooth_interfaces") {
@@ -20,6 +23,9 @@
   ]
 
   use_once_callback = true
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("experimental_interfaces") {
@@ -37,4 +43,7 @@
     "//chrome/browser:*",
     "//chrome/browser/ui:*",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/device/generic_sensor/public/interfaces/BUILD.gn b/device/generic_sensor/public/interfaces/BUILD.gn
index 24aabe84..bd043fd 100644
--- a/device/generic_sensor/public/interfaces/BUILD.gn
+++ b/device/generic_sensor/public/interfaces/BUILD.gn
@@ -19,4 +19,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/device/geolocation/public/interfaces/BUILD.gn b/device/geolocation/public/interfaces/BUILD.gn
index 1fcd5431..974c18e 100644
--- a/device/geolocation/public/interfaces/BUILD.gn
+++ b/device/geolocation/public/interfaces/BUILD.gn
@@ -11,4 +11,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/device/usb/public/interfaces/BUILD.gn b/device/usb/public/interfaces/BUILD.gn
index 2ff08c00..052c18a8 100644
--- a/device/usb/public/interfaces/BUILD.gn
+++ b/device/usb/public/interfaces/BUILD.gn
@@ -13,4 +13,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index be3ea9b..677d999a 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -133,4 +133,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index ef92f67..a5e96fe8 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -36,6 +36,9 @@
 
     # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
     use_once_callback = false
+
+    # TODO(crbug.com/699569): Convert to use the new JS bindings.
+    use_new_js_bindings = false
   }
 
   # This must be a static library because extensions common depends on
diff --git a/extensions/common/api/BUILD.gn b/extensions/common/api/BUILD.gn
index 8382c61e..3321a45 100644
--- a/extensions/common/api/BUILD.gn
+++ b/extensions/common/api/BUILD.gn
@@ -32,6 +32,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 group("api") {
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn
index c11f262..08dc472 100644
--- a/gpu/ipc/common/BUILD.gn
+++ b/gpu/ipc/common/BUILD.gn
@@ -154,6 +154,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("test_interfaces") {
diff --git a/ios/web/test/BUILD.gn b/ios/web/test/BUILD.gn
index 5ddfc4db..855ecb2b 100644
--- a/ios/web/test/BUILD.gn
+++ b/ios/web/test/BUILD.gn
@@ -10,6 +10,9 @@
   sources = [
     "mojo_test.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 repack("packed_resources") {
diff --git a/media/capture/mojo/BUILD.gn b/media/capture/mojo/BUILD.gn
index 2214c240..e862ea15 100644
--- a/media/capture/mojo/BUILD.gn
+++ b/media/capture/mojo/BUILD.gn
@@ -23,4 +23,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/media/midi/midi_service.cc b/media/midi/midi_service.cc
index 160f7ae7..4567a360 100644
--- a/media/midi/midi_service.cc
+++ b/media/midi/midi_service.cc
@@ -53,16 +53,22 @@
 
 void MidiService::Shutdown() {
   base::AutoLock lock(lock_);
-  if (manager_.get())
+  if (manager_) {
     manager_->Shutdown();
+    if (is_dynamic_instantiation_enabled_)
+      manager_destructor_runner_->DeleteSoon(FROM_HERE, std::move(manager_));
+    manager_destructor_runner_ = nullptr;
+  }
 }
 
 void MidiService::StartSession(MidiManagerClient* client) {
   base::AutoLock lock(lock_);
-  if (!manager_.get()) {
+  if (!manager_) {
     CHECK(is_dynamic_instantiation_enabled_);
     CHECK_EQ(0u, active_clients_);
     manager_.reset(MidiManager::Create(this));
+    if (!manager_destructor_runner_)
+      manager_destructor_runner_ = base::ThreadTaskRunnerHandle::Get();
   }
   active_clients_++;
   manager_->StartSession(client);
@@ -70,16 +76,21 @@
 
 void MidiService::EndSession(MidiManagerClient* client) {
   base::AutoLock lock(lock_);
-  CHECK(manager_.get());
   CHECK_NE(0u, active_clients_);
-  manager_->EndSession(client);
   active_clients_--;
+
+  // Do nothing if MidiService::Shutdown() already runs.
+  if (!manager_)
+    return;
+
+  manager_->EndSession(client);
   if (is_dynamic_instantiation_enabled_ && !active_clients_) {
     // MidiManager for each platform should be able to shutdown correctly even
     // if following Shutdown() call happens in the middle of
     // StartInitialization() to support the dynamic instantiation feature.
     manager_->Shutdown();
     manager_.reset();
+    manager_destructor_runner_ = nullptr;
   }
 }
 
@@ -96,7 +107,7 @@
   base::AutoLock lock(threads_lock_);
   if (threads_.size() <= runner_id)
     threads_.resize(runner_id + 1);
-  if (!threads_[runner_id].get()) {
+  if (!threads_[runner_id]) {
     threads_[runner_id] = base::MakeUnique<base::Thread>(
         base::StringPrintf("MidiServiceThread(%zu)", runner_id));
 #if defined(OS_WIN)
diff --git a/media/midi/midi_service.h b/media/midi/midi_service.h
index 722d5e6..3017b86 100644
--- a/media/midi/midi_service.h
+++ b/media/midi/midi_service.h
@@ -62,6 +62,9 @@
   // thread, and all MidiManager methods would be called on the I/O thread.
   std::unique_ptr<MidiManager> manager_;
 
+  // TaskRunner to destruct |manager_| on the right thread.
+  scoped_refptr<base::SingleThreadTaskRunner> manager_destructor_runner_;
+
   // A flag to indicate if the dynamic instantiation feature is supported and
   // actually enabled.
   const bool is_dynamic_instantiation_enabled_;
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index ac0cac6..4e57a46e 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -24,6 +24,9 @@
     "values.mojom",
     "version.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 component("common_base") {
diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn
index a805d3aba..21c9bfc4 100644
--- a/mojo/edk/js/tests/BUILD.gn
+++ b/mojo/edk/js/tests/BUILD.gn
@@ -48,6 +48,9 @@
   sources = [
     "js_to_cpp.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 test("mojo_js_unittests") {
diff --git a/mojo/public/interfaces/bindings/BUILD.gn b/mojo/public/interfaces/bindings/BUILD.gn
index 650e8bf7e..3bd98de 100644
--- a/mojo/public/interfaces/bindings/BUILD.gn
+++ b/mojo/public/interfaces/bindings/BUILD.gn
@@ -19,6 +19,8 @@
   export_class_attribute_shared = "MOJO_CPP_BINDINGS_EXPORT"
   export_define_shared = "MOJO_CPP_BINDINGS_IMPLEMENTATION"
   export_header_shared = "mojo/public/cpp/bindings/bindings_export.h"
+
+  use_new_js_bindings = false
 }
 
 # TODO(yzshen): Remove this target and use the one above once
@@ -29,6 +31,4 @@
     "new_bindings/interface_control_messages.mojom",
     "new_bindings/pipe_control_messages.mojom",
   ]
-
-  use_new_js_bindings = true
 }
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index 9cd84d4..17f1f1b2 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -69,7 +69,6 @@
     ":test_mojom_import",
     ":test_mojom_import2",
   ]
-  use_new_js_bindings = true
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
@@ -109,7 +108,6 @@
   if (!is_ios) {
     visibility_blink = [ ":test_export_blink_component" ]
   }
-  use_new_js_bindings = true
 }
 
 mojom("test_exported_import") {
@@ -127,7 +125,6 @@
     overridden_deps_blink = [ ":test_export" ]
     component_deps_blink = [ ":test_export_blink_component" ]
   }
-  use_new_js_bindings = true
 }
 
 # Used to test that it is okay to call mojom::Foo::Serialize()/Deserialize()
@@ -153,7 +150,6 @@
   export_define = "MOJO_TEST_IMPLEMENTATION=1"
   export_header = "mojo/public/cpp/bindings/tests/mojo_test_export.h"
   visibility = [ ":test_export_component2" ]
-  use_new_js_bindings = true
 }
 
 mojom("test_mojom_import") {
@@ -161,7 +157,6 @@
   sources = [
     "sample_import.mojom",
   ]
-  use_new_js_bindings = true
 }
 
 mojom("test_mojom_import_wrapper") {
@@ -187,7 +182,6 @@
     ":test_mojom_import",
     ":test_mojom_import_wrapper_wrapper",
   ]
-  use_new_js_bindings = true
 }
 
 mojom("test_struct_traits_interfaces") {
@@ -196,8 +190,6 @@
     "struct_with_traits.mojom",
   ]
 
-  use_new_js_bindings = true
-
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
 }
@@ -215,8 +207,6 @@
     ":test_interfaces",
   ]
 
-  use_new_js_bindings = true
-
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
 }
@@ -226,7 +216,6 @@
   sources = [
     "versioning_test_service.mojom",
   ]
-  use_new_js_bindings = true
 }
 
 mojom("versioning_test_client_interfaces") {
@@ -234,7 +223,6 @@
   sources = [
     "versioning_test_client.mojom",
   ]
-  use_new_js_bindings = true
 }
 
 mojom("test_wtf_types") {
@@ -244,8 +232,6 @@
     "test_wtf_types.mojom",
   ]
 
-  use_new_js_bindings = true
-
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
 }
@@ -264,5 +250,4 @@
     "echo.mojom",
     "echo_import.mojom",
   ]
-  use_new_js_bindings = true
 }
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index 1d3b81b..8708e7a 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -149,9 +149,9 @@
 #   use_new_js_bindings (optional)
 #       If set to true, the generated JS code will use the new module loading
 #       approach and the core API exposed by Web IDL.
-#
-#       TODO(yzshen): Switch all existing users to use_new_js_bindings=true and
-#       remove the old mode.
+#       Default value is true.
+#       TODO(yzshen): Convert all users to use new JS bindings and remove the
+#       old mode.
 #
 #   component_output_prefix (optional)
 #       The prefix to use for the output_name of any component library emitted
@@ -625,7 +625,7 @@
           args += [ "--use_once_callback" ]
         }
 
-        if (defined(invoker.use_new_js_bindings) &&
+        if (!defined(invoker.use_new_js_bindings) ||
             invoker.use_new_js_bindings) {
           args += [ "--use_new_js_bindings" ]
         }
diff --git a/net/interfaces/BUILD.gn b/net/interfaces/BUILD.gn
index 65910368..20363ec9 100644
--- a/net/interfaces/BUILD.gn
+++ b/net/interfaces/BUILD.gn
@@ -13,4 +13,7 @@
   public_deps = [
     "//url/mojo:url_mojom_gurl",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn
index c4f0a6fd..ae3247b 100644
--- a/services/device/public/interfaces/BUILD.gn
+++ b/services/device/public/interfaces/BUILD.gn
@@ -22,10 +22,16 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("constants") {
   sources = [
     "constants.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/services/service_manager/public/interfaces/BUILD.gn b/services/service_manager/public/interfaces/BUILD.gn
index d41f259e..9cf87d8 100644
--- a/services/service_manager/public/interfaces/BUILD.gn
+++ b/services/service_manager/public/interfaces/BUILD.gn
@@ -25,6 +25,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom_component("constants") {
@@ -33,4 +36,7 @@
   sources = [
     "constants.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/services/shape_detection/public/interfaces/BUILD.gn b/services/shape_detection/public/interfaces/BUILD.gn
index 7b09d0cd..22266aec 100644
--- a/services/shape_detection/public/interfaces/BUILD.gn
+++ b/services/shape_detection/public/interfaces/BUILD.gn
@@ -19,4 +19,7 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 1d2c0df7..f2491d8 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -3035,3 +3035,8 @@
 crbug.com/725455 [ Linux ] nfc/push.html [ Failure Pass Timeout ]
 crbug.com/725455 [ Linux ] nfc/watch.html [ Failure Pass Timeout ]
 crbug.com/725585 payments/payment-request-interface.html [ Failure Pass ]
+
+# Sheriff failure 2017-05-29
+crbug.com/727014 [ Linux ] external/wpt/IndexedDB/large-nested-cloning.html [ Pass Timeout ]
+crbug.com/727252 [ Win7 ] external/wpt/media-source/mediasource-endofstream.html [ Pass Timeout ]
+crbug.com/727257 [ Mac10.11 ] svg/animations/animate-local-url.html [ Pass Failure ]
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl
index 40ee4e918..e5ee163ef0 100644
--- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl
@@ -12,6 +12,7 @@
 
 class CSSValue;
 class CSSParserContext;
+class CSSParserLocalContext;
 class CSSParserTokenRange;
 
 // Base class for property APIs that contain logic for handling individual
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl
index eb0fb71..b6c1b68 100644
--- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl
@@ -12,6 +12,7 @@
 
 class CSSParserTokenRange;
 class CSSParserContext;
+class CSSParserLocalContext;
 
 // {{api_classname}} is the API that contains logic
 // for handling the {{property_name}} property.
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyDescriptor.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyDescriptor.h.tmpl
index 33f5a67..d85fc2a 100644
--- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyDescriptor.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyDescriptor.h.tmpl
@@ -9,6 +9,7 @@
 class CSSValue;
 class CSSParserTokenRange;
 class CSSParserContext;
+class CSSParserLocalContext;
 
 // Stores function pointers matching those declared in CSSPropertyAPI.
 struct CSSPropertyDescriptor {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
index c2f8ffcc..c4a337c 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.cpp
@@ -11,7 +11,7 @@
 CSSParserLocalContext::CSSParserLocalContext(bool use_alias_parsing)
     : use_alias_parsing_(use_alias_parsing) {}
 
-bool CSSParserLocalContext::GetUseAliasParsing() {
+bool CSSParserLocalContext::GetUseAliasParsing() const {
   return use_alias_parsing_;
 }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
index 952dbcb..6240c75 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserLocalContext.h
@@ -18,7 +18,7 @@
  public:
   CSSParserLocalContext();
   explicit CSSParserLocalContext(bool use_alias_parsing);
-  bool GetUseAliasParsing();
+  bool GetUseAliasParsing() const;
 
  private:
   bool use_alias_parsing_;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 0388e82..43e2c01 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -35,6 +35,7 @@
 #include "core/css/HashTools.h"
 #include "core/css/parser/CSSParserFastPaths.h"
 #include "core/css/parser/CSSParserIdioms.h"
+#include "core/css/parser/CSSParserLocalContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/CSSVariableParser.h"
 #include "core/css/parser/FontVariantLigaturesParser.h"
@@ -1629,8 +1630,9 @@
   const CSSPropertyDescriptor& css_property_desc =
       CSSPropertyDescriptor::Get(property);
   if (css_property_desc.parseSingleValue) {
-    return css_property_desc.parseSingleValue(range_, *context_,
-                                              unresolved_property);
+    return css_property_desc.parseSingleValue(
+        range_, *context_,
+        CSSParserLocalContext(unresolved_property != property));
   }
 
   switch (property) {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignItems.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignItems.cpp
index 4b2385b9..5238191 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignItems.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignItems.cpp
@@ -8,12 +8,13 @@
 #include "core/css/properties/CSSPropertyAlignmentUtils.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIAlignItems::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssGridLayoutEnabled());
   // align-items property does not allow the 'auto' value.
   if (CSSPropertyParserHelpers::IdentMatches<CSSValueAuto>(range.Peek().Id()))
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifyContent.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifyContent.cpp
index 923afea..3a09d3a 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifyContent.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifyContent.cpp
@@ -7,12 +7,13 @@
 #include "core/css/properties/CSSPropertyAlignmentUtils.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIAlignOrJustifyContent::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssGridLayoutEnabled());
   return CSSPropertyAlignmentUtils::ConsumeContentDistributionOverflowPosition(
       range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifySelf.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifySelf.cpp
index 2f6a6e7..6833498f 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifySelf.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIAlignOrJustifySelf.cpp
@@ -7,12 +7,13 @@
 #include "core/css/properties/CSSPropertyAlignmentUtils.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIAlignOrJustifySelf::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssGridLayoutEnabled());
   return CSSPropertyAlignmentUtils::ConsumeSelfPositionOverflowPosition(range);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBaselineShift.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBaselineShift.cpp
index ef6d8c56..64b5fe7 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBaselineShift.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBaselineShift.cpp
@@ -7,12 +7,13 @@
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIBaselineShift::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueBaseline || id == CSSValueSub || id == CSSValueSuper)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderRadius.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderRadius.cpp
index 836ade5..55b74b3 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderRadius.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIBorderRadius.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIBorderRadius::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValue* parsed_value1 = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
       range, context.Mode(), kValueRangeNonNegative);
   if (!parsed_value1)
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICaretColor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICaretColor.cpp
index e2391271..e1294952 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICaretColor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICaretColor.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPICaretColor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClip.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClip.cpp
index 37a1888c..7de4ec1 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClip.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClip.cpp
@@ -8,6 +8,7 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 namespace {
@@ -26,7 +27,7 @@
 const CSSValue* CSSPropertyAPIClip::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClipPath.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClipPath.cpp
index c6f45440..7a0f3e7 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClipPath.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIClipPath.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyShapeUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIClipPath::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   if (CSSURIValue* url = CSSPropertyParserHelpers::ConsumeUrl(range, &context))
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColor.cpp
index 52184c18..f4e299cf 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColor.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnCount.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnCount.cpp
index ec7aba6..961eb3c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnCount.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnCount.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyColumnUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColumnCount::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyColumnUtils::ConsumeColumnCount(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnGap.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnGap.cpp
index d9e69d5..103e097 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnGap.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnGap.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColumnGap::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNormal)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeLength(range, context.Mode(),
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnRuleWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnRuleWidth.cpp
index e4fd5ee..4d412cb9 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnRuleWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnRuleWidth.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColumnRuleWidth::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLineWidth(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnSpan.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnSpan.cpp
index ab6cc52..29073d21 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnSpan.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnSpan.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColumnSpan::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeIdent<CSSValueAll, CSSValueNone>(
       range);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnWidth.cpp
index 91f3b111..320fa3e 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIColumnWidth.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyColumnUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIColumnWidth::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyColumnUtils::ConsumeColumnWidth(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContain.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContain.cpp
index 4acd895..bd5c68b5 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContain.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContain.cpp
@@ -8,13 +8,14 @@
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 // none | strict | content | [ layout || style || paint || size ]
 const CSSValue* CSSPropertyAPIContain::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp
index 1965964..b0f5ef2 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIContent.cpp
@@ -12,6 +12,7 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 using CSSCounterValue = cssvalue::CSSCounterValue;
@@ -74,7 +75,7 @@
 const CSSValue* CSSPropertyAPIContent::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (CSSPropertyParserHelpers::IdentMatches<CSSValueNone, CSSValueNormal>(
           range.Peek().Id()))
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterIncrement.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterIncrement.cpp
index 308ccfd..1f0db5c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterIncrement.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterIncrement.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyCounterUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPICounterIncrement::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext&,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyCounterUtils::ConsumeCounter(
       range, CSSPropertyCounterUtils::kIncrementDefaultValue);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterReset.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterReset.cpp
index c2c3b1b..0319668 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterReset.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICounterReset.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyCounterUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPICounterReset::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext&,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyCounterUtils::ConsumeCounter(
       range, CSSPropertyCounterUtils::kResetDefaultValue);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICursor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICursor.cpp
index 48dea9ca..9f01751 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICursor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPICursor.cpp
@@ -11,6 +11,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/frame/UseCounter.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 using CSSCursorImageValue = cssvalue::CSSCursorImageValue;
@@ -18,7 +19,7 @@
 const CSSValue* CSSPropertyAPICursor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   bool in_quirks_mode = IsQuirksModeBehavior(context.Mode());
   CSSValueList* list = nullptr;
   while (CSSValue* image = CSSPropertyParserHelpers::ConsumeImage(
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPID.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPID.cpp
index 3246bb7c..3ebb1c5 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPID.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPID.cpp
@@ -6,11 +6,14 @@
 
 #include "core/css/properties/CSSPropertyOffsetPathUtils.h"
 
+class CSSParserLocalContext;
+
 namespace blink {
 
-const CSSValue* CSSPropertyAPID::parseSingleValue(CSSParserTokenRange& range,
-                                                  const CSSParserContext&,
-                                                  CSSPropertyID) {
+const CSSValue* CSSPropertyAPID::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
   return CSSPropertyOffsetPathUtils::ConsumePathOrNone(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFlexBasis.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFlexBasis.cpp
index c7fdb0c..758a3725 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFlexBasis.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFlexBasis.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFlexBasis::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   // FIXME: Support intrinsic dimensions too.
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFamily.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFamily.cpp
index ae5dde1..398c0d1 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFamily.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFamily.cpp
@@ -9,12 +9,13 @@
 
 class CSSParserContext;
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontFamily::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext&,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyFontUtils::ConsumeFontFamily(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFeatureSettings.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFeatureSettings.cpp
index 5aae820..89ed3530 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFeatureSettings.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontFeatureSettings.cpp
@@ -8,12 +8,13 @@
 
 class CSSParserContext;
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontFeatureSettings::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext&,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyFontUtils::ConsumeFontFeatureSettings(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSize.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSize.cpp
index 4a76f51e..8fb79c6 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSize.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSize.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyFontUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontSize::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyFontUtils::ConsumeFontSize(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kAllow);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSizeAdjust.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSizeAdjust.cpp
index 05cc934..f461265 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSizeAdjust.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontSizeAdjust.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontSizeAdjust::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssFontSizeAdjustEnabled());
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantCaps.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantCaps.cpp
index 9008d9a..7d8f736 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantCaps.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantCaps.cpp
@@ -7,12 +7,13 @@
 #include "core/CSSValueKeywords.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontVariantCaps::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeIdent<
       CSSValueNormal, CSSValueSmallCaps, CSSValueAllSmallCaps,
       CSSValuePetiteCaps, CSSValueAllPetiteCaps, CSSValueUnicase,
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantLigatures.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantLigatures.cpp
index 684f851..0cb7f5c3 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantLigatures.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantLigatures.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/FontVariantLigaturesParser.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontVariantLigatures::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNormal || range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantNumeric.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantNumeric.cpp
index b3cb4ef2..113bd5d 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantNumeric.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariantNumeric.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/FontVariantNumericParser.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIFontVariantNumeric::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNormal)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariationSettings.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariationSettings.cpp
index 7daf99b..60a17e7 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariationSettings.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFontVariationSettings.cpp
@@ -10,6 +10,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 namespace {
@@ -44,7 +45,7 @@
 const CSSValue* CSSPropertyAPIFontVariationSettings::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssVariableFontsEnabled());
   if (range.Peek().Id() == CSSValueNormal)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFragmentation.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFragmentation.cpp
index acf3785..18d0942 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFragmentation.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIFragmentation.cpp
@@ -4,11 +4,12 @@
 #include "core/css/properties/CSSPropertyAPIFragmentation.h"
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
+class CSSParserLocalContext;
 namespace blink {
 const CSSValue* CSSPropertyAPIFragmentation::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumePositiveInteger(range);
 }
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridAutoFlow.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridAutoFlow.cpp
index 50847547..5cf72297 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridAutoFlow.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIGridAutoFlow.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIGridAutoFlow::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssGridLayoutEnabled());
   CSSIdentifierValue* row_or_column_value =
       CSSPropertyParserHelpers::ConsumeIdent<CSSValueRow, CSSValueColumn>(
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImage.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImage.cpp
index b442976..867d6dc 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImage.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImage.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIImage::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeImageOrNone(range, &context);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImageOrientation.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImageOrientation.cpp
index 835eb278..a55dbf1 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImageOrientation.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIImageOrientation.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIImageOrientation::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::imageOrientationEnabled());
   if (range.Peek().Id() == CSSValueFromImage)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIJustifyItems.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIJustifyItems.cpp
index 179b71b2..eb288d5 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIJustifyItems.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIJustifyItems.cpp
@@ -9,12 +9,13 @@
 #include "core/css/properties/CSSPropertyAlignmentUtils.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIJustifyItems::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssGridLayoutEnabled());
   CSSParserTokenRange range_copy = range;
   CSSIdentifierValue* legacy =
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILetterAndWordSpacing.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILetterAndWordSpacing.cpp
index a7ad107..8c6d3ab 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILetterAndWordSpacing.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILetterAndWordSpacing.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPILetterAndWordSpacing::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNormal)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   // TODO(timloh): allow <percentage>s in word-spacing.
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeight.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeight.cpp
index efbf6b23..0cdb07d1 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeight.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeight.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/properties/CSSPropertyFontUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPILineHeight::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyFontUtils::ConsumeLineHeight(range, context.Mode());
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeightStep.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeightStep.cpp
index 1f9723f..6e63caf 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeightStep.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPILineHeightStep.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPILineHeightStep::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLength(range, context.Mode(),
                                                  kValueRangeNonNegative);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMargin.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMargin.cpp
index 8935baa..862b5d2c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMargin.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMargin.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyMarginUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIMargin::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyMarginUtils::ConsumeMarginOrOffset(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kAllow);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5 b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
index f146476f..f4d2e4ab 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIMethods.json5
@@ -29,7 +29,7 @@
     {
       name: "parseSingleValue",
       return_type: "const CSSValue*",
-      parameters: "(CSSParserTokenRange&, const CSSParserContext&, CSSPropertyID)",
+      parameters: "(CSSParserTokenRange&, const CSSParserContext&, const CSSParserLocalContext&)",
       description: "Parses a single CSS property and returns the corresponding CSSValue. If the input is invalid it returns nullptr.",
     },
     {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetAnchor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetAnchor.cpp
index 00374dc..bf605632 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetAnchor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetAnchor.cpp
@@ -9,6 +9,7 @@
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 using namespace CSSPropertyParserHelpers;
@@ -16,7 +17,7 @@
 const CSSValue* CSSPropertyAPIOffsetAnchor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueAuto)
     return ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPath.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPath.cpp
index 2d4e00d2..bb10b5c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPath.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPath.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyOffsetPathUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOffsetPath::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyOffsetPathUtils::ConsumeOffsetPath(range, &context);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPosition.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPosition.cpp
index 6aa6214..ad45dccf 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPosition.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOffsetPosition.cpp
@@ -9,6 +9,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/frame/UseCounter.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 using namespace CSSPropertyParserHelpers;
@@ -16,7 +17,7 @@
 const CSSValue* CSSPropertyAPIOffsetPosition::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueAuto)
     return ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOpacity.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOpacity.cpp
index 2c921037..19999c8 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOpacity.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOpacity.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOpacity::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeAll);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOrder.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOrder.cpp
index efc444b6..c0f463a0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOrder.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOrder.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOrder::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeInteger(range);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineColor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineColor.cpp
index 15ff243e..a0d1e19 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineColor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineColor.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOutlineColor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   // Allow the special focus color even in HTML Standard parsing mode.
   if (range.Peek().Id() == CSSValueWebkitFocusRingColor)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineOffset.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineOffset.cpp
index bf71a8c..1b6b738 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineOffset.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineOffset.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOutlineOffset::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLength(range, context.Mode(),
                                                  kValueRangeAll);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineWidth.cpp
index 50f06fb..3e364a8 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIOutlineWidth.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIOutlineWidth::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLineWidth(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp
index c9989cd..98a2f02 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPadding.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIPadding::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return ConsumeLengthOrPercent(
       range, context.Mode(), kValueRangeNonNegative,
       CSSPropertyParserHelpers::UnitlessQuirk::kAllow);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPage.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPage.cpp
index 27b81a45..c3fc145c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPage.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPage.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIPage::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeCustomIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintOrder.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintOrder.cpp
index aeadd43..33ec704 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintOrder.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintOrder.cpp
@@ -7,12 +7,13 @@
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIPaintOrder::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNormal)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintStroke.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintStroke.cpp
index 7e94d6d..6dfae70 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintStroke.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIPaintStroke.cpp
@@ -10,12 +10,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIPaintStroke::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   CSSURIValue* url = CSSPropertyParserHelpers::ConsumeUrl(range, &context);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIQuotes.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIQuotes.cpp
index 6eeca161..55fb7f2 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIQuotes.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIQuotes.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIQuotes::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   CSSValueList* values = CSSValueList::CreateSpaceSeparated();
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp
index e30f2d76..fe4bcdf 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRadius.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIRadius::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeLengthOrPercent(
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRotate.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRotate.cpp
index cb1583c..a0ed5a0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRotate.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIRotate.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIRotate::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssIndependentTransformPropertiesEnabled());
 
   CSSValueID id = range.Peek().Id();
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScale.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScale.cpp
index bb5a6b4..0179056 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScale.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScale.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIScale::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssIndependentTransformPropertiesEnabled());
 
   CSSValueID id = range.Peek().Id();
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScrollSnapCoordinate.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScrollSnapCoordinate.cpp
index 45e93d5..bc15860 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScrollSnapCoordinate.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIScrollSnapCoordinate.cpp
@@ -11,6 +11,7 @@
 
 // TODO(crbug.com/724912): Retire scroll-snap-coordinate
 
+class CSSParserLocalContext;
 namespace blink {
 
 using namespace CSSPropertyParserHelpers;
@@ -31,7 +32,7 @@
 const CSSValue* CSSPropertyAPIScrollSnapCoordinate::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNone)
     return ConsumeIdent(range);
   return ConsumePositionList(range, context);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeImageThreshold.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeImageThreshold.cpp
index c9a957d..02104532 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeImageThreshold.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeImageThreshold.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIShapeImageThreshold::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeAll);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp
index 1868b71..8327afe 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeMargin.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIShapeMargin::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLengthOrPercent(
       range, context.Mode(), kValueRangeNonNegative);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeOutside.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeOutside.cpp
index c71e79e0..dfeb9ef 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeOutside.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIShapeOutside.cpp
@@ -9,6 +9,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyShapeUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 using namespace CSSPropertyParserHelpers;
@@ -16,7 +17,7 @@
 const CSSValue* CSSPropertyAPIShapeOutside::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (CSSValue* image_value = ConsumeImageOrNone(range, &context))
     return image_value;
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPISize.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPISize.cpp
index 51012c6..400c038f 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPISize.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPISize.cpp
@@ -8,6 +8,7 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 static CSSValue* ConsumePageSize(CSSParserTokenRange& range) {
@@ -19,7 +20,7 @@
 const CSSValue* CSSPropertyAPISize::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueList* result = CSSValueList::CreateSpaceSeparated();
 
   if (range.Peek().Id() == CSSValueAuto) {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp
index b0213e2..aa011ae 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeDasharray.cpp
@@ -7,12 +7,13 @@
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIStrokeDasharray::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeMiterlimit.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeMiterlimit.cpp
index bc248c8..1bd9b70 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeMiterlimit.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeMiterlimit.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIStrokeMiterlimit::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeNumber(range, kValueRangeNonNegative);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp
index 0b814fe..032d194 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITabSize.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITabSize::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSPrimitiveValue* parsed_value =
       CSSPropertyParserHelpers::ConsumeInteger(range, 0);
   if (parsed_value)
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationColor.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationColor.cpp
index 879c7ff3..6ba259f 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationColor.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationColor.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITextDecorationColor::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
   return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp
index 3ac574bd..22a0db3f 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextDecorationSkip.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITextDecorationSkip::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   while (true) {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp
index a207714..20ddea2d 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextIndent.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITextIndent::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   // [ <length> | <percentage> ] && hanging? && each-line?
   // Keywords only allowed when css3Text is enabled.
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextSizeAdjust.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextSizeAdjust.cpp
index 0d35b57..07d6cf0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextSizeAdjust.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextSizeAdjust.cpp
@@ -7,12 +7,13 @@
 #include "core/CSSValueKeywords.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITextSizeAdjust::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   if (range.Peek().Id() == CSSValueNone)
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextUnderlinePosition.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextUnderlinePosition.cpp
index cbb0f43c7..82cf461c 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextUnderlinePosition.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITextUnderlinePosition.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITextUnderlinePosition::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   // auto | [ under || [ left | right ] ], but we only support auto | under
   // for now
   DCHECK(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITouchAction.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITouchAction.cpp
index 358d8ff..fc93b0a6 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITouchAction.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITouchAction.cpp
@@ -8,6 +8,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 namespace {
@@ -37,7 +38,7 @@
 const CSSValue* CSSPropertyAPITouchAction::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueManipulation) {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
index 6367c9e..c2bf72f0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransform.cpp
@@ -7,6 +7,7 @@
 #include "core/css/CSSFunctionValue.h"
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSParserLocalContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "platform/Length.h"
 
@@ -190,15 +191,14 @@
 const CSSValue* CSSPropertyAPITransform::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID unresolved_property) {
+    const CSSParserLocalContext& local_context) {
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
   CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   do {
     CSSValue* parsed_transform_value = ConsumeTransformValue(
-        range, &context,
-        unresolved_property == CSSPropertyAliasWebkitTransform);
+        range, &context, local_context.GetUseAliasParsing());
     if (!parsed_transform_value)
       return nullptr;
     list->Append(*parsed_transform_value);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransformOrigin.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransformOrigin.cpp
index 55efd29..ca2c0493 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransformOrigin.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITransformOrigin.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITransformOrigin::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValue* result_x = nullptr;
   CSSValue* result_y = nullptr;
   if (CSSPropertyParserHelpers::ConsumeOneOrTwoValuedPosition(
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITranslate.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITranslate.cpp
index db397b0..d9378a75 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITranslate.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPITranslate.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParser.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPITranslate::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   DCHECK(RuntimeEnabledFeatures::cssIndependentTransformPropertiesEnabled());
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueNone)
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIVerticalAlign.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIVerticalAlign.cpp
index 6146d016..6008c82 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIVerticalAlign.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIVerticalAlign.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIVerticalAlign::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValue* parsed_value = CSSPropertyParserHelpers::ConsumeIdentRange(
       range, CSSValueBaseline, CSSValueWebkitBaselineMiddle);
   if (!parsed_value) {
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderSpacing.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderSpacing.cpp
index 21a0f34..9c65a31 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderSpacing.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderSpacing.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitBorderSpacing::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLength(range, context.Mode(),
                                                  kValueRangeNonNegative);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderWidth.cpp
index 8cffddd..acaec2db 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBorderWidth.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyWebkitBorderWidthUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitBorderWidth::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyWebkitBorderWidthUtils::ConsumeBorderWidth(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp
index 1ea2171..bbdba80 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitBoxFlexGroup.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitBoxFlexGroup::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeInteger(range, 0);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitFontSizeDelta.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitFontSizeDelta.cpp
index d4f5336..9e2936b 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitFontSizeDelta.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitFontSizeDelta.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitFontSizeDelta::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLength(
       range, context.Mode(), kValueRangeAll,
       CSSPropertyParserHelpers::UnitlessQuirk::kAllow);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp
index 445223b..74c16d8 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitHighlight.cpp
@@ -7,12 +7,13 @@
 #include "core/css/CSSStringValue.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitHighlight::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeString(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp
index f4a1bcb..e2f2ef30 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitLineClamp.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitLineClamp::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().GetType() != kPercentageToken &&
       range.Peek().GetType() != kNumberToken)
     return nullptr;
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMargin.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMargin.cpp
index c6dbdd8..44dd936 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMargin.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMargin.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyMarginUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitMargin::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyMarginUtils::ConsumeMarginOrOffset(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMaxLogicalWidthOrHeight.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMaxLogicalWidthOrHeight.cpp
index d7c51772..12b66cb8 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMaxLogicalWidthOrHeight.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitMaxLogicalWidthOrHeight.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/properties/CSSPropertyLengthUtils.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitMaxLogicalWidthOrHeight::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyLengthUtils::ConsumeMaxWidthOrHeight(range, context);
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitPadding.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitPadding.cpp
index 760b3fed..b895ce7 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitPadding.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitPadding.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSParserTokenRange.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitPadding::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return ConsumeLengthOrPercent(
       range, context.Mode(), kValueRangeNonNegative,
       CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextEmphasisStyle.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextEmphasisStyle.cpp
index 5243694..fd55316 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextEmphasisStyle.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextEmphasisStyle.cpp
@@ -8,12 +8,13 @@
 #include "core/css/CSSValueList.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitTextEmphasisStyle::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   CSSValueID id = range.Peek().Id();
   if (id == CSSValueNone)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextStrokeWidth.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextStrokeWidth.cpp
index 9348210..7cd45b1 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextStrokeWidth.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTextStrokeWidth.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitTextStrokeWidth::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLineWidth(
       range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTransformOriginZ.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTransformOriginZ.cpp
index a0405564..6552851 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTransformOriginZ.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWebkitTransformOriginZ.cpp
@@ -7,12 +7,13 @@
 #include "core/css/parser/CSSParserContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWebkitTransformOriginZ::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   return CSSPropertyParserHelpers::ConsumeLength(range, context.Mode(),
                                                  kValueRangeAll);
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWillChange.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWillChange.cpp
index 4d59f3f91..6d4c40b9 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWillChange.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIWillChange.cpp
@@ -9,12 +9,13 @@
 #include "core/css/parser/CSSPropertyParser.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIWillChange::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZIndex.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZIndex.cpp
index b5fdecac..523532d 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZIndex.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZIndex.cpp
@@ -6,12 +6,13 @@
 
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIZIndex::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   if (range.Peek().Id() == CSSValueAuto)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
   return CSSPropertyParserHelpers::ConsumeInteger(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZoom.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZoom.cpp
index 2d94b6fb..5c8de41b 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZoom.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIZoom.cpp
@@ -8,12 +8,13 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/frame/UseCounter.h"
 
+class CSSParserLocalContext;
 namespace blink {
 
 const CSSValue* CSSPropertyAPIZoom::parseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
-    CSSPropertyID) {
+    const CSSParserLocalContext&) {
   const CSSParserToken& token = range.Peek();
   CSSValue* zoom = nullptr;
   if (token.GetType() == kIdentToken) {
diff --git a/third_party/WebKit/Source/core/dom/ClassList.cpp b/third_party/WebKit/Source/core/dom/ClassList.cpp
index 305ec56..31b4dbbe38 100644
--- a/third_party/WebKit/Source/core/dom/ClassList.cpp
+++ b/third_party/WebKit/Source/core/dom/ClassList.cpp
@@ -25,52 +25,11 @@
 
 #include "core/dom/ClassList.h"
 
-#include "core/dom/Document.h"
-#include "platform/wtf/PtrUtil.h"
-
 namespace blink {
 
-using namespace HTMLNames;
-
 ClassList::ClassList(Element* element)
     : DOMTokenList(nullptr), element_(element) {}
 
-unsigned ClassList::length() const {
-  return element_->HasClass() ? ClassNames().size() : 0;
-}
-
-const AtomicString ClassList::item(unsigned index) const {
-  if (index >= length())
-    return AtomicString();
-  return ClassNames()[index];
-}
-
-bool ClassList::ContainsInternal(const AtomicString& token) const {
-  return element_->HasClass() && ClassNames().Contains(token);
-}
-
-const SpaceSplitString& ClassList::ClassNames() const {
-  DCHECK(element_->HasClass());
-  if (element_->GetDocument().InQuirksMode()) {
-    if (!class_names_for_quirks_mode_) {
-      class_names_for_quirks_mode_ =
-          WTF::WrapUnique(new SpaceSplitString(value()));
-    }
-    return *class_names_for_quirks_mode_.get();
-  }
-  return element_->ClassNames();
-}
-
-SpaceSplitString& ClassList::MutableSet() {
-  // We can't mutate element_->ClassNames() because it is used to compare class
-  // names before/after class attribute change.
-  if (element_->HasClass())
-    mutable_set_ = ClassNames();
-  else
-    mutable_set_ = SpaceSplitString();
-  return mutable_set_;
-}
-
 DEFINE_TRACE(ClassList) {
   visitor->Trace(element_);
   DOMTokenList::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/dom/ClassList.h b/third_party/WebKit/Source/core/dom/ClassList.h
index db64716..d411f854 100644
--- a/third_party/WebKit/Source/core/dom/ClassList.h
+++ b/third_party/WebKit/Source/core/dom/ClassList.h
@@ -39,33 +39,16 @@
 class ClassList final : public DOMTokenList {
  public:
   static ClassList* Create(Element* element) { return new ClassList(element); }
-
-  unsigned length() const override;
-  const AtomicString item(unsigned index) const override;
-
-  void ClearValueForQuirksMode() { class_names_for_quirks_mode_ = nullptr; }
-
   DECLARE_VIRTUAL_TRACE();
 
  private:
   explicit ClassList(Element*);
 
-  bool ContainsInternal(const AtomicString&) const override;
-
-  const SpaceSplitString& ClassNames() const;
-  SpaceSplitString& MutableSet() override;
-
-  const AtomicString& value() const override {
-    return element_->getAttribute(HTMLNames::classAttr);
-  }
   void setValue(const AtomicString& value) override {
     element_->setAttribute(HTMLNames::classAttr, value);
-    mutable_set_.Clear();
   }
 
   Member<Element> element_;
-  mutable std::unique_ptr<SpaceSplitString> class_names_for_quirks_mode_;
-  SpaceSplitString mutable_set_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
index b68b08c..8e651e5 100644
--- a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
+++ b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
@@ -78,7 +78,7 @@
 
 // https://dom.spec.whatwg.org/#dom-domtokenlist-contains
 bool DOMTokenList::contains(const AtomicString& token) const {
-  return ContainsInternal(token);
+  return tokens_.Contains(token);
 }
 
 void DOMTokenList::add(const AtomicString& token,
@@ -126,7 +126,7 @@
   if (!ValidateToken(token, exception_state))
     return false;
 
-  if (ContainsInternal(token)) {
+  if (contains(token)) {
     RemoveInternal(token);
     return false;
   }
@@ -154,7 +154,7 @@
 }
 
 void DOMTokenList::AddInternal(const AtomicString& token) {
-  if (ContainsInternal(token))
+  if (contains(token))
     return;
   Vector<String> tokens;
   tokens.push_back(token.GetString());
@@ -163,7 +163,7 @@
 
 void DOMTokenList::RemoveInternal(const AtomicString& token) {
   // Check using contains first to skip unnecessary reserialization.
-  if (!ContainsInternal(token))
+  if (!contains(token))
     return;
   Vector<String> tokens;
   tokens.push_back(token.GetString());
@@ -172,22 +172,20 @@
 
 // https://dom.spec.whatwg.org/#dom-domtokenlist-add
 void DOMTokenList::AddTokens(const Vector<String>& tokens) {
-  SpaceSplitString& token_set = MutableSet();
   // 2. For each token in tokens, append token to context object’s token set.
   for (const auto& token : tokens)
-    token_set.Add(AtomicString(token));
+    tokens_.Add(AtomicString(token));
   // 3. Run the update steps.
-  UpdateWithTokenSet(token_set);
+  UpdateWithTokenSet(tokens_);
 }
 
 // https://dom.spec.whatwg.org/#dom-domtokenlist-remove
 void DOMTokenList::RemoveTokens(const Vector<String>& tokens) {
-  SpaceSplitString& token_set = MutableSet();
   // 2. For each token in tokens, remove token from context object’s token set.
   for (const auto& token : tokens)
-    token_set.Remove(AtomicString(token));
+    tokens_.Remove(AtomicString(token));
   // 3. Run the update steps.
-  UpdateWithTokenSet(token_set);
+  UpdateWithTokenSet(tokens_);
 }
 
 // https://dom.spec.whatwg.org/#concept-ordered-set-serializer
@@ -229,10 +227,6 @@
     tokens_.Set(new_value);
 }
 
-bool DOMTokenList::ContainsInternal(const AtomicString& token) const {
-  return tokens_.Contains(token);
-}
-
 const AtomicString DOMTokenList::item(unsigned index) const {
   if (index >= length())
     return AtomicString();
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.h b/third_party/WebKit/Source/core/dom/DOMTokenList.h
index d5e5377..5ef9f8d 100644
--- a/third_party/WebKit/Source/core/dom/DOMTokenList.h
+++ b/third_party/WebKit/Source/core/dom/DOMTokenList.h
@@ -57,19 +57,19 @@
 
   virtual ~DOMTokenList() {}
 
-  virtual unsigned length() const { return tokens_.size(); }
-  virtual const AtomicString item(unsigned index) const;
+  unsigned length() const { return tokens_.size(); }
+  const AtomicString item(unsigned index) const;
 
   bool contains(const AtomicString&) const;
-  virtual void add(const Vector<String>&, ExceptionState&);
+  void add(const Vector<String>&, ExceptionState&);
   void add(const AtomicString&, ExceptionState&);
-  virtual void remove(const Vector<String>&, ExceptionState&);
+  void remove(const Vector<String>&, ExceptionState&);
   void remove(const AtomicString&, ExceptionState&);
   bool toggle(const AtomicString&, ExceptionState&);
   bool toggle(const AtomicString&, bool force, ExceptionState&);
   bool supports(const AtomicString&, ExceptionState&);
 
-  virtual const AtomicString& value() const { return value_; }
+  const AtomicString& value() const { return value_; }
   // DOMTokenListObserver::ValueWasSet or setValue override should update the
   // associated attribute value.
   virtual void setValue(const AtomicString&);
@@ -89,16 +89,14 @@
  protected:
   DOMTokenList(DOMTokenListObserver* observer) : observer_(observer) {}
 
-  virtual void AddInternal(const AtomicString&);
-  virtual bool ContainsInternal(const AtomicString&) const;
-  virtual void RemoveInternal(const AtomicString&);
+  void AddInternal(const AtomicString&);
+  void RemoveInternal(const AtomicString&);
 
   bool ValidateToken(const String&, ExceptionState&) const;
   bool ValidateTokens(const Vector<String>&, ExceptionState&) const;
   virtual bool ValidateTokenValue(const AtomicString&, ExceptionState&) const;
   void AddTokens(const Vector<String>&);
   void RemoveTokens(const Vector<String>&);
-  virtual SpaceSplitString& MutableSet() { return tokens_; }
 
  private:
   void UpdateWithTokenSet(const SpaceSplitString&);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 4f428b56..92c8598 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -609,7 +609,8 @@
   } else if (imports_controller_) {
     fetcher_ = FrameFetchContext::CreateFetcherFromDocument(this);
   } else {
-    fetcher_ = ResourceFetcher::Create(nullptr);
+    fetcher_ = ResourceFetcher::Create(
+        nullptr, Platform::Current()->CurrentThread()->GetWebTaskRunner());
   }
   DCHECK(fetcher_);
 
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 6a54398..3f81b6d 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -1355,6 +1355,10 @@
     }
   } else if (name == classAttr) {
     ClassAttributeChanged(params.new_value);
+    if (HasRareData() && GetElementRareData()->GetClassList()) {
+      GetElementRareData()->GetClassList()->DidUpdateAttributeValue(
+          params.old_value, params.new_value);
+    }
   } else if (name == HTMLNames::nameAttr) {
     SetHasName(!params.new_value.IsNull());
   } else if (IsStyledElement()) {
@@ -1455,9 +1459,6 @@
     else
       GetElementData()->ClearClass();
   }
-
-  if (HasRareData())
-    GetElementRareData()->ClearClassListValueForQuirksMode();
 }
 
 bool Element::ShouldInvalidateDistributionWhenAttributeChanged(
@@ -1633,7 +1634,6 @@
 
   if (HasRareData()) {
     ElementRareData* rare_data = GetElementRareData();
-    rare_data->ClearClassListValueForQuirksMode();
     if (rare_data->IntersectionObserverData())
       rare_data->IntersectionObserverData()->ActivateValidIntersectionObservers(
           *this);
@@ -3510,8 +3510,12 @@
 
 DOMTokenList& Element::classList() {
   ElementRareData& rare_data = EnsureElementRareData();
-  if (!rare_data.GetClassList())
-    rare_data.SetClassList(ClassList::Create(this));
+  if (!rare_data.GetClassList()) {
+    ClassList* class_list = ClassList::Create(this);
+    class_list->DidUpdateAttributeValue(g_null_atom,
+                                        getAttribute(HTMLNames::classAttr));
+    rare_data.SetClassList(class_list);
+  }
   return *rare_data.GetClassList();
 }
 
@@ -4242,6 +4246,8 @@
 }
 
 bool Element::SupportsStyleSharing() const {
+  if (!RuntimeEnabledFeatures::styleSharingEnabled())
+    return false;
   if (!IsStyledElement() || !ParentOrShadowHostElement())
     return false;
   // If the element has inline style it is probably unique.
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.h b/third_party/WebKit/Source/core/dom/ElementRareData.h
index 921153f..1da0c8c 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.h
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.h
@@ -101,11 +101,6 @@
     class_list_ = class_list;
     ScriptWrappableVisitor::WriteBarrier(this, class_list_);
   }
-  void ClearClassListValueForQuirksMode() {
-    if (!class_list_)
-      return;
-    class_list_->ClearValueForQuirksMode();
-  }
 
   DatasetDOMStringMap* Dataset() const { return dataset_.Get(); }
   void SetDataset(DatasetDOMStringMap* dataset) {
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
index fadc5589..9ebfbdea 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -1088,6 +1088,8 @@
 
 void SpellChecker::PrepareForLeakDetection() {
   spell_check_requester_->PrepareForLeakDetection();
+  if (RuntimeEnabledFeatures::idleTimeSpellCheckingEnabled())
+    idle_spell_check_callback_->Deactivate();
 }
 
 Vector<TextCheckingResult> SpellChecker::FindMisspellings(const String& text) {
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn
index b81f073d..e4a5b6d 100644
--- a/third_party/WebKit/Source/core/frame/BUILD.gn
+++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -124,6 +124,8 @@
     "WebLocalFrameBase.h",
     "WebRemoteFrameBase.cpp",
     "WebRemoteFrameBase.h",
+    "WebViewFrameWidget.cpp",
+    "WebViewFrameWidget.h",
     "csp/CSPDirective.h",
     "csp/CSPDirectiveList.cpp",
     "csp/CSPDirectiveList.h",
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
similarity index 99%
rename from third_party/WebKit/Source/web/WebViewFrameWidget.cpp
rename to third_party/WebKit/Source/core/frame/WebViewFrameWidget.cpp
index 1cf162e..0314cb5a 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
+++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.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 "web/WebViewFrameWidget.h"
+#include "core/frame/WebViewFrameWidget.h"
 
 #include "core/exported/WebViewBase.h"
 #include "core/frame/WebLocalFrameBase.h"
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.h b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h
similarity index 97%
rename from third_party/WebKit/Source/web/WebViewFrameWidget.h
rename to third_party/WebKit/Source/core/frame/WebViewFrameWidget.h
index 3df2833ba..990b81c6 100644
--- a/third_party/WebKit/Source/web/WebViewFrameWidget.h
+++ b/third_party/WebKit/Source/core/frame/WebViewFrameWidget.h
@@ -5,6 +5,7 @@
 #ifndef WebViewFrameWidget_h
 #define WebViewFrameWidget_h
 
+#include "core/CoreExport.h"
 #include "core/frame/WebFrameWidgetBase.h"
 #include "core/frame/WebLocalFrameBase.h"
 #include "platform/heap/Handle.h"
@@ -31,7 +32,7 @@
 // into one class.
 // A more detailed writeup of this transition can be read at
 // https://goo.gl/7yVrnb.
-class WebViewFrameWidget : public WebFrameWidgetBase {
+class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
   WTF_MAKE_NONCOPYABLE(WebViewFrameWidget);
 
  public:
diff --git a/third_party/WebKit/Source/core/html/RelList.cpp b/third_party/WebKit/Source/core/html/RelList.cpp
index bae84e45..ac391bc 100644
--- a/third_party/WebKit/Source/core/html/RelList.cpp
+++ b/third_party/WebKit/Source/core/html/RelList.cpp
@@ -15,15 +15,6 @@
 
 RelList::RelList(Element* element) : DOMTokenList(nullptr), element_(element) {}
 
-unsigned RelList::length() const {
-  return !element_->FastGetAttribute(relAttr).IsEmpty() ? Tokens().size() : 0;
-}
-
-bool RelList::ContainsInternal(const AtomicString& token) const {
-  return !element_->FastGetAttribute(relAttr).IsEmpty() &&
-         Tokens().Contains(token);
-}
-
 static HashSet<AtomicString>& SupportedTokens() {
   DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tokens, ());
 
diff --git a/third_party/WebKit/Source/core/html/RelList.h b/third_party/WebKit/Source/core/html/RelList.h
index b22ab426..ff60b46d3 100644
--- a/third_party/WebKit/Source/core/html/RelList.h
+++ b/third_party/WebKit/Source/core/html/RelList.h
@@ -15,19 +15,11 @@
 class RelList final : public DOMTokenList {
  public:
   static RelList* Create(Element* element) { return new RelList(element); }
-
-  unsigned length() const override;
-
   DECLARE_VIRTUAL_TRACE();
 
  private:
   explicit RelList(Element*);
 
-  bool ContainsInternal(const AtomicString&) const override;
-
-  const AtomicString& value() const override {
-    return element_->getAttribute(HTMLNames::relAttr);
-  }
   void setValue(const AtomicString& value) override {
     element_->setAttribute(HTMLNames::relAttr, value);
   }
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index 0065c6e4..c0bc426e 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -194,6 +194,10 @@
   return frame;
 }
 
+RefPtr<WebTaskRunner> FrameFetchContext::GetTaskRunner() const {
+  return GetFrame()->FrameScheduler()->LoadingTaskRunner();
+}
+
 Document* FrameFetchContext::GetDocument() const {
   return document_;
 }
@@ -711,10 +715,6 @@
       ->Archive();
 }
 
-RefPtr<WebTaskRunner> FrameFetchContext::LoadingTaskRunner() const {
-  return GetFrame()->FrameScheduler()->LoadingTaskRunner();
-}
-
 ContentSettingsClient* FrameFetchContext::GetContentSettingsClient() const {
   return GetFrame()->GetContentSettingsClient();
 }
@@ -802,8 +802,11 @@
   return document_->AddConsoleMessage(message);
 }
 
-std::unique_ptr<WebURLLoader> FrameFetchContext::CreateURLLoader() {
-  return GetFrame()->CreateURLLoader();
+std::unique_ptr<WebURLLoader> FrameFetchContext::CreateURLLoader(
+    const ResourceRequest& request) {
+  auto loader = GetFrame()->CreateURLLoader();
+  loader->SetLoadingTaskRunner(GetTaskRunner().Get());
+  return loader;
 }
 
 DEFINE_TRACE(FrameFetchContext) {
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index 5257bf40..41749c210 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -51,15 +51,18 @@
 class LocalFrameClient;
 class ResourceError;
 class ResourceResponse;
+class WebTaskRunner;
 
 class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
  public:
   static ResourceFetcher* CreateFetcherFromDocumentLoader(
       DocumentLoader* loader) {
-    return ResourceFetcher::Create(new FrameFetchContext(loader, nullptr));
+    auto* context = new FrameFetchContext(loader, nullptr);
+    return ResourceFetcher::Create(context, context->GetTaskRunner());
   }
   static ResourceFetcher* CreateFetcherFromDocument(Document* document) {
-    return ResourceFetcher::Create(new FrameFetchContext(nullptr, document));
+    auto* context = new FrameFetchContext(nullptr, document);
+    return ResourceFetcher::Create(context, context->GetTaskRunner());
   }
 
   static void ProvideDocumentToContext(FetchContext&, Document*);
@@ -148,9 +151,8 @@
 
   MHTMLArchive* Archive() const override;
 
-  RefPtr<WebTaskRunner> LoadingTaskRunner() const override;
-
-  std::unique_ptr<WebURLLoader> CreateURLLoader() override;
+  std::unique_ptr<WebURLLoader> CreateURLLoader(
+      const ResourceRequest&) override;
 
   DECLARE_VIRTUAL_TRACE();
 
@@ -167,6 +169,7 @@
   LocalFrame* GetFrame() const;
   LocalFrameClient* GetLocalFrameClient() const;
   LocalFrame* FrameOfImportsController() const;
+  RefPtr<WebTaskRunner> GetTaskRunner() const;
 
   // BaseFetchContext overrides:
   ContentSettingsClient* GetContentSettingsClient() const override;
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index 02885150..85b173d5 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -61,6 +61,7 @@
 #include "platform/loader/fetch/UniqueIdentifier.h"
 #include "platform/network/EncodedFormData.h"
 #include "platform/network/ParsedContentType.h"
+#include "platform/scheduler/child/web_scheduler.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "platform/weborigin/SecurityPolicy.h"
 #include "platform/wtf/Compiler.h"
@@ -273,7 +274,9 @@
   if (frame->FrameScheduler())
     frame->FrameScheduler()->DidStopLoading(identifier_);
 
-  loader_ = fetch_context.CreateURLLoader();
+  loader_ = fetch_context.CreateURLLoader(request);
+  loader_->SetLoadingTaskRunner(
+      Platform::Current()->CurrentThread()->Scheduler()->LoadingTaskRunner());
   DCHECK(loader_);
   WrappedResourceRequest wrapped_request(request);
   wrapped_request.SetAllowStoredCredentials(credentials_allowed ==
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index 240f59d..fd4e51c 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -11,7 +11,6 @@
 #include "core/loader/ThreadableLoadingContext.h"
 #include "core/loader/WorkerThreadableLoader.h"
 #include "core/testing/DummyPageHolder.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "core/workers/WorkerThreadTestHelper.h"
 #include "platform/WaitableEvent.h"
@@ -170,8 +169,7 @@
   Persistent<DocumentThreadableLoader> loader_;
 };
 
-class WorkerThreadableLoaderTestHelper : public ThreadableLoaderTestHelper,
-                                         public WorkerLoaderProxyProvider {
+class WorkerThreadableLoaderTestHelper : public ThreadableLoaderTestHelper {
  public:
   WorkerThreadableLoaderTestHelper()
       : dummy_page_holder_(DummyPageHolder::Create(IntSize(1, 1))) {}
@@ -244,9 +242,8 @@
     security_origin_ = GetDocument().GetSecurityOrigin();
     parent_frame_task_runners_ =
         ParentFrameTaskRunners::Create(&dummy_page_holder_->GetFrame());
-    worker_thread_ =
-        WTF::WrapUnique(new WorkerThreadForTest(this, *reporting_proxy_));
-    loading_context_ = ThreadableLoadingContext::Create(GetDocument());
+    worker_thread_ = WTF::MakeUnique<WorkerThreadForTest>(
+        ThreadableLoadingContext::Create(GetDocument()), *reporting_proxy_);
 
     worker_thread_->StartWithSourceCode(security_origin_.Get(),
                                         "//fake source code",
@@ -273,8 +270,6 @@
     // Needed to clean up the things on the main thread side and
     // avoid Resource leaks.
     testing::RunPendingTasks();
-
-    worker_thread_->GetWorkerLoaderProxy()->DetachProvider(this);
   }
 
  private:
@@ -321,11 +316,6 @@
     event->Signal();
   }
 
-  // WorkerLoaderProxyProvider methods.
-  ThreadableLoadingContext* GetThreadableLoadingContext() override {
-    return loading_context_.Get();
-  }
-
   RefPtr<SecurityOrigin> security_origin_;
   std::unique_ptr<WorkerReportingProxy> reporting_proxy_;
   std::unique_ptr<WorkerThreadForTest> worker_thread_;
@@ -337,8 +327,6 @@
   Checkpoint checkpoint_;
   // |m_loader| must be touched only from the worker thread only.
   CrossThreadPersistent<ThreadableLoader> loader_;
-
-  Persistent<ThreadableLoadingContext> loading_context_;
 };
 
 class ThreadableLoaderTest
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
index e5f4ef6..1f38c934 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
@@ -52,6 +52,7 @@
   }
 
   RefPtr<WebTaskRunner> GetTaskRunner(TaskType type) override {
+    DCHECK(IsContextThread());
     return TaskRunnerHelper::Get(type, document_.Get());
   }
 
@@ -112,7 +113,8 @@
   Document* GetLoadingDocument() override { return nullptr; }
 
   RefPtr<WebTaskRunner> GetTaskRunner(TaskType type) override {
-    return fetch_context_->LoadingTaskRunner();
+    DCHECK(IsContextThread());
+    return fetch_context_->GetTaskRunner();
   }
 
   void RecordUseCount(UseCounter::Feature feature) override {
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index 54a62dd..e9ce483 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -91,7 +91,7 @@
 ResourceFetcher* WorkerFetchContext::GetResourceFetcher() {
   if (resource_fetcher_)
     return resource_fetcher_;
-  resource_fetcher_ = ResourceFetcher::Create(this);
+  resource_fetcher_ = ResourceFetcher::Create(this, loading_task_runner_);
   return resource_fetcher_;
 }
 
@@ -194,8 +194,11 @@
   return worker_global_scope_->GetSecurityOrigin();
 }
 
-std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader() {
-  return web_context_->CreateURLLoader();
+std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader(
+    const ResourceRequest&) {
+  auto loader = web_context_->CreateURLLoader();
+  loader->SetLoadingTaskRunner(loading_task_runner_.Get());
+  return loader;
 }
 
 bool WorkerFetchContext::IsControlledByServiceWorker() const {
@@ -209,10 +212,6 @@
   web_context_->WillSendRequest(webreq);
 }
 
-RefPtr<WebTaskRunner> WorkerFetchContext::LoadingTaskRunner() const {
-  return loading_task_runner_;
-}
-
 void WorkerFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
                                                      FetchResourceType type) {
   BaseFetchContext::AddAdditionalRequestHeaders(request, type);
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
index f4e6e1c..a4c9c63 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -34,6 +34,7 @@
 
   ResourceFetcher* GetResourceFetcher();
   KURL FirstPartyForCookies() const;
+  RefPtr<WebTaskRunner> GetTaskRunner() { return loading_task_runner_; }
 
   // BaseFetchContext implementation:
   ContentSettingsClient* GetContentSettingsClient() const override;
@@ -62,10 +63,10 @@
   // FetchContext implementation:
   // TODO(horo): Implement more methods.
   SecurityOrigin* GetSecurityOrigin() const override;
-  std::unique_ptr<WebURLLoader> CreateURLLoader() override;
+  std::unique_ptr<WebURLLoader> CreateURLLoader(
+      const ResourceRequest&) override;
   void PrepareRequest(ResourceRequest&, RedirectType) override;
   bool IsControlledByServiceWorker() const override;
-  RefPtr<WebTaskRunner> LoadingTaskRunner() const override;
 
   void AddAdditionalRequestHeaders(ResourceRequest&,
                                    FetchResourceType) override;
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
index a63be36a..be133459 100644
--- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
@@ -35,7 +35,6 @@
 #include "core/loader/ThreadableLoadingContext.h"
 #include "core/timing/WorkerGlobalScopePerformance.h"
 #include "core/workers/WorkerGlobalScope.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/heap/SafePoint.h"
 #include "platform/loader/fetch/ResourceError.h"
@@ -197,8 +196,6 @@
     const ResourceLoaderOptions& resource_loader_options,
     BlockingBehavior blocking_behavior)
     : worker_global_scope_(&worker_global_scope),
-      worker_loader_proxy_(
-          worker_global_scope.GetThread()->GetWorkerLoaderProxy()),
       parent_frame_task_runners_(
           worker_global_scope.GetThread()->GetParentFrameTaskRunners()),
       client_(client),
@@ -225,6 +222,7 @@
 }
 
 void WorkerThreadableLoader::Start(const ResourceRequest& original_request) {
+  DCHECK(worker_global_scope_->IsContextThread());
   ResourceRequest request(original_request);
   if (!request.DidSetHTTPReferrer()) {
     request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
@@ -232,24 +230,25 @@
         worker_global_scope_->OutgoingReferrer()));
   }
 
-  DCHECK(!IsMainThread());
   RefPtr<WaitableEventWithTasks> event_with_tasks;
   if (blocking_behavior_ == kLoadSynchronously)
     event_with_tasks = WaitableEventWithTasks::Create();
 
+  WorkerThread* worker_thread = worker_global_scope_->GetThread();
   RefPtr<WebTaskRunner> worker_loading_task_runner = TaskRunnerHelper::Get(
       TaskType::kUnspecedLoading, worker_global_scope_.Get());
   parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
       ->PostTask(
           BLINK_FROM_HERE,
-          CrossThreadBind(&MainThreadLoaderHolder::CreateAndStart,
-                          WrapCrossThreadPersistent(this), worker_loader_proxy_,
-                          std::move(worker_loading_task_runner),
-                          WrapCrossThreadPersistent(
-                              worker_global_scope_->GetThread()
-                                  ->GetWorkerThreadLifecycleContext()),
-                          request, threadable_loader_options_,
-                          resource_loader_options_, event_with_tasks));
+          CrossThreadBind(
+              &MainThreadLoaderHolder::CreateAndStart,
+              WrapCrossThreadPersistent(this),
+              WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
+              std::move(worker_loading_task_runner),
+              WrapCrossThreadPersistent(
+                  worker_thread->GetWorkerThreadLifecycleContext()),
+              request, threadable_loader_options_, resource_loader_options_,
+              event_with_tasks));
 
   if (blocking_behavior_ == kLoadAsynchronously)
     return;
@@ -437,7 +436,7 @@
 
 void WorkerThreadableLoader::MainThreadLoaderHolder::CreateAndStart(
     WorkerThreadableLoader* worker_loader,
-    RefPtr<WorkerLoaderProxy> loader_proxy,
+    ThreadableLoadingContext* loading_context,
     RefPtr<WebTaskRunner> worker_loading_task_runner,
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     std::unique_ptr<CrossThreadResourceRequestData> request,
@@ -446,10 +445,6 @@
     PassRefPtr<WaitableEventWithTasks> event_with_tasks) {
   DCHECK(IsMainThread());
   TaskForwarder* forwarder;
-  ThreadableLoadingContext* loading_context =
-      loader_proxy->GetThreadableLoadingContext();
-  if (!loading_context)
-    return;
   if (event_with_tasks)
     forwarder = new SyncTaskForwarder(std::move(event_with_tasks));
   else
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
index 10ec0f7..dc452388 100644
--- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
+++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
@@ -52,7 +52,6 @@
 class ResourceRequest;
 class ResourceResponse;
 class WorkerGlobalScope;
-class WorkerLoaderProxy;
 struct CrossThreadResourceRequestData;
 struct CrossThreadResourceTimingInfoData;
 
@@ -141,7 +140,7 @@
 
    public:
     static void CreateAndStart(WorkerThreadableLoader*,
-                               RefPtr<WorkerLoaderProxy>,
+                               ThreadableLoadingContext*,
                                RefPtr<WebTaskRunner>,
                                WorkerThreadLifecycleContext*,
                                std::unique_ptr<CrossThreadResourceRequestData>,
@@ -211,7 +210,6 @@
       std::unique_ptr<CrossThreadResourceTimingInfoData>);
 
   Member<WorkerGlobalScope> worker_global_scope_;
-  RefPtr<WorkerLoaderProxy> worker_loader_proxy_;
   CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
   ThreadableLoaderClient* client_;
 
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
index c9df0ba..15466a3 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -112,8 +112,9 @@
   platform_->AdvanceClockSeconds(1.);  // For non-zero DocumentParserTimings
   dummy_page_holder_ = DummyPageHolder::Create(IntSize(500, 500));
   GetDocument().SetURL(KURL(KURL(), "https://example.test"));
-  fetcher_ = ResourceFetcher::Create(
-      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource));
+  auto* context =
+      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
+  fetcher_ = ResourceFetcher::Create(context, context->GetTaskRunner().Get());
   modulator_ = new ModuleScriptLoaderTestModulator(
       ToScriptStateForMainWorld(&GetFrame()),
       GetDocument().GetSecurityOrigin());
diff --git a/third_party/WebKit/Source/core/loader/resource/FontResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/FontResourceTest.cpp
index 24abe79..0301696 100644
--- a/third_party/WebKit/Source/core/loader/resource/FontResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/FontResourceTest.cpp
@@ -46,7 +46,8 @@
 
   MockFetchContext* context =
       MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
-  ResourceFetcher* fetcher = ResourceFetcher::Create(context);
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(context, context->GetTaskRunner());
 
   // Fetch to cache a resource.
   ResourceRequest request1(url);
@@ -105,8 +106,11 @@
   Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
       url, WrappedResourceResponse(response), "");
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(
-      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource));
+  auto* context =
+      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
+
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(context, context->GetTaskRunner());
 
   FetchParameters fetch_params =
       FetchParameters(ResourceRequest(url), FetchInitiatorInfo());
diff --git a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
index 824365b7..e27e51fb 100644
--- a/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ImageResourceTest.cpp
@@ -337,8 +337,9 @@
 }
 
 ResourceFetcher* CreateFetcher() {
-  return ResourceFetcher::Create(
-      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource));
+  auto* context =
+      MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
+  return ResourceFetcher::Create(context, context->GetTaskRunner());
 }
 
 TEST(ImageResourceTest, MultipartImage) {
diff --git a/third_party/WebKit/Source/core/svg/properties/SVGListPropertyHelper.h b/third_party/WebKit/Source/core/svg/properties/SVGListPropertyHelper.h
index 072979f7..22f2279 100644
--- a/third_party/WebKit/Source/core/svg/properties/SVGListPropertyHelper.h
+++ b/third_party/WebKit/Source/core/svg/properties/SVGListPropertyHelper.h
@@ -91,11 +91,6 @@
   };
 
   ConstIterator begin() const { return ConstIterator(values_.begin()); }
-
-  ConstIterator LastAppended() const {
-    return ConstIterator(values_.begin() + values_.size() - 1);
-  }
-
   ConstIterator end() const { return ConstIterator(values_.end()); }
 
   void Append(ItemPropertyType* new_item) {
diff --git a/third_party/WebKit/Source/core/svg/properties/SVGPropertyTearOff.h b/third_party/WebKit/Source/core/svg/properties/SVGPropertyTearOff.h
index 3119f2b..a78c3f97 100644
--- a/third_party/WebKit/Source/core/svg/properties/SVGPropertyTearOff.h
+++ b/third_party/WebKit/Source/core/svg/properties/SVGPropertyTearOff.h
@@ -69,8 +69,6 @@
     attribute_name_ = attribute_name;
   }
 
-  virtual AnimatedPropertyType GetType() const = 0;
-
   DEFINE_INLINE_VIRTUAL_TRACE() {}
 
   static void ThrowReadOnly(ExceptionState&);
@@ -106,10 +104,6 @@
 
   void SetTarget(Property* target) { target_ = target; }
 
-  AnimatedPropertyType GetType() const override {
-    return Property::ClassType();
-  }
-
   DEFINE_INLINE_VIRTUAL_TRACE() {
     visitor->Trace(target_);
     SVGPropertyTearOffBase::Trace(visitor);
diff --git a/third_party/WebKit/Source/core/workers/BUILD.gn b/third_party/WebKit/Source/core/workers/BUILD.gn
index 4e01ee7..bf0958a 100644
--- a/third_party/WebKit/Source/core/workers/BUILD.gn
+++ b/third_party/WebKit/Source/core/workers/BUILD.gn
@@ -61,8 +61,6 @@
     "WorkerGlobalScope.h",
     "WorkerInspectorProxy.cpp",
     "WorkerInspectorProxy.h",
-    "WorkerLoaderProxy.cpp",
-    "WorkerLoaderProxy.h",
     "WorkerLocation.h",
     "WorkerNavigator.cpp",
     "WorkerNavigator.h",
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index 4963e90..37a4c0bc 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -19,8 +19,8 @@
 
 std::unique_ptr<WorkerThread> DedicatedWorkerMessagingProxy::CreateWorkerThread(
     double origin_time) {
-  return DedicatedWorkerThread::Create(LoaderProxy(), WorkerObjectProxy(),
-                                       origin_time);
+  return DedicatedWorkerThread::Create(GetThreadableLoadingContext(),
+                                       WorkerObjectProxy(), origin_time);
 }
 
 bool DedicatedWorkerMessagingProxy::IsAtomicsWaitAllowed() {
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 5d9b473f..80cb812a 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -37,13 +37,10 @@
 
 class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread {
  public:
-  DedicatedWorkerThreadForTest(
-      WorkerLoaderProxyProvider* worker_loader_proxy_provider,
-      InProcessWorkerObjectProxy& worker_object_proxy)
-      : DedicatedWorkerThread(
-            WorkerLoaderProxy::Create(worker_loader_proxy_provider),
-            worker_object_proxy,
-            MonotonicallyIncreasingTime()) {
+  DedicatedWorkerThreadForTest(InProcessWorkerObjectProxy& worker_object_proxy)
+      : DedicatedWorkerThread(nullptr /* ThreadableLoadingContext */,
+                              worker_object_proxy,
+                              MonotonicallyIncreasingTime()) {
     worker_backing_thread_ = WorkerBackingThread::CreateForTest("Test thread");
   }
 
@@ -121,10 +118,8 @@
                                       nullptr /* workerClients */) {
     worker_object_proxy_ = WTF::MakeUnique<InProcessWorkerObjectProxyForTest>(
         weak_ptr_factory_.CreateWeakPtr(), GetParentFrameTaskRunners());
-    worker_loader_proxy_provider_ =
-        WTF::MakeUnique<WorkerLoaderProxyProvider>();
-    worker_thread_ = WTF::WrapUnique(new DedicatedWorkerThreadForTest(
-        worker_loader_proxy_provider_.get(), WorkerObjectProxy()));
+    worker_thread_ =
+        WTF::MakeUnique<DedicatedWorkerThreadForTest>(WorkerObjectProxy());
     mock_worker_thread_lifecycle_observer_ =
         new MockWorkerThreadLifecycleObserver(
             worker_thread_->GetWorkerThreadLifecycleContext());
@@ -135,8 +130,6 @@
 
   ~InProcessWorkerMessagingProxyForTest() override {
     EXPECT_FALSE(blocking_);
-    worker_thread_->GetWorkerLoaderProxy()->DetachProvider(
-        worker_loader_proxy_provider_.get());
   }
 
   void StartWithSourceCode(const String& source) {
@@ -224,7 +217,6 @@
   }
 
  private:
-  std::unique_ptr<WorkerLoaderProxyProvider> worker_loader_proxy_provider_;
   Persistent<MockWorkerThreadLifecycleObserver>
       mock_worker_thread_lifecycle_observer_;
   RefPtr<SecurityOrigin> security_origin_;
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
index 00d8580..7cd9d89 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
@@ -41,18 +41,18 @@
 namespace blink {
 
 std::unique_ptr<DedicatedWorkerThread> DedicatedWorkerThread::Create(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     InProcessWorkerObjectProxy& worker_object_proxy,
     double time_origin) {
   return WTF::WrapUnique(new DedicatedWorkerThread(
-      std::move(worker_loader_proxy), worker_object_proxy, time_origin));
+      loading_context, worker_object_proxy, time_origin));
 }
 
 DedicatedWorkerThread::DedicatedWorkerThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     InProcessWorkerObjectProxy& worker_object_proxy,
     double time_origin)
-    : WorkerThread(std::move(worker_loader_proxy), worker_object_proxy),
+    : WorkerThread(loading_context, worker_object_proxy),
       worker_backing_thread_(
           WorkerBackingThread::Create("DedicatedWorker Thread")),
       worker_object_proxy_(worker_object_proxy),
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h
index cde15ef4..a4fa471 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.h
@@ -41,7 +41,7 @@
 class CORE_EXPORT DedicatedWorkerThread : public WorkerThread {
  public:
   static std::unique_ptr<DedicatedWorkerThread> Create(
-      PassRefPtr<WorkerLoaderProxy>,
+      ThreadableLoadingContext*,
       InProcessWorkerObjectProxy&,
       double time_origin);
   ~DedicatedWorkerThread() override;
@@ -55,7 +55,7 @@
   }
 
  protected:
-  DedicatedWorkerThread(PassRefPtr<WorkerLoaderProxy>,
+  DedicatedWorkerThread(ThreadableLoadingContext*,
                         InProcessWorkerObjectProxy&,
                         double time_origin);
   WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
index 729142328..6eff0f72 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
@@ -32,7 +32,6 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/dom/MessagePort.h"
 #include "core/workers/ThreadedMessagingProxyBase.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Noncopyable.h"
 #include "platform/wtf/PassRefPtr.h"
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerThread.cpp b/third_party/WebKit/Source/core/workers/SharedWorkerThread.cpp
index 3ac4a71..93fc942 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerThread.cpp
@@ -38,19 +38,11 @@
 
 namespace blink {
 
-std::unique_ptr<SharedWorkerThread> SharedWorkerThread::Create(
-    const String& name,
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
-    WorkerReportingProxy& worker_reporting_proxy) {
-  return WTF::WrapUnique(new SharedWorkerThread(
-      name, std::move(worker_loader_proxy), worker_reporting_proxy));
-}
-
 SharedWorkerThread::SharedWorkerThread(
     const String& name,
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy)
-    : WorkerThread(std::move(worker_loader_proxy), worker_reporting_proxy),
+    : WorkerThread(loading_context, worker_reporting_proxy),
       worker_backing_thread_(
           WorkerBackingThread::Create("SharedWorker Thread")),
       name_(name.IsolatedCopy()) {}
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerThread.h b/third_party/WebKit/Source/core/workers/SharedWorkerThread.h
index 22f68cd..6158a6e 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerThread.h
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerThread.h
@@ -41,10 +41,9 @@
 
 class CORE_EXPORT SharedWorkerThread : public WorkerThread {
  public:
-  static std::unique_ptr<SharedWorkerThread> Create(
-      const String& name,
-      PassRefPtr<WorkerLoaderProxy>,
-      WorkerReportingProxy&);
+  SharedWorkerThread(const String& name,
+                     ThreadableLoadingContext*,
+                     WorkerReportingProxy&);
   ~SharedWorkerThread() override;
 
   WorkerBackingThread& GetWorkerBackingThread() override {
@@ -57,10 +56,6 @@
       std::unique_ptr<WorkerThreadStartupData>) override;
 
  private:
-  SharedWorkerThread(const String& name,
-                     PassRefPtr<WorkerLoaderProxy>,
-                     WorkerReportingProxy&);
-
   std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
   String name_;
 };
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
index e122721..beed666 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
@@ -36,8 +36,6 @@
 
 ThreadedMessagingProxyBase::~ThreadedMessagingProxyBase() {
   DCHECK(IsParentContextThread());
-  if (loader_proxy_)
-    loader_proxy_->DetachProvider(this);
   g_live_messaging_proxy_count--;
 }
 
@@ -61,7 +59,6 @@
           ? document->Loader()->GetTiming().ReferenceMonotonicTime()
           : MonotonicallyIncreasingTime();
 
-  loader_proxy_ = WorkerLoaderProxy::Create(this);
   worker_thread_ = CreateWorkerThread(origin_time);
   worker_thread_->Start(std::move(startup_data), GetParentFrameTaskRunners());
   WorkerThreadCreated();
@@ -70,11 +67,7 @@
 ThreadableLoadingContext*
 ThreadedMessagingProxyBase::GetThreadableLoadingContext() {
   DCHECK(IsParentContextThread());
-  if (!loading_context_) {
-    loading_context_ =
-        ThreadableLoadingContext::Create(*ToDocument(execution_context_));
-  }
-  return loading_context_;
+  return ThreadableLoadingContext::Create(*ToDocument(execution_context_));
 }
 
 void ThreadedMessagingProxyBase::CountFeature(UseCounter::Feature feature) {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
index ed21b16..30837e6 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
@@ -9,20 +9,18 @@
 #include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleTypes.h"
 #include "core/workers/ParentFrameTaskRunners.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "platform/wtf/Forward.h"
 
 namespace blink {
 
 class ExecutionContext;
 class SourceLocation;
+class ThreadableLoadingContext;
 class WorkerInspectorProxy;
-class WorkerLoaderProxy;
 class WorkerThread;
 class WorkerThreadStartupData;
 
-class CORE_EXPORT ThreadedMessagingProxyBase
-    : private WorkerLoaderProxyProvider {
+class CORE_EXPORT ThreadedMessagingProxyBase {
  public:
   void TerminateGlobalScope();
 
@@ -61,7 +59,7 @@
 
  protected:
   ThreadedMessagingProxyBase(ExecutionContext*);
-  ~ThreadedMessagingProxyBase() override;
+  virtual ~ThreadedMessagingProxyBase();
 
   void InitializeWorkerThread(std::unique_ptr<WorkerThreadStartupData>);
   virtual std::unique_ptr<WorkerThread> CreateWorkerThread(
@@ -71,7 +69,6 @@
 
   bool AskedToTerminate() const { return asked_to_terminate_; }
 
-  PassRefPtr<WorkerLoaderProxy> LoaderProxy() { return loader_proxy_; }
   WorkerInspectorProxy* GetWorkerInspectorProxy() const {
     return worker_inspector_proxy_.Get();
   }
@@ -79,8 +76,7 @@
   // Returns true if this is called on the parent context thread.
   bool IsParentContextThread() const;
 
-  // WorkerLoaderProxyProvider
-  ThreadableLoadingContext* GetThreadableLoadingContext() override;
+  ThreadableLoadingContext* GetThreadableLoadingContext();
 
  private:
   friend class InProcessWorkerMessagingProxyForTest;
@@ -89,15 +85,12 @@
   void ParentObjectDestroyedInternal();
 
   Persistent<ExecutionContext> execution_context_;
-  Persistent<ThreadableLoadingContext> loading_context_;
   Persistent<WorkerInspectorProxy> worker_inspector_proxy_;
   // Accessed cross-thread when worker thread posts tasks to the parent.
   CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
 
   std::unique_ptr<WorkerThread> worker_thread_;
 
-  RefPtr<WorkerLoaderProxy> loader_proxy_;
-
   bool may_be_destroyed_;
   bool asked_to_terminate_;
 };
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index e9a2c962..2fd70cb 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -51,11 +51,9 @@
 
 class ThreadedWorkletThreadForTest : public WorkerThread {
  public:
-  ThreadedWorkletThreadForTest(
-      WorkerLoaderProxyProvider* worker_loader_proxy_provider,
+  explicit ThreadedWorkletThreadForTest(
       WorkerReportingProxy& worker_reporting_proxy)
-      : WorkerThread(WorkerLoaderProxy::Create(worker_loader_proxy_provider),
-                     worker_reporting_proxy) {}
+      : WorkerThread(nullptr, worker_reporting_proxy) {}
   ~ThreadedWorkletThreadForTest() override {}
 
   WorkerBackingThread& GetWorkerBackingThread() override {
@@ -121,16 +119,12 @@
       : ThreadedWorkletMessagingProxy(execution_context) {
     worklet_object_proxy_ = WTF::MakeUnique<ThreadedWorkletObjectProxyForTest>(
         weak_ptr_factory_.CreateWeakPtr(), GetParentFrameTaskRunners());
-    worker_loader_proxy_provider_ =
-        WTF::MakeUnique<WorkerLoaderProxyProvider>();
-    worker_thread_ = WTF::MakeUnique<ThreadedWorkletThreadForTest>(
-        worker_loader_proxy_provider_.get(), WorkletObjectProxy());
+    worker_thread_ =
+        WTF::MakeUnique<ThreadedWorkletThreadForTest>(WorkletObjectProxy());
     ThreadedWorkletThreadForTest::EnsureSharedBackingThread();
   }
 
   ~ThreadedWorkletMessagingProxyForTest() override {
-    worker_thread_->GetWorkerLoaderProxy()->DetachProvider(
-        worker_loader_proxy_provider_.get());
     worker_thread_->TerminateAndWait();
     ThreadedWorkletThreadForTest::ClearSharedBackingThread();
   };
@@ -166,7 +160,6 @@
  private:
   friend class ThreadedWorkletTest;
 
-  std::unique_ptr<WorkerLoaderProxyProvider> worker_loader_proxy_provider_;
   RefPtr<SecurityOrigin> security_origin_;
 };
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index cc0d668..45fb5a5 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -46,7 +46,6 @@
 #include "core/loader/WorkerThreadableLoader.h"
 #include "core/probe/CoreProbes.h"
 #include "core/workers/WorkerClients.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerLocation.h"
 #include "core/workers/WorkerNavigator.h"
 #include "core/workers/WorkerReportingProxy.h"
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
deleted file mode 100644
index 59b65a0..0000000
--- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/workers/WorkerLoaderProxy.h"
-
-#include "core/loader/ThreadableLoadingContext.h"
-
-namespace blink {
-
-WorkerLoaderProxy::WorkerLoaderProxy(
-    WorkerLoaderProxyProvider* loader_proxy_provider)
-    : loader_proxy_provider_(loader_proxy_provider) {}
-
-WorkerLoaderProxy::~WorkerLoaderProxy() {
-  DCHECK(!loader_proxy_provider_);
-}
-
-void WorkerLoaderProxy::DetachProvider(
-    WorkerLoaderProxyProvider* proxy_provider) {
-  DCHECK(IsMainThread());
-  DCHECK_EQ(proxy_provider, loader_proxy_provider_);
-  loader_proxy_provider_ = nullptr;
-}
-
-ThreadableLoadingContext* WorkerLoaderProxy::GetThreadableLoadingContext() {
-  DCHECK(IsMainThread());
-  if (!loader_proxy_provider_)
-    return nullptr;
-  DCHECK(
-      loader_proxy_provider_->GetThreadableLoadingContext()->IsContextThread());
-  return loader_proxy_provider_->GetThreadableLoadingContext();
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
deleted file mode 100644
index d82caf7..0000000
--- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WorkerLoaderProxy_h
-#define WorkerLoaderProxy_h
-
-#include "core/CoreExport.h"
-#include "platform/wtf/Forward.h"
-#include "platform/wtf/Functional.h"
-#include "platform/wtf/PassRefPtr.h"
-#include "platform/wtf/ThreadSafeRefCounted.h"
-#include "public/platform/WebTraceLocation.h"
-
-namespace blink {
-
-class ThreadableLoadingContext;
-
-// The abstract interface to provider ThreadableLoadingContext; separated from
-// the thread-safe & ref-counted WorkerLoaderProxy object which keeps a
-// protected reference to the provider object. This to support non-overlapping
-// lifetimes, the provider may be destructed before all references to the
-// WorkerLoaderProxy object have been dropped.
-//
-// A provider implementation must detach itself when finalizing by calling
-// WorkerLoaderProxy::detachProvider(). This stops the WorkerLoaderProxy from
-// accessing the now-dead object, but it will remain alive while ref-ptrs are
-// still kept to it.
-//
-// TODO(nhiroki): Clean up or remove this class (https://crbug.com/694914).
-class CORE_EXPORT WorkerLoaderProxyProvider {
- public:
-  virtual ~WorkerLoaderProxyProvider() {}
-
-  // It is guaranteed that this gets accessed only on the thread where
-  // the loading context is bound.
-  virtual ThreadableLoadingContext* GetThreadableLoadingContext() {
-    return nullptr;
-  }
-};
-
-class CORE_EXPORT WorkerLoaderProxy final
-    : public ThreadSafeRefCounted<WorkerLoaderProxy> {
- public:
-  static PassRefPtr<WorkerLoaderProxy> Create(
-      WorkerLoaderProxyProvider* loader_proxy_provider) {
-    return AdoptRef(new WorkerLoaderProxy(loader_proxy_provider));
-  }
-
-  ~WorkerLoaderProxy();
-
-  // This may return nullptr.
-  // This must be called from the main thread (== the thread of the
-  // loading context).
-  ThreadableLoadingContext* GetThreadableLoadingContext();
-
-  // Notification from the provider that it can no longer be accessed. An
-  // implementation of WorkerLoaderProxyProvider is required to call
-  // detachProvider() when finalizing. This must be called from the main thread.
-  void DetachProvider(WorkerLoaderProxyProvider*);
-
- private:
-  explicit WorkerLoaderProxy(WorkerLoaderProxyProvider*);
-
-  WorkerLoaderProxyProvider* loader_proxy_provider_;
-};
-
-}  // namespace blink
-
-#endif  // WorkerLoaderProxy_h
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index e35a0aa7..d778af6b 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -201,6 +201,13 @@
   return GetWorkerBackingThread().BackingThread().IsCurrentThread();
 }
 
+ThreadableLoadingContext* WorkerThread::GetLoadingContext() {
+  DCHECK(IsCurrentThread());
+  // This should be never called after the termination sequence starts.
+  DCHECK(loading_context_);
+  return loading_context_;
+}
+
 void WorkerThread::AppendDebuggerTask(
     std::unique_ptr<CrossThreadClosure> task) {
   DCHECK(IsMainThread());
@@ -287,12 +294,12 @@
   return false;
 }
 
-WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+WorkerThread::WorkerThread(ThreadableLoadingContext* loading_context,
                            WorkerReportingProxy& worker_reporting_proxy)
     : worker_thread_id_(GetNextWorkerThreadId()),
       forcible_termination_delay_in_ms_(kForcibleTerminationDelayInMs),
       inspector_task_runner_(WTF::MakeUnique<InspectorTaskRunner>()),
-      worker_loader_proxy_(std::move(worker_loader_proxy)),
+      loading_context_(loading_context),
       worker_reporting_proxy_(worker_reporting_proxy),
       shutdown_event_(WTF::WrapUnique(
           new WaitableEvent(WaitableEvent::ResetPolicy::kManual,
@@ -534,6 +541,7 @@
   GlobalScope()->Dispose();
   global_scope_scheduler_->Dispose();
   console_message_storage_.Clear();
+  loading_context_.Clear();
   GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.h b/third_party/WebKit/Source/core/workers/WorkerThread.h
index 1519bb69..8de8cb3 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.h
@@ -31,8 +31,8 @@
 
 #include "core/CoreExport.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
+#include "core/loader/ThreadableLoadingContext.h"
 #include "core/workers/ParentFrameTaskRunners.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerThreadLifecycleObserver.h"
 #include "platform/LifecycleNotifier.h"
 #include "platform/WaitableEvent.h"
@@ -128,10 +128,8 @@
 
   bool IsCurrentThread();
 
-  WorkerLoaderProxy* GetWorkerLoaderProxy() const {
-    CHECK(worker_loader_proxy_);
-    return worker_loader_proxy_.Get();
-  }
+  // Called on the worker thread.
+  ThreadableLoadingContext* GetLoadingContext();
 
   WorkerReportingProxy& GetWorkerReportingProxy() const {
     return worker_reporting_proxy_;
@@ -178,7 +176,7 @@
   }
 
  protected:
-  WorkerThread(PassRefPtr<WorkerLoaderProxy>, WorkerReportingProxy&);
+  WorkerThread(ThreadableLoadingContext*, WorkerReportingProxy&);
 
   // Factory method for creating a new worker context for the thread.
   // Called on the worker thread.
@@ -288,7 +286,10 @@
 
   std::unique_ptr<InspectorTaskRunner> inspector_task_runner_;
 
-  RefPtr<WorkerLoaderProxy> worker_loader_proxy_;
+  // Created on the main thread, passed to the worker thread but should kept
+  // being accessed only on the main thread.
+  CrossThreadPersistent<ThreadableLoadingContext> loading_context_;
+
   WorkerReportingProxy& worker_reporting_proxy_;
 
   CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index f141dab..6c87a6c 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -67,20 +67,16 @@
   WorkerThreadTest() {}
 
   void SetUp() override {
-    loader_proxy_provider_ = WTF::MakeUnique<WorkerLoaderProxyProvider>();
     reporting_proxy_ = WTF::MakeUnique<MockWorkerReportingProxy>();
     security_origin_ =
         SecurityOrigin::Create(KURL(kParsedURLString, "http://fake.url/"));
-    worker_thread_ = WTF::WrapUnique(new WorkerThreadForTest(
-        loader_proxy_provider_.get(), *reporting_proxy_));
+    worker_thread_ =
+        WTF::WrapUnique(new WorkerThreadForTest(nullptr, *reporting_proxy_));
     lifecycle_observer_ = new MockWorkerThreadLifecycleObserver(
         worker_thread_->GetWorkerThreadLifecycleContext());
   }
 
-  void TearDown() override {
-    worker_thread_->GetWorkerLoaderProxy()->DetachProvider(
-        loader_proxy_provider_.get());
-  }
+  void TearDown() override {}
 
   void Start() {
     worker_thread_->StartWithSourceCode(
@@ -143,7 +139,6 @@
   ExitCode GetExitCode() { return worker_thread_->GetExitCodeForTesting(); }
 
   RefPtr<SecurityOrigin> security_origin_;
-  std::unique_ptr<WorkerLoaderProxyProvider> loader_proxy_provider_;
   std::unique_ptr<MockWorkerReportingProxy> reporting_proxy_;
   std::unique_ptr<WorkerThreadForTest> worker_thread_;
   Persistent<MockWorkerThreadLifecycleObserver> lifecycle_observer_;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
index d646ffd..b5fd6dd47 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -13,7 +13,6 @@
 #include "core/workers/WorkerBackingThread.h"
 #include "core/workers/WorkerClients.h"
 #include "core/workers/WorkerGlobalScope.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "core/workers/WorkerThreadLifecycleObserver.h"
@@ -51,10 +50,9 @@
 
 class WorkerThreadForTest : public WorkerThread {
  public:
-  WorkerThreadForTest(WorkerLoaderProxyProvider* worker_loader_proxy_provider,
+  WorkerThreadForTest(ThreadableLoadingContext* loading_context,
                       WorkerReportingProxy& mock_worker_reporting_proxy)
-      : WorkerThread(WorkerLoaderProxy::Create(worker_loader_proxy_provider),
-                     mock_worker_reporting_proxy),
+      : WorkerThread(loading_context, mock_worker_reporting_proxy),
         worker_backing_thread_(
             WorkerBackingThread::CreateForTest("Test thread")) {}
 
diff --git a/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.cpp b/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.cpp
index b9d4099..d734b2941 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.cpp
@@ -5,6 +5,7 @@
 #include "modules/compositorworker/AbstractAnimationWorkletThread.h"
 
 #include <memory>
+#include "core/loader/ThreadableLoadingContext.h"
 #include "core/workers/WorkerBackingThread.h"
 #include "core/workers/WorkletThreadHolder.h"
 #include "platform/CrossThreadFunctional.h"
@@ -18,9 +19,9 @@
 template class WorkletThreadHolder<AbstractAnimationWorkletThread>;
 
 AbstractAnimationWorkletThread::AbstractAnimationWorkletThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy)
-    : WorkerThread(std::move(worker_loader_proxy), worker_reporting_proxy) {}
+    : WorkerThread(loading_context, worker_reporting_proxy) {}
 
 AbstractAnimationWorkletThread::~AbstractAnimationWorkletThread() {}
 
diff --git a/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.h b/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.h
index 43904030..3c8f502 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.h
+++ b/third_party/WebKit/Source/modules/compositorworker/AbstractAnimationWorkletThread.h
@@ -5,13 +5,13 @@
 #ifndef AbstractAnimationWorkletThread_h
 #define AbstractAnimationWorkletThread_h
 
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "modules/ModulesExport.h"
 #include <memory>
 
 namespace blink {
 
+class ThreadableLoadingContext;
 class WorkerReportingProxy;
 
 // TODO(ikilpatrick): Remove this class up to AnimationWorkletThread once we no
@@ -34,7 +34,7 @@
   static void CreateSharedBackingThreadForTest();
 
  protected:
-  AbstractAnimationWorkletThread(PassRefPtr<WorkerLoaderProxy>,
+  AbstractAnimationWorkletThread(ThreadableLoadingContext*,
                                  WorkerReportingProxy&);
 
   bool IsOwningBackingThread() const override { return false; }
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletMessagingProxy.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletMessagingProxy.cpp
index 9e6c6f9..85fb75ed 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletMessagingProxy.cpp
@@ -19,7 +19,8 @@
 
 std::unique_ptr<WorkerThread>
 AnimationWorkletMessagingProxy::CreateWorkerThread(double origin_time) {
-  return AnimationWorkletThread::Create(LoaderProxy(), WorkletObjectProxy());
+  return AnimationWorkletThread::Create(GetThreadableLoadingContext(),
+                                        WorkletObjectProxy());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp
index 5950851..0952160 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.cpp
@@ -13,20 +13,19 @@
 namespace blink {
 
 std::unique_ptr<AnimationWorkletThread> AnimationWorkletThread::Create(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
                "AnimationWorkletThread::create");
   DCHECK(IsMainThread());
-  return WTF::WrapUnique(new AnimationWorkletThread(
-      std::move(worker_loader_proxy), worker_reporting_proxy));
+  return WTF::WrapUnique(
+      new AnimationWorkletThread(loading_context, worker_reporting_proxy));
 }
 
 AnimationWorkletThread::AnimationWorkletThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy)
-    : AbstractAnimationWorkletThread(std::move(worker_loader_proxy),
-                                     worker_reporting_proxy) {}
+    : AbstractAnimationWorkletThread(loading_context, worker_reporting_proxy) {}
 
 AnimationWorkletThread::~AnimationWorkletThread() {}
 
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h
index 76747c9a0..289c74f8 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThread.h
@@ -17,7 +17,7 @@
     : public AbstractAnimationWorkletThread {
  public:
   static std::unique_ptr<AnimationWorkletThread> Create(
-      PassRefPtr<WorkerLoaderProxy>,
+      ThreadableLoadingContext*,
       WorkerReportingProxy&);
   ~AnimationWorkletThread() override;
 
@@ -26,7 +26,7 @@
       std::unique_ptr<WorkerThreadStartupData>) final;
 
  private:
-  AnimationWorkletThread(PassRefPtr<WorkerLoaderProxy>, WorkerReportingProxy&);
+  AnimationWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
index de6dc7b..e429afa 100644
--- a/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/AnimationWorkletThreadTest.cpp
@@ -13,7 +13,6 @@
 #include "core/workers/InProcessWorkerObjectProxy.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerBackingThread.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerOrWorkletGlobalScope.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "core/workers/WorkerThreadStartupData.h"
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerMessagingProxy.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerMessagingProxy.cpp
index 9d95f3d..fa4a22a 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerMessagingProxy.cpp
@@ -21,8 +21,8 @@
 
 std::unique_ptr<WorkerThread>
 CompositorWorkerMessagingProxy::CreateWorkerThread(double origin_time) {
-  return CompositorWorkerThread::Create(LoaderProxy(), WorkerObjectProxy(),
-                                        origin_time);
+  return CompositorWorkerThread::Create(GetThreadableLoadingContext(),
+                                        WorkerObjectProxy(), origin_time);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
index 3d0df5b..a4a3e764 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.cpp
@@ -14,22 +14,21 @@
 namespace blink {
 
 std::unique_ptr<CompositorWorkerThread> CompositorWorkerThread::Create(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     InProcessWorkerObjectProxy& worker_object_proxy,
     double time_origin) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("compositor-worker"),
                "CompositorWorkerThread::create");
   DCHECK(IsMainThread());
   return WTF::WrapUnique(new CompositorWorkerThread(
-      std::move(worker_loader_proxy), worker_object_proxy, time_origin));
+      loading_context, worker_object_proxy, time_origin));
 }
 
 CompositorWorkerThread::CompositorWorkerThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     InProcessWorkerObjectProxy& worker_object_proxy,
     double time_origin)
-    : AbstractAnimationWorkletThread(std::move(worker_loader_proxy),
-                                     worker_object_proxy),
+    : AbstractAnimationWorkletThread(loading_context, worker_object_proxy),
       worker_object_proxy_(worker_object_proxy),
       time_origin_(time_origin) {}
 
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h
index d2137611..c88dc2690 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThread.h
@@ -17,7 +17,7 @@
     : public AbstractAnimationWorkletThread {
  public:
   static std::unique_ptr<CompositorWorkerThread> Create(
-      PassRefPtr<WorkerLoaderProxy>,
+      ThreadableLoadingContext*,
       InProcessWorkerObjectProxy&,
       double time_origin);
   ~CompositorWorkerThread() override;
@@ -31,7 +31,7 @@
       std::unique_ptr<WorkerThreadStartupData>) override;
 
  private:
-  CompositorWorkerThread(PassRefPtr<WorkerLoaderProxy>,
+  CompositorWorkerThread(ThreadableLoadingContext*,
                          InProcessWorkerObjectProxy&,
                          double time_origin);
 
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
index 6d5796cd..263ee29 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
@@ -14,7 +14,6 @@
 #include "core/workers/InProcessWorkerObjectProxy.h"
 #include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerBackingThread.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerOrWorkletGlobalScope.h"
 #include "core/workers/WorkerThreadStartupData.h"
 #include "platform/CrossThreadFunctional.h"
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp
index d38d6c3b..e98d2c6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.cpp
@@ -38,17 +38,10 @@
 
 namespace blink {
 
-std::unique_ptr<ServiceWorkerThread> ServiceWorkerThread::Create(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
-    WorkerReportingProxy& worker_reporting_proxy) {
-  return WTF::WrapUnique(new ServiceWorkerThread(std::move(worker_loader_proxy),
-                                                 worker_reporting_proxy));
-}
-
 ServiceWorkerThread::ServiceWorkerThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy)
-    : WorkerThread(std::move(worker_loader_proxy), worker_reporting_proxy),
+    : WorkerThread(loading_context, worker_reporting_proxy),
       worker_backing_thread_(
           WorkerBackingThread::Create("ServiceWorker Thread")) {}
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h
index 4b50fbb1..fc438b2 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerThread.h
@@ -41,9 +41,7 @@
 
 class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread {
  public:
-  static std::unique_ptr<ServiceWorkerThread> Create(
-      PassRefPtr<WorkerLoaderProxy>,
-      WorkerReportingProxy&);
+  ServiceWorkerThread(ThreadableLoadingContext*, WorkerReportingProxy&);
   ~ServiceWorkerThread() override;
 
   WorkerBackingThread& GetWorkerBackingThread() override {
@@ -56,7 +54,6 @@
       std::unique_ptr<WorkerThreadStartupData>) override;
 
  private:
-  ServiceWorkerThread(PassRefPtr<WorkerLoaderProxy>, WorkerReportingProxy&);
   std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
 };
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
index fca1589..d351325 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
@@ -17,7 +17,8 @@
 
 std::unique_ptr<WorkerThread> AudioWorkletMessagingProxy::CreateWorkerThread(
     double origin_time) {
-  return AudioWorkletThread::Create(LoaderProxy(), WorkletObjectProxy());
+  return AudioWorkletThread::Create(GetThreadableLoadingContext(),
+                                    WorkletObjectProxy());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp
index ebf9b3f5..3c031900 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.cpp
@@ -22,19 +22,19 @@
 template class WorkletThreadHolder<AudioWorkletThread>;
 
 std::unique_ptr<AudioWorkletThread> AudioWorkletThread::Create(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
                "AudioWorkletThread::create");
   DCHECK(IsMainThread());
-  return WTF::WrapUnique(new AudioWorkletThread(std::move(worker_loader_proxy),
-                                                worker_reporting_proxy));
+  return WTF::WrapUnique(
+      new AudioWorkletThread(loading_context, worker_reporting_proxy));
 }
 
 AudioWorkletThread::AudioWorkletThread(
-    PassRefPtr<WorkerLoaderProxy> worker_loader_proxy,
+    ThreadableLoadingContext* loading_context,
     WorkerReportingProxy& worker_reporting_proxy)
-    : WorkerThread(std::move(worker_loader_proxy), worker_reporting_proxy) {}
+    : WorkerThread(loading_context, worker_reporting_proxy) {}
 
 AudioWorkletThread::~AudioWorkletThread() {}
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h
index 22e5b9d..93a091de 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThread.h
@@ -5,7 +5,6 @@
 #ifndef AudioWorkletThread_h
 #define AudioWorkletThread_h
 
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "core/workers/WorkletThreadHolder.h"
 #include "modules/ModulesExport.h"
@@ -21,9 +20,8 @@
 
 class MODULES_EXPORT AudioWorkletThread final : public WorkerThread {
  public:
-  static std::unique_ptr<AudioWorkletThread> Create(
-      PassRefPtr<WorkerLoaderProxy>,
-      WorkerReportingProxy&);
+  static std::unique_ptr<AudioWorkletThread> Create(ThreadableLoadingContext*,
+                                                    WorkerReportingProxy&);
   ~AudioWorkletThread() override;
 
   WorkerBackingThread& GetWorkerBackingThread() override;
@@ -46,7 +44,7 @@
   bool IsOwningBackingThread() const override { return false; }
 
  private:
-  AudioWorkletThread(PassRefPtr<WorkerLoaderProxy>, WorkerReportingProxy&);
+  AudioWorkletThread(ThreadableLoadingContext*, WorkerReportingProxy&);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
index 4fbbf59..a5ead726 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
@@ -11,7 +11,6 @@
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/workers/WorkerBackingThread.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerOrWorkletGlobalScope.h"
 #include "core/workers/WorkerReportingProxy.h"
 #include "core/workers/WorkerThreadStartupData.h"
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
index 73c1e7125..ad542c96 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -36,7 +36,6 @@
 #include "core/fileapi/Blob.h"
 #include "core/loader/ThreadableLoadingContext.h"
 #include "core/workers/WorkerGlobalScope.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "modules/websockets/DocumentWebSocketChannel.h"
 #include "platform/CrossThreadFunctional.h"
@@ -161,12 +160,10 @@
 }
 
 Peer::Peer(Bridge* bridge,
-           PassRefPtr<WorkerLoaderProxy> loader_proxy,
            RefPtr<WebTaskRunner> worker_networking_task_runner,
            WorkerThreadLifecycleContext* worker_thread_lifecycle_context)
     : WorkerThreadLifecycleObserver(worker_thread_lifecycle_context),
       bridge_(bridge),
-      loader_proxy_(std::move(loader_proxy)),
       worker_networking_task_runner_(std::move(worker_networking_task_runner)),
       main_web_socket_channel_(nullptr) {
   DCHECK(IsMainThread());
@@ -358,7 +355,6 @@
                WorkerGlobalScope& worker_global_scope)
     : client_(client),
       worker_global_scope_(worker_global_scope),
-      loader_proxy_(worker_global_scope_->GetThread()->GetWorkerLoaderProxy()),
       parent_frame_task_runners_(
           worker_global_scope_->GetThread()->GetParentFrameTaskRunners()) {}
 
@@ -368,7 +364,7 @@
 
 void Bridge::ConnectOnMainThread(
     std::unique_ptr<SourceLocation> location,
-    RefPtr<WorkerLoaderProxy> loader_proxy,
+    ThreadableLoadingContext* loading_context,
     RefPtr<WebTaskRunner> worker_networking_task_runner,
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     const KURL& url,
@@ -376,13 +372,8 @@
     WebSocketChannelSyncHelper* sync_helper) {
   DCHECK(IsMainThread());
   DCHECK(!peer_);
-  ThreadableLoadingContext* loading_context =
-      loader_proxy->GetThreadableLoadingContext();
-  if (!loading_context)
-    return;
-  Peer* peer =
-      new Peer(this, loader_proxy_, std::move(worker_networking_task_runner),
-               worker_thread_lifecycle_context);
+  Peer* peer = new Peer(this, std::move(worker_networking_task_runner),
+                        worker_thread_lifecycle_context);
   if (peer->Initialize(std::move(location), loading_context)) {
     peer_ = peer;
     sync_helper->SetConnectRequestResult(peer_->Connect(url, protocol));
@@ -393,22 +384,24 @@
 bool Bridge::Connect(std::unique_ptr<SourceLocation> location,
                      const KURL& url,
                      const String& protocol) {
+  DCHECK(worker_global_scope_->IsContextThread());
   // Wait for completion of the task on the main thread because the mixed
   // content check must synchronously be conducted.
   WebSocketChannelSyncHelper sync_helper;
   RefPtr<WebTaskRunner> worker_networking_task_runner =
       TaskRunnerHelper::Get(TaskType::kNetworking, worker_global_scope_.Get());
+  WorkerThread* worker_thread = worker_global_scope_->GetThread();
   parent_frame_task_runners_->Get(TaskType::kNetworking)
       ->PostTask(
           BLINK_FROM_HERE,
-          CrossThreadBind(&Bridge::ConnectOnMainThread,
-                          WrapCrossThreadPersistent(this),
-                          WTF::Passed(location->Clone()), loader_proxy_,
-                          std::move(worker_networking_task_runner),
-                          WrapCrossThreadPersistent(
-                              worker_global_scope_->GetThread()
-                                  ->GetWorkerThreadLifecycleContext()),
-                          url, protocol, CrossThreadUnretained(&sync_helper)));
+          CrossThreadBind(
+              &Bridge::ConnectOnMainThread, WrapCrossThreadPersistent(this),
+              WTF::Passed(location->Clone()),
+              WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
+              std::move(worker_networking_task_runner),
+              WrapCrossThreadPersistent(
+                  worker_thread->GetWorkerThreadLifecycleContext()),
+              url, protocol, CrossThreadUnretained(&sync_helper)));
   sync_helper.Wait();
   return sync_helper.ConnectRequestResult();
 }
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
index 80f42f0..0f2af37 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
@@ -53,7 +53,6 @@
 class ThreadableLoadingContext;
 class WebSocketChannelSyncHelper;
 class WorkerGlobalScope;
-class WorkerLoaderProxy;
 
 class WorkerWebSocketChannel final : public WebSocketChannel {
   WTF_MAKE_NONCOPYABLE(WorkerWebSocketChannel);
@@ -98,7 +97,6 @@
 
    public:
     Peer(Bridge*,
-         PassRefPtr<WorkerLoaderProxy>,
          RefPtr<WebTaskRunner>,
          WorkerThreadLifecycleContext*);
     ~Peer() override;
@@ -137,7 +135,6 @@
 
    private:
     CrossThreadWeakPersistent<Bridge> bridge_;
-    RefPtr<WorkerLoaderProxy> loader_proxy_;
     RefPtr<WebTaskRunner> worker_networking_task_runner_;
     Member<WebSocketChannel> main_web_socket_channel_;
   };
@@ -167,7 +164,7 @@
     void Disconnect();
 
     void ConnectOnMainThread(std::unique_ptr<SourceLocation>,
-                             RefPtr<WorkerLoaderProxy>,
+                             ThreadableLoadingContext*,
                              RefPtr<WebTaskRunner>,
                              WorkerThreadLifecycleContext*,
                              const KURL&,
@@ -184,7 +181,6 @@
    private:
     Member<WebSocketChannelClient> client_;
     Member<WorkerGlobalScope> worker_global_scope_;
-    RefPtr<WorkerLoaderProxy> loader_proxy_;
     CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
     CrossThreadPersistent<Peer> peer_;
   };
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 30d1e2d0..cc91807 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -950,7 +950,7 @@
     },
     {
       name: "StyleSharing",
-      status: "stable",
+      status: "experimental",
     },
     {
       name: "Suborigins",
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
index 5b3edd5..c6bc4fb 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
@@ -53,7 +53,6 @@
 class ResourceError;
 class ResourceResponse;
 class ResourceTimingInfo;
-class WebTaskRunner;
 enum class WebCachePolicy;
 
 enum FetchResourceType { kFetchMainResource, kFetchSubresource };
@@ -204,13 +203,12 @@
 
   virtual MHTMLArchive* Archive() const { return nullptr; }
 
-  virtual RefPtr<WebTaskRunner> LoadingTaskRunner() const { return nullptr; }
-
   PlatformProbeSink* GetPlatformProbeSink() const {
     return platform_probe_sink_;
   }
 
-  virtual std::unique_ptr<WebURLLoader> CreateURLLoader() {
+  virtual std::unique_ptr<WebURLLoader> CreateURLLoader(
+      const ResourceRequest&) {
     NOTREACHED();
     return nullptr;
   }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/MemoryCacheCorrectnessTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/MemoryCacheCorrectnessTest.cpp
index d4e3ffd8..c6e4294 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/MemoryCacheCorrectnessTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/MemoryCacheCorrectnessTest.cpp
@@ -102,8 +102,9 @@
     // Save the global memory cache to restore it upon teardown.
     global_memory_cache_ = ReplaceMemoryCacheForTesting(MemoryCache::Create());
 
-    fetcher_ = ResourceFetcher::Create(
-        MockFetchContext::Create(MockFetchContext::kShouldNotLoadNewResource));
+    auto* context =
+        MockFetchContext::Create(MockFetchContext::kShouldNotLoadNewResource);
+    fetcher_ = ResourceFetcher::Create(context, context->GetTaskRunner().Get());
   }
   void TearDown() override {
     GetMemoryCache()->EvictResources();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index f56c4c12..5cedba9 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -263,14 +263,12 @@
   return WebURLRequest::kRequestContextSubresource;
 }
 
-ResourceFetcher::ResourceFetcher(FetchContext* new_context)
+ResourceFetcher::ResourceFetcher(FetchContext* new_context,
+                                 RefPtr<WebTaskRunner> task_runner)
     : context_(new_context),
       archive_(Context().IsMainFrame() ? nullptr : Context().Archive()),
-      // loadingTaskRunner() is null in tests that use the null fetch context.
       resource_timing_report_timer_(
-          Context().LoadingTaskRunner()
-              ? Context().LoadingTaskRunner()
-              : Platform::Current()->CurrentThread()->GetWebTaskRunner(),
+          std::move(task_runner),
           this,
           &ResourceFetcher::ResourceTimingReportTimerFired),
       auto_load_images_(true),
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
index 3b66e01..0493f69 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.h
@@ -65,8 +65,9 @@
   USING_PRE_FINALIZER(ResourceFetcher, ClearPreloads);
 
  public:
-  static ResourceFetcher* Create(FetchContext* context) {
-    return new ResourceFetcher(context);
+  static ResourceFetcher* Create(FetchContext* context,
+                                 RefPtr<WebTaskRunner> task_runner) {
+    return new ResourceFetcher(context, std::move(task_runner));
   }
   virtual ~ResourceFetcher();
   DECLARE_VIRTUAL_TRACE();
@@ -160,7 +161,7 @@
  private:
   friend class ResourceCacheValidationSuppressor;
 
-  explicit ResourceFetcher(FetchContext*);
+  ResourceFetcher(FetchContext*, RefPtr<WebTaskRunner>);
 
   void InitializeRevalidation(ResourceRequest&, Resource*);
   Resource* CreateResourceForLoading(FetchParameters&,
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
index 13638fc15..e0810d6 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcherTest.cpp
@@ -107,7 +107,10 @@
   KURL secure_url(kParsedURLString, "https://secureorigin.test/image.png");
   // Try to request a url. The request should fail, and a resource in an error
   // state should be returned, and no resource should be present in the cache.
-  ResourceFetcher* fetcher = ResourceFetcher::Create(nullptr);
+  ResourceFetcher* fetcher = ResourceFetcher::Create(
+      &FetchContext::NullInstance(),
+      Platform::Current()->CurrentThread()->GetWebTaskRunner());
+
   ResourceRequest resource_request(secure_url);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
   FetchParameters fetch_params =
@@ -125,7 +128,8 @@
 }
 
 TEST_F(ResourceFetcherTest, UseExistingResource) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.html");
   ResourceResponse response;
@@ -160,7 +164,8 @@
   resource->Finish();
   ASSERT_TRUE(resource->MustReloadDueToVaryHeader(ResourceRequest(url)));
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest resource_request(url);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
   FetchParameters fetch_params =
@@ -178,7 +183,8 @@
   response.SetURL(url);
   response.SetHTTPStatusCode(200);
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest resource_request(url);
   resource_request.SetFrameType(WebURLRequest::kFrameTypeNested);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextForm);
@@ -212,7 +218,8 @@
 }
 
 TEST_F(ResourceFetcherTest, VaryOnBack) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.html");
   Resource* resource =
@@ -237,7 +244,8 @@
 }
 
 TEST_F(ResourceFetcherTest, VaryResource) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.html");
   ResourceResponse response;
@@ -273,7 +281,8 @@
     EXPECT_EQ(resource_, resource);
     MockFetchContext* context =
         MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
-    ResourceFetcher* fetcher2 = ResourceFetcher::Create(context);
+    ResourceFetcher* fetcher2 =
+        ResourceFetcher::Create(context, context->GetTaskRunner());
     ResourceRequest resource_request2(resource_->Url());
     resource_request2.SetCachePolicy(WebCachePolicy::kValidatingCacheData);
     FetchParameters fetch_params2(resource_request2, FetchInitiatorInfo());
@@ -303,7 +312,8 @@
   response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=3600");
   response.SetHTTPHeaderField(HTTPNames::ETag, "1234567890");
   RegisterMockedURLLoadWithCustomResponse(url, response);
-  ResourceFetcher* fetcher1 = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher1 =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest request1(url);
   request1.SetHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
   FetchParameters fetch_params1 =
@@ -318,7 +328,8 @@
 }
 
 TEST_F(ResourceFetcherTest, DontReuseMediaDataUrl) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest request(KURL(kParsedURLString, "data:text/html,foo"));
   request.SetRequestContext(WebURLRequest::kRequestContextVideo);
   ResourceLoaderOptions options;
@@ -381,7 +392,8 @@
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest resource_request(url);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
   FetchParameters fetch_params =
@@ -419,7 +431,8 @@
   }
 
   void Request(const WebString& url) {
-    ResourceFetcher* fetcher = ResourceFetcher::Create(context_);
+    ResourceFetcher* fetcher =
+        ResourceFetcher::Create(context_, context_->GetTaskRunner());
     ResourceRequest resource_request(url);
     resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
     FetchParameters fetch_params =
@@ -474,7 +487,8 @@
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest resource_request(url);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
   FetchParameters fetch_params(resource_request, FetchInitiatorInfo());
@@ -486,7 +500,8 @@
 }
 
 TEST_F(ResourceFetcherTest, PreloadResourceTwice) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -514,7 +529,8 @@
 }
 
 TEST_F(ResourceFetcherTest, LinkPreloadResourceAndUse) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -551,7 +567,8 @@
 }
 
 TEST_F(ResourceFetcherTest, PreloadMatchWithBypassingCache) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
 
@@ -573,8 +590,10 @@
 }
 
 TEST_F(ResourceFetcherTest, CrossFramePreloadMatchIsNotAllowed) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
-  ResourceFetcher* fetcher2 = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
+  ResourceFetcher* fetcher2 =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -599,7 +618,8 @@
 }
 
 TEST_F(ResourceFetcherTest, RepetitiveLinkPreloadShouldBeMerged) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -629,7 +649,8 @@
 }
 
 TEST_F(ResourceFetcherTest, RepetitiveSpeculativePreloadShouldBeMerged) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -660,7 +681,8 @@
 }
 
 TEST_F(ResourceFetcherTest, SpeculativePreloadShouldBePromotedToLinkePreload) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -710,7 +732,8 @@
   resource->ResponseReceived(response, nullptr);
   resource->Finish();
 
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   ResourceRequest resource_request(url);
   resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
   FetchParameters fetch_params =
@@ -724,8 +747,10 @@
 }
 
 TEST_F(ResourceFetcherTest, LinkPreloadResourceMultipleFetchersAndMove) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
-  ResourceFetcher* fetcher2 = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
+  ResourceFetcher* fetcher2 =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
 
   KURL url(kParsedURLString, "http://127.0.0.1:8000/foo.png");
   RegisterMockedURLLoad(url);
@@ -750,7 +775,8 @@
 }
 
 TEST_F(ResourceFetcherTest, ContentTypeDataURL) {
-  ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+  ResourceFetcher* fetcher =
+      ResourceFetcher::Create(Context(), Context()->GetTaskRunner());
   FetchParameters fetch_params = FetchParameters(
       ResourceRequest("data:text/testmimetype,foo"), FetchInitiatorInfo());
   Resource* resource = MockResource::Fetch(fetch_params, fetcher);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
index 04a20d0..a6db5b32 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -83,10 +83,9 @@
     return;
   }
 
-  loader_ = fetcher_->Context().CreateURLLoader();
+  loader_ = fetcher_->Context().CreateURLLoader(request);
   DCHECK(loader_);
   loader_->SetDefersLoading(Context().DefersLoading());
-  loader_->SetLoadingTaskRunner(Context().LoadingTaskRunner().Get());
 
   if (is_cache_aware_loading_activated_) {
     // Override cache policy for cache-aware loading. If this request fails, a
diff --git a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
index f1b9ccb8..7c0a01f 100644
--- a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
@@ -68,17 +68,21 @@
   bool ShouldLoadNewResource(Resource::Type) const override {
     return load_policy_ == kShouldLoadNewResource;
   }
-  RefPtr<WebTaskRunner> LoadingTaskRunner() const override { return runner_; }
   bool IsLoadComplete() const override { return complete_; }
   void AddResourceTiming(
       const ResourceTimingInfo& resource_timing_info) override {
     transfer_size_ = resource_timing_info.TransferSize();
   }
 
-  std::unique_ptr<WebURLLoader> CreateURLLoader() override {
-    return Platform::Current()->CreateURLLoader();
+  std::unique_ptr<WebURLLoader> CreateURLLoader(
+      const ResourceRequest&) override {
+    auto loader = Platform::Current()->CreateURLLoader();
+    loader->SetLoadingTaskRunner(runner_.Get());
+    return loader;
   }
 
+  RefPtr<WebTaskRunner> GetTaskRunner() { return runner_; }
+
  private:
   MockFetchContext(LoadPolicy load_policy, RefPtr<WebTaskRunner> task_runner)
       : load_policy_(load_policy),
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index aee8f6fb..eb4a756 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -188,8 +188,6 @@
     "WebUserGestureIndicator.cpp",
     "WebUserGestureToken.cpp",
     "WebUserMediaRequest.cpp",
-    "WebViewFrameWidget.cpp",
-    "WebViewFrameWidget.h",
     "WebViewImpl.cpp",
     "WebViewImpl.h",
     "linux/WebFontRendering.cpp",
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
index 91c1f35..0c59c3d 100644
--- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
@@ -48,7 +48,6 @@
 #include "core/workers/WorkerContentSettingsClient.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "core/workers/WorkerInspectorProxy.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerScriptLoader.h"
 #include "core/workers/WorkerThreadStartupData.h"
 #include "modules/serviceworkers/ServiceWorkerContainerClient.h"
@@ -130,8 +129,6 @@
 
   web_view_->Close();
   main_frame_->Close();
-  if (loader_proxy_)
-    loader_proxy_->DetachProvider(this);
 }
 
 void WebEmbeddedWorkerImpl::StartWorkerContext(
@@ -266,14 +263,6 @@
   worker_inspector_proxy_->DispatchMessageFromWorker(message);
 }
 
-ThreadableLoadingContext* WebEmbeddedWorkerImpl::GetThreadableLoadingContext() {
-  if (!loading_context_) {
-    loading_context_ = ThreadableLoadingContext::Create(
-        *main_frame_->GetFrame()->GetDocument());
-  }
-  return loading_context_;
-}
-
 void WebEmbeddedWorkerImpl::PrepareShadowPageForLoader() {
   // Create 'shadow page', which is never displayed and is used mainly to
   // provide a context for loading on the main thread.
@@ -471,9 +460,8 @@
 
   worker_global_scope_proxy_ =
       ServiceWorkerGlobalScopeProxy::Create(*this, *worker_context_client_);
-  loader_proxy_ = WorkerLoaderProxy::Create(this);
-  worker_thread_ =
-      ServiceWorkerThread::Create(loader_proxy_, *worker_global_scope_proxy_);
+  worker_thread_ = WTF::MakeUnique<ServiceWorkerThread>(
+      ThreadableLoadingContext::Create(*document), *worker_global_scope_proxy_);
 
   // We have a dummy document here for loading but it doesn't really represent
   // the document/frame of associated document(s) for this worker. Here we
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
index b4e76b0..f627f4e 100644
--- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
+++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
@@ -31,8 +31,6 @@
 #ifndef WebEmbeddedWorkerImpl_h
 #define WebEmbeddedWorkerImpl_h
 
-#include "core/workers/WorkerLoaderProxy.h"
-
 #include <memory>
 #include "platform/heap/Handle.h"
 #include "public/platform/Platform.h"
@@ -54,8 +52,7 @@
 
 class WebEmbeddedWorkerImpl final : public WebEmbeddedWorker,
                                     public WebFrameClient,
-                                    public WebDevToolsAgentClient,
-                                    private WorkerLoaderProxyProvider {
+                                    public WebDevToolsAgentClient {
   WTF_MAKE_NONCOPYABLE(WebEmbeddedWorkerImpl);
 
  public:
@@ -104,9 +101,6 @@
   void OnScriptLoaderFinished();
   void StartWorkerThread();
 
-  // WorkerLoaderProxyProvider
-  ThreadableLoadingContext* GetThreadableLoadingContext() override;
-
   WebEmbeddedWorkerStartData worker_start_data_;
 
   std::unique_ptr<WebServiceWorkerContextClient> worker_context_client_;
@@ -119,7 +113,6 @@
   RefPtr<WorkerScriptLoader> main_script_loader_;
 
   std::unique_ptr<WorkerThread> worker_thread_;
-  RefPtr<WorkerLoaderProxy> loader_proxy_;
   Persistent<ServiceWorkerGlobalScopeProxy> worker_global_scope_proxy_;
   Persistent<WorkerInspectorProxy> worker_inspector_proxy_;
 
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index e3806f2d..958d648 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -47,6 +47,7 @@
 #include "core/frame/Settings.h"
 #include "core/frame/VisualViewport.h"
 #include "core/frame/WebLocalFrameBase.h"
+#include "core/frame/WebViewFrameWidget.h"
 #include "core/html/HTMLTextAreaElement.h"
 #include "core/input/ContextMenuAllowedScope.h"
 #include "core/input/EventHandler.h"
@@ -74,7 +75,6 @@
 #include "web/WebDevToolsAgentImpl.h"
 #include "web/WebPagePopupImpl.h"
 #include "web/WebRemoteFrameImpl.h"
-#include "web/WebViewFrameWidget.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
index 9b2a552..e23768f 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -49,7 +49,6 @@
 #include "core/workers/WorkerContentSettingsClient.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "core/workers/WorkerInspectorProxy.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerScriptLoader.h"
 #include "core/workers/WorkerThreadStartupData.h"
 #include "platform/CrossThreadFunctional.h"
@@ -102,8 +101,6 @@
 
   web_view_->Close();
   main_frame_->Close();
-  if (loader_proxy_)
-    loader_proxy_->DetachProvider(this);
 }
 
 void WebSharedWorkerImpl::TerminateWorkerThread() {
@@ -252,14 +249,6 @@
   delete this;
 }
 
-ThreadableLoadingContext* WebSharedWorkerImpl::GetThreadableLoadingContext() {
-  if (!loading_context_) {
-    loading_context_ =
-        ThreadableLoadingContext::Create(*ToDocument(loading_document_.Get()));
-  }
-  return loading_context_;
-}
-
 void WebSharedWorkerImpl::Connect(
     std::unique_ptr<WebMessagePortChannel> web_channel) {
   DCHECK(IsMainThread());
@@ -384,10 +373,11 @@
   ParentFrameTaskRunners* task_runners =
       ParentFrameTaskRunners::Create(nullptr);
 
-  loader_proxy_ = WorkerLoaderProxy::Create(this);
   reporting_proxy_ = new WebSharedWorkerReportingProxyImpl(this, task_runners);
-  worker_thread_ =
-      SharedWorkerThread::Create(name_, loader_proxy_, *reporting_proxy_);
+  worker_thread_ = WTF::MakeUnique<SharedWorkerThread>(
+      name_,
+      ThreadableLoadingContext::Create(*ToDocument(loading_document_.Get())),
+      *reporting_proxy_);
   probe::scriptImported(loading_document_, main_script_loader_->Identifier(),
                         main_script_loader_->SourceText());
   main_script_loader_.Clear();
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
index 6d5f44e..d97176b9 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
@@ -35,7 +35,6 @@
 
 #include <memory>
 #include "core/dom/ExecutionContext.h"
-#include "core/workers/WorkerLoaderProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/Platform.h"
@@ -65,8 +64,7 @@
 // *OnWorkerThread or have header comments.
 class WebSharedWorkerImpl final : public WebFrameClient,
                                   public WebSharedWorker,
-                                  public WebDevToolsAgentClient,
-                                  private WorkerLoaderProxyProvider {
+                                  public WebDevToolsAgentClient {
  public:
   explicit WebSharedWorkerImpl(WebSharedWorkerClient*);
 
@@ -134,9 +132,6 @@
 
   void ConnectTaskOnWorkerThread(std::unique_ptr<WebMessagePortChannel>);
 
-  // WorkerLoaderProxyProvider
-  ThreadableLoadingContext* GetThreadableLoadingContext() override;
-
   // 'shadow page' - created to proxy loading requests from the worker.
   // Will be accessed by worker thread when posting tasks.
   Persistent<ExecutionContext> loading_document_;
@@ -160,8 +155,6 @@
   // Kept around only while main script loading is ongoing.
   RefPtr<WorkerScriptLoader> main_script_loader_;
 
-  RefPtr<WorkerLoaderProxy> loader_proxy_;
-
   WebURL url_;
   WebString name_;
   WebAddressSpace creation_address_space_;
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 14e6325..dbcceb8 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -757,6 +757,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("android_mojo_bindings") {
@@ -789,6 +792,9 @@
 
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 # The offscreen_canvas_mojo_bindings is separated from the rest of mojom files
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5fdc2582..6ed192b3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -46904,7 +46904,7 @@
 <histogram name="Omnibox.ProgressBarBreakPointUpdateCount"
     units="break point updates">
   <obsolete>
-    Obselete 05/16/2017. Data is unused (crbug.com/719801).
+    Obsolete 05/16/2017. Data is unused (crbug.com/719801).
   </obsolete>
   <owner>kkimlabs@chromium.org</owner>
   <summary>
@@ -46915,7 +46915,7 @@
 
 <histogram name="Omnibox.ProgressBarUpdateCount" units="frame updates">
   <obsolete>
-    Obselete 05/16/2017. Data is unused (crbug.com/719801).
+    Obsolete 05/16/2017. Data is unused (crbug.com/719801).
   </obsolete>
   <owner>kkimlabs@chromium.org</owner>
   <summary>
@@ -47520,7 +47520,7 @@
 
 <histogram name="OSX.CatSixtyFour" enum="CatSixtyFour">
   <obsolete>
-    Obselete as of Chrome 43. See OmahaProxy for more relevant statistics.
+    Obsolete as of Chrome 43. See OmahaProxy for more relevant statistics.
   </obsolete>
   <owner>mark@chromium.org</owner>
   <summary>The cat's flavor and how many bits there are in it.</summary>
@@ -84805,7 +84805,7 @@
 <histogram name="WinJumplist.DetailedFolderResultsDeleteUpdated"
     enum="JumplistIconsDetailedFolderOperationDeleteUpdatedCategory">
   <obsolete>
-    Obselete 03/20/2016. New metrics named WinJumplist.DeleteStatusJumpListIcons
+    Obsolete 03/20/2016. New metrics named WinJumplist.DeleteStatusJumpListIcons
     and WinJumplist.DeleteStatusJumpListIconsOld are used instead.
   </obsolete>
   <owner>chengx@chromium.org</owner>
@@ -84850,7 +84850,7 @@
 <histogram name="WinJumplist.FolderMoveResults"
     enum="JumplistIconsFolderMoveCategory">
   <obsolete>
-    Obselete 12/08/2016. DetailedFolderMoveResults is used for more detailed
+    Obsolete 12/08/2016. DetailedFolderMoveResults is used for more detailed
     analysis.
   </obsolete>
   <owner>chengx@chromium.org</owner>
@@ -84868,7 +84868,7 @@
 
 <histogram name="WinJumplist.FolderResults" enum="JumplisticonsfolderCategory">
   <obsolete>
-    Obselete 12/13/2016, as we are now recording DetailedFolderResults.
+    Obsolete 12/13/2016, as we are now recording DetailedFolderResults.
   </obsolete>
   <owner>chengx@chromium.org</owner>
   <summary>
diff --git a/ui/gfx/geometry/mojo/BUILD.gn b/ui/gfx/geometry/mojo/BUILD.gn
index 2dd850c..38c52b2 100644
--- a/ui/gfx/geometry/mojo/BUILD.gn
+++ b/ui/gfx/geometry/mojo/BUILD.gn
@@ -10,6 +10,9 @@
   sources = [
     "geometry.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("test_interfaces") {
diff --git a/url/mojo/BUILD.gn b/url/mojo/BUILD.gn
index 528e9f72..04aae07 100644
--- a/url/mojo/BUILD.gn
+++ b/url/mojo/BUILD.gn
@@ -8,6 +8,9 @@
   sources = [
     "url.mojom",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("url_mojom_origin") {
@@ -18,6 +21,9 @@
   public_deps = [
     ":url_mojom_gurl",
   ]
+
+  # TODO(crbug.com/699569): Convert to use the new JS bindings.
+  use_new_js_bindings = false
 }
 
 mojom("test_url_mojom_gurl") {