diff --git a/DEPS b/DEPS
index 7d6233ed..b43f0bd 100644
--- a/DEPS
+++ b/DEPS
@@ -115,11 +115,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '2e6db18c4309f7f2036e40abf77804086132c237',
+  'skia_revision': '32def82f1247ccf4121345390e4a73c4b2273bd7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'b4e322e3cc9db4831f5f4812759b1349acb96982',
+  'v8_revision': '5f69146b2adcf279e719a4c86722c8ae4e666bfd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -127,7 +127,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '7139b434210c8c168aece65022ee9196c2bf550b',
+  'angle_revision': '4622905b30d17428ece05c4d6f86e2b11e9ff217',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -239,7 +239,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '28c1fba1c02eb0c8fedb9794645e4a2dc06d1904',
+  'dawn_revision': '0d95887dbc948adc317959efd1639520b32b9b11',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -662,7 +662,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '6ecafca7571142b3cf941dac37e8d72806c7d4ce',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1b63735bf490b1c2d5a3e990dd2059b4ff76d3f3',
       'condition': 'checkout_linux',
   },
 
@@ -828,7 +828,7 @@
     Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e',
 
   'src/third_party/icu':
-    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '2823bdd7ed9022fafa0c3443ffde90e522d92b52',
+    Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '23de01679d298bf9fb964ebede32f2157729ba96',
 
   'src/third_party/icu4j': {
       'packages': [
@@ -951,7 +951,7 @@
 
   # Minizip library. Used on Chrome OS.
   'src/third_party/minizip/src': {
-      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '4d4c9db5b019e71b4a40fb41ab21fb47de12ae69',
+      'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '1ff40343b55e738d941abb51c70eddb803db16e2',
       'condition': 'checkout_linux',
   },
 
@@ -1019,7 +1019,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '2ffa75e376e4716c04edd2fb490beda9d4ba407a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '76717a36d3128515aefdb26c135fe951a2e85e48',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1182,7 +1182,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5b6cbd789b9b91b4e46dde883c9f2ecb31eddade',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'adae52b58844e110cfc577043ebb42c0ff0df3c6',
+    Var('webrtc_git') + '/src.git' + '@' + '194d4d20fbf9e4fbd9c673e7ec9e926abce7b685',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1213,7 +1213,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9f278bae3e807e47bd8c9d4eff46b246b5a9008f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b5c6e3aa4f146ece00fd470a6ad9929159d6fee1',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 5e2d0ee..fd177e3 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -20,6 +20,7 @@
 #include <limits>
 #include <vector>
 
+#include "base/bit_cast.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/no_destructor.h"
@@ -370,6 +371,16 @@
     output->clear();
 }
 
+#if defined(WCHAR_T_IS_UTF16)
+StringPiece16 CastToStringPiece16(WStringPiece wide) {
+  return StringPiece16(bit_cast<const char16*>(wide.data()), wide.size());
+}
+
+WStringPiece CastToWStringPiece(StringPiece16 utf16) {
+  return WStringPiece(bit_cast<const wchar_t*>(utf16.data()), utf16.size());
+}
+#endif  // defined(WCHAR_T_IS_UTF16)
+
 TrimPositions TrimWhitespace(const string16& input,
                              TrimPositions positions,
                              string16* output) {
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index d534590..f5f8da6 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -229,6 +229,15 @@
                                         const size_t byte_size,
                                         std::string* output);
 
+#if defined(WCHAR_T_IS_UTF16)
+// In case wchar_t is UTF-16 StringPiece16 and WStringPiece can be effieciently
+// converted into each other.
+// Note: These functions will only become useful once base::char16 is char16_t
+// on all platforms: https://crbug.com/911896
+BASE_EXPORT StringPiece16 CastToStringPiece16(WStringPiece wide);
+BASE_EXPORT WStringPiece CastToWStringPiece(StringPiece16 utf16);
+#endif  // defined(WCHAR_T_IS_UTF16)
+
 // Trims any whitespace from either end of the input string.
 //
 // The StringPiece versions return a substring referencing the input buffer.
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc
index cadb963..88a2520 100644
--- a/base/strings/utf_string_conversions.cc
+++ b/base/strings/utf_string_conversions.cc
@@ -9,6 +9,7 @@
 
 #include <type_traits>
 
+#include "base/bit_cast.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversion_utils.h"
@@ -306,12 +307,11 @@
 // Easy case since we can use the "utf" versions we already wrote above.
 
 bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) {
-  return UTF16ToUTF8(reinterpret_cast<const char16*>(src), src_len, output);
+  return UTF16ToUTF8(bit_cast<const char16*>(src), src_len, output);
 }
 
 std::string WideToUTF8(WStringPiece wide) {
-  return UTF16ToUTF8(
-      StringPiece16(reinterpret_cast<const char16*>(wide.data()), wide.size()));
+  return UTF16ToUTF8(CastToStringPiece16(wide));
 }
 
 #elif defined(WCHAR_T_IS_UTF32)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index a343dff..e57c350 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0fd351b28f70448aac649a9a22864c26d97b8eba
\ No newline at end of file
+5639aa6b5daf5c85a77d65dc2918efaa5b91ca51
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index db54ba6..11db295 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-bc53f844542bf4b95664f1d53e12c92fd42579b3
\ No newline at end of file
+61812e02a3d4422192b1749ddd912ad6be0f3e72
\ No newline at end of file
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 4b2fb090..8c04c7d 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -261,6 +261,9 @@
     // http://crbug.com/797998
     "race:content::SandboxIPCHandler::HandleLocaltime\n"
 
+    // http://crbug.com/910524
+    "race:base::subtle::ScopedTimeClockOverrides::ScopedTimeClockOverrides\n"
+
     // End of suppressions.
     ;  // Please keep this semicolon.
 
diff --git a/chrome/VERSION b/chrome/VERSION
index ea2ebfaa..9176e82 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=73
 MINOR=0
-BUILD=3643
+BUILD=3644
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index 9dc7e14..40c7a6f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -4,31 +4,56 @@
 
 package org.chromium.chrome.browser.autofill_assistant;
 
+import android.app.PendingIntent;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.chrome.browser.util.IntentUtils;
 
 import java.util.HashMap;
 import java.util.Map;
 
 /** Facade for starting Autofill Assistant on a custom tab. */
 public class AutofillAssistantFacade {
-    /** Prefix for Intent extras relevant to this feature. */
+    /**
+     * Prefix for Intent extras relevant to this feature.
+     *
+     * <p>Intent starting with this prefix are reported to the controller as parameters, except for
+     * the ones starting with {@code INTENT_SPECIAL_PREFIX}.
+     */
     private static final String INTENT_EXTRA_PREFIX =
             "org.chromium.chrome.browser.autofill_assistant.";
 
+    /** Prefix for intent extras which are not parameters. */
+    private static final String INTENT_SPECIAL_PREFIX = INTENT_EXTRA_PREFIX + "special.";
 
     /** Special parameter that enables the feature. */
     private static final String PARAMETER_ENABLED = "ENABLED";
 
-    /** Returns true if all conditions are satisfied to start Autofill Assistant. */
+    /**
+     * Boolean parameter that trusted apps can use to declare that the user has agreed to Terms and
+     * Conditions that cover the use of Autofill Assistant in Chrome for that specific invocation.
+     */
+    private static final String AGREED_TO_TC = "AGREED_TO_TC";
+
+    /** Pending intent sent by first-party apps. */
+    private static final String PENDING_INTENT_NAME = INTENT_SPECIAL_PREFIX + "PENDING_INTENT";
+
+    /** Package names of trusted first-party apps, from the pending intent. */
+    private static final String[] TRUSTED_CALLER_PACKAGES = {
+            "com.google.android.googlequicksearchbox", // GSA
+    };
+
+    /** Returns true if conditions are satisfied to attempt to start Autofill Assistant. */
     public static boolean isConfigured(@Nullable Bundle intentExtras) {
         return getBooleanParameter(intentExtras, PARAMETER_ENABLED);
     }
@@ -47,6 +72,10 @@
         final AbstractAutofillAssistantUiController targetController = controller == null
                 ? new AutofillAssistantUiController(activity, parameters)
                 : controller;
+        if (canStart(activity.getInitialIntent())) {
+            initiateAutofillAssistant(activity, parameters, targetController);
+            return;
+        }
         if (AutofillAssistantPreferencesUtil.getShowOnboarding()) {
             FirstRunScreen.show(activity, (result) -> {
                 if (result) initiateAutofillAssistant(activity, parameters, targetController);
@@ -54,9 +83,6 @@
             return;
         }
 
-        if (AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()) {
-            initiateAutofillAssistant(activity, parameters, targetController);
-        }
         // We don't have consent to start Autofill Assistant and cannot show initial screen.
         // Do nothing.
     }
@@ -101,7 +127,8 @@
 
     /** Return the value if the given boolean parameter from the extras. */
     private static boolean getBooleanParameter(@Nullable Bundle extras, String parameterName) {
-        return extras != null && extras.getBoolean(INTENT_EXTRA_PREFIX + parameterName, false);
+        return extras != null
+                && IntentUtils.safeGetBoolean(extras, INTENT_EXTRA_PREFIX + parameterName, false);
     }
 
     /** Returns a map containing the extras starting with {@link #INTENT_EXTRA_PREFIX}. */
@@ -109,7 +136,7 @@
         Map<String, String> result = new HashMap<>();
         if (extras != null) {
             for (String key : extras.keySet()) {
-                if (key.startsWith(INTENT_EXTRA_PREFIX)) {
+                if (key.startsWith(INTENT_EXTRA_PREFIX) && !key.startsWith(INTENT_SPECIAL_PREFIX)) {
                     result.put(key.substring(INTENT_EXTRA_PREFIX.length()),
                             extras.get(key).toString());
                 }
@@ -117,4 +144,37 @@
         }
         return result;
     }
+
+    /** Returns {@code true} if we can start right away. */
+    private static boolean canStart(Intent intent) {
+        return (AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()
+                       && !AutofillAssistantPreferencesUtil.getShowOnboarding())
+                || hasAgreedToTc(intent);
+    }
+
+    /**
+     * Returns {@code true} if the user has already agreed to specific terms and conditions for the
+     * current task, that cover the use of autofill assistant. There's no need to show the generic
+     * first-time screen for that call.
+     */
+    private static boolean hasAgreedToTc(Intent intent) {
+        return getBooleanParameter(intent.getExtras(), AGREED_TO_TC)
+                && callerIsOnWhitelist(intent, TRUSTED_CALLER_PACKAGES);
+    }
+
+    /** Returns {@code true} if the caller is on the given whitelist. */
+    private static boolean callerIsOnWhitelist(Intent intent, String[] whitelist) {
+        PendingIntent pendingIntent =
+                IntentUtils.safeGetParcelableExtra(intent, PENDING_INTENT_NAME);
+        if (pendingIntent == null) {
+            return false;
+        }
+        String packageName = ApiCompatibilityUtils.getCreatorPackage(pendingIntent);
+        for (String whitelistedPackage : whitelist) {
+            if (whitelistedPackage.equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 8074af7..0737953 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-73.0.3641.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-73.0.3642.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index aa50fc5..b7bcc95 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6703,7 +6703,10 @@
         Help improve Chrome and its security
       </message>
       <message name="IDS_SYNC_CONFIRMATION_UNITY_IMPROVE_CHROME_INFO_DESC" desc="Description in the information about improving Chrome on the sync confirmation dialog when Unity is enabled">
-        Anonymous system and usage data will be sent to Google.
+        Sends some system information and page content to Google anonymously.
+      </message>
+      <message name="IDS_SYNC_CONFIRMATION_UNITY_SETTINGS_INFO" desc="Information about customizing Sync settings in the sync confirmation dialog when Unity is enabled">
+        You can customize these settings anytime.
       </message>
 
       <!-- "Chrome sync" is the Google Cloud Based service used for sync. Thus this string resource is set to "Chrome sync" even for Chromium builds. -->
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 686d0f7..edb286d 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3582,9 +3582,6 @@
   <message name="IDS_SETTINGS_SYNC" desc="Name of the sync service.">
     Sync
   </message>
-  <message name="IDS_SETTINGS_SYNC_UNIFIED_CONSENT" desc="Name of the sync service when unified consent is enabled.">
-    Sync and personalization
-  </message>
   <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL" desc="Title for a section that shows options for various Google services">
     Other Google services
   </message>
@@ -3594,6 +3591,12 @@
   <message name="IDS_SETTINGS_SYNC_PAGE_TITLE" desc="Name of the settings page which manages syncing data between multiple browser instances with the same Google profile.">
     Advanced sync settings
   </message>
+  <message name="IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE" desc="Name of the settings page which manages data used by sync.">
+    Manage sync
+  </message>
+  <message name="IDS_SETTINGS_SYNC_ADVANCED_ROW_CUSTOM_SETTINGS" desc="Sublabel for the sync advanced row to inform that the user has custom sync settings, i.e. is not syncing everything.">
+    Custom settings
+  </message>
   <message name="IDS_SETTINGS_SYNC_LOADING" desc="The message shown when waiting for the sync backend to start up.">
     Please wait...
   </message>
@@ -3601,6 +3604,9 @@
     <message name="IDS_SETTINGS_SYNC_WILL_START" desc="The message to tell users that sync will start once they leave the sync setup page.">
       Sync will start once you leave this page
     </message>
+    <message name="IDS_SETTINGS_SYNC_WILL_START_UNITY" desc="The message to tell users that sync will start once they leave the sync setup page when unified consent is enabled.">
+      Sync will start once you leave sync settings
+    </message>
     <message name="IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC" desc="The label of button that allows user to cancel sync.">
       Cancel sync
     </message>
@@ -3660,6 +3666,9 @@
   <message name="IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE" desc="Title for the link to manage Chrome Sync data via Google Dashboard.">
     Manage synced data on Google Dashboard
   </message>
+   <message name="IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT" desc="Title for the link to manage Chrome Sync data via Google Dashboard when unified consent is enabled.">
+    Data from Chrome sync
+  </message>
   <message name="IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE" desc="Title for the section where the user enters the passphrase.">
     Encryption options
   </message>
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm
index 1dbba3b..708d726 100644
--- a/chrome/app_shim/chrome_main_app_mode_mac.mm
+++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -30,6 +30,7 @@
 #include "chrome/app/chrome_crash_reporter_client.h"
 #include "chrome/app_shim/app_shim_controller.h"
 #include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/crash/content/app/crashpad.h"
@@ -206,9 +207,12 @@
   std::string locale = l10n_util::NormalizeLocale(
       l10n_util::GetApplicationLocale(preferred_localization));
 
-  // Load localized strings.
+  // Load localized strings and mouse cursor images.
   ui::ResourceBundle::InitSharedInstanceWithLocale(
-      locale, NULL, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
+      locale, NULL, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
+
+  ChromeContentClient chrome_content_client;
+  content::SetContentClient(&chrome_content_client);
 
   // Launch the IO thread.
   base::Thread::Options io_thread_options;
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
index 1d7cad04..5defa276 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -8,6 +8,7 @@
 
 #include "apps/app_lifetime_monitor_factory.h"
 #include "apps/launcher.h"
+#include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -114,13 +115,10 @@
  public:
   EnableViaPrompt(Profile* profile,
                   const std::string& extension_id,
-                  const base::Callback<void()>& callback)
+                  base::OnceCallback<void()> callback)
       : profile_(profile),
         extension_id_(extension_id),
-        callback_(callback) {
-  }
-
-  ~EnableViaPrompt() override {}
+        callback_(std::move(callback)) {}
 
   void Run() {
     flow_.reset(new ExtensionEnableFlow(profile_, extension_id_, this));
@@ -128,20 +126,19 @@
   }
 
  private:
+  ~EnableViaPrompt() override { std::move(callback_).Run(); }
+
   // ExtensionEnableFlowDelegate overrides.
   void ExtensionEnableFlowFinished() override {
-    callback_.Run();
     delete this;
   }
-
   void ExtensionEnableFlowAborted(bool user_initiated) override {
-    callback_.Run();
     delete this;
   }
 
   Profile* profile_;
   std::string extension_id_;
-  base::Callback<void()> callback_;
+  base::OnceCallback<void()> callback_;
   std::unique_ptr<ExtensionEnableFlow> flow_;
 
   DISALLOW_COPY_AND_ASSIGN(EnableViaPrompt);
@@ -209,8 +206,8 @@
 void ExtensionAppShimHandler::Delegate::EnableExtension(
     Profile* profile,
     const std::string& extension_id,
-    const base::Callback<void()>& callback) {
-  (new EnableViaPrompt(profile, extension_id, callback))->Run();
+    base::OnceCallback<void()> callback) {
+  (new EnableViaPrompt(profile, extension_id, std::move(callback)))->Run();
 }
 
 void ExtensionAppShimHandler::Delegate::LaunchApp(
@@ -560,8 +557,8 @@
 
   delegate_->EnableExtension(
       profile, app_id,
-      base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled,
-                 weak_factory_.GetWeakPtr(), host->GetWeakPtr(), files));
+      base::BindOnce(&ExtensionAppShimHandler::OnExtensionEnabled,
+                     weak_factory_.GetWeakPtr(), host->GetWeakPtr(), files));
 }
 
 void ExtensionAppShimHandler::OnExtensionEnabled(
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
index 955bd49..258a2292 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
@@ -69,7 +69,7 @@
                                     const base::FilePath& profile_path);
     virtual void EnableExtension(Profile* profile,
                                  const std::string& extension_id,
-                                 const base::Callback<void()>& callback);
+                                 base::OnceCallback<void()> callback);
     virtual void LaunchApp(Profile* profile,
                            const extensions::Extension* extension,
                            const std::vector<base::FilePath>& files);
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index 8710412..61b8b66 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
+#include "base/test/mock_callback.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -22,6 +23,13 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// Templates for calling base::OnceCallback from gmock actions.
+ACTION_TEMPLATE(RunOnceCallback,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return std::move(std::get<k>(args)).Run();
+}
+
 namespace apps {
 
 using extensions::Extension;
@@ -51,9 +59,14 @@
 
   MOCK_METHOD2(MaybeGetAppExtension,
                const Extension*(content::BrowserContext*, const std::string&));
-  MOCK_METHOD3(EnableExtension, void(Profile*,
-                                     const std::string&,
-                                     const base::Callback<void()>&));
+  // Note that DoEnableExtension takes |callback| as a reference.
+  void EnableExtension(Profile* profile,
+                       const std::string& app_id,
+                       base::OnceCallback<void()> callback) {
+    DoEnableExtension(profile, app_id, callback);
+  }
+  MOCK_METHOD3(DoEnableExtension,
+               void(Profile*, const std::string&, base::OnceCallback<void()>&));
   MOCK_METHOD3(LaunchApp,
                void(Profile*,
                     const Extension*,
@@ -89,10 +102,6 @@
     return callbacks_.erase(path);
   }
 
-  void RunCallback(const base::Callback<void()>& callback) {
-    callback.Run();
-  }
-
  private:
   std::map<base::FilePath, base::OnceCallback<void(Profile*)>> callbacks_;
   AppShimHost* host_for_create_ = nullptr;
@@ -400,8 +409,8 @@
   // App not found.
   EXPECT_CALL(*delegate_, MaybeGetAppExtension(&profile_a_, kTestAppIdA))
       .WillRepeatedly(Return(static_cast<const Extension*>(NULL)));
-  EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _))
-      .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback)));
+  EXPECT_CALL(*delegate_, DoEnableExtension(&profile_a_, kTestAppIdA, _))
+      .WillOnce(RunOnceCallback<2>());
   NormalLaunch(bootstrap_aa_, host_aa_);
   EXPECT_EQ(APP_SHIM_LAUNCH_APP_NOT_FOUND, *bootstrap_aa_result_);
 }
@@ -411,8 +420,8 @@
   EXPECT_CALL(*delegate_, MaybeGetAppExtension(&profile_a_, kTestAppIdA))
       .WillOnce(Return(static_cast<const Extension*>(NULL)))
       .WillRepeatedly(Return(extension_a_.get()));
-  EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _))
-      .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback)));
+  EXPECT_CALL(*delegate_, DoEnableExtension(&profile_a_, kTestAppIdA, _))
+      .WillOnce(RunOnceCallback<2>());
   NormalLaunch(bootstrap_aa_, host_aa_);
 }
 
diff --git a/chrome/browser/badging/badge_service_impl.cc b/chrome/browser/badging/badge_service_impl.cc
index 3f13350..56786ba 100644
--- a/chrome/browser/badging/badge_service_impl.cc
+++ b/chrome/browser/badging/badge_service_impl.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/extension.h"
@@ -36,7 +37,7 @@
 
   badge_manager_->UpdateBadge(extension->id(), base::nullopt);
 #else
-  if (!is_hosted_app_)
+  if (!IsInApp())
     return;
 
   delegate_->SetBadge(web_contents_);
@@ -52,7 +53,7 @@
 
   badge_manager_->ClearBadge(extension->id());
 #else
-  if (!is_hosted_app_)
+  if (!IsInApp())
     return;
 
   delegate_->ClearBadge(web_contents_);
@@ -66,13 +67,13 @@
       render_frame_host_(render_frame_host) {
   web_contents_ = content::WebContents::FromRenderFrameHost(render_frame_host_);
   browser_context_ = web_contents_->GetBrowserContext();
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
+  hosted_app_controller_ = browser->hosted_app_controller();
 
 #if defined(OS_CHROMEOS)
   badge_manager_ = badging::BadgeManagerFactory::GetInstance()->GetForProfile(
       Profile::FromBrowserContext(browser_context_));
 #else
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
-  is_hosted_app_ = browser->hosted_app_controller();
   delegate_ = browser->window()->GetBadgeServiceDelegate();
 #endif
 }
@@ -85,3 +86,10 @@
   return extensions::util::GetInstalledPwaForUrl(
       browser_context_, render_frame_host_->GetLastCommittedURL());
 }
+
+bool BadgeServiceImpl::IsInApp() {
+  return hosted_app_controller_ &&
+         extensions::IsSameScope(hosted_app_controller_->GetAppLaunchURL(),
+                                 web_contents_->GetLastCommittedURL(),
+                                 web_contents_->GetBrowserContext());
+}
diff --git a/chrome/browser/badging/badge_service_impl.h b/chrome/browser/badging/badge_service_impl.h
index 4f811fa..23402fc 100644
--- a/chrome/browser/badging/badge_service_impl.h
+++ b/chrome/browser/badging/badge_service_impl.h
@@ -16,6 +16,7 @@
 
 namespace extensions {
 class Extension;
+class HostedAppBrowserController;
 }
 
 #if defined(OS_CHROMEOS)
@@ -44,15 +45,16 @@
   ~BadgeServiceImpl() override;
 
   const extensions::Extension* ExtensionFromLastUrl();
+  bool IsInApp();
 
   content::RenderFrameHost* render_frame_host_;
   content::BrowserContext* browser_context_;
   content::WebContents* web_contents_;
+  extensions::HostedAppBrowserController* hosted_app_controller_;
 #if defined(OS_CHROMEOS)
   badging::BadgeManager* badge_manager_;
 #else
   BadgeServiceDelegate* delegate_;
-  bool is_hosted_app_;
 #endif
 };
 
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc b/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc
index 53531ec..5d597fb 100644
--- a/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc
+++ b/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc
@@ -126,6 +126,7 @@
 AlternativeBrowserDriver::~AlternativeBrowserDriver() {}
 
 AlternativeBrowserDriverImpl::AlternativeBrowserDriverImpl() {}
+
 AlternativeBrowserDriverImpl::~AlternativeBrowserDriverImpl() {}
 
 void AlternativeBrowserDriverImpl::SetBrowserPath(base::StringPiece path) {
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_win.cc b/chrome/browser/browser_switcher/alternative_browser_driver_win.cc
index 707385f..12b74ae5 100644
--- a/chrome/browser/browser_switcher/alternative_browser_driver_win.cc
+++ b/chrome/browser/browser_switcher/alternative_browser_driver_win.cc
@@ -134,6 +134,7 @@
 AlternativeBrowserDriver::~AlternativeBrowserDriver() {}
 
 AlternativeBrowserDriverImpl::AlternativeBrowserDriverImpl() {}
+
 AlternativeBrowserDriverImpl::~AlternativeBrowserDriverImpl() {}
 
 void AlternativeBrowserDriverImpl::SetBrowserPath(base::StringPiece path) {
diff --git a/chrome/browser/browser_switcher/alternative_browser_launcher.cc b/chrome/browser/browser_switcher/alternative_browser_launcher.cc
index 37d5d00..9b228d4 100644
--- a/chrome/browser/browser_switcher/alternative_browser_launcher.cc
+++ b/chrome/browser/browser_switcher/alternative_browser_launcher.cc
@@ -46,24 +46,29 @@
 AlternativeBrowserLauncherImpl::~AlternativeBrowserLauncherImpl() {}
 
 void AlternativeBrowserLauncherImpl::OnAltBrowserPathChanged() {
+  std::string path = prefs_->GetString(prefs::kAlternativeBrowserPath);
+
   // This pref is sensitive. Only set through policies.
   if (!prefs_->IsManagedPreference(prefs::kAlternativeBrowserPath))
-    return;
+    path = "";
 
   // This string could be a variable, e.g. "${ie}". Let the driver decide what
   // to do with it.
-  driver_->SetBrowserPath(prefs_->GetString(prefs::kAlternativeBrowserPath));
+  driver_->SetBrowserPath(path);
 }
 
 void AlternativeBrowserLauncherImpl::OnAltBrowserParametersChanged() {
+  const base::ListValue* params =
+      prefs_->GetList(prefs::kAlternativeBrowserParameters);
+  const base::ListValue empty_list;
+
   // This pref is sensitive. Only set through policies.
   if (!prefs_->IsManagedPreference(prefs::kAlternativeBrowserParameters))
-    return;
+    params = &empty_list;
 
   // This string could contain a placeholder, e.g. "${url}". Let the driver
   // decide what to do with it.
-  driver_->SetBrowserParameters(
-      prefs_->GetList(prefs::kAlternativeBrowserParameters));
+  driver_->SetBrowserParameters(params);
 }
 
 bool AlternativeBrowserLauncherImpl::Launch(const GURL& url) const {
diff --git a/chrome/browser/browser_switcher/alternative_browser_launcher_unittest.cc b/chrome/browser/browser_switcher/alternative_browser_launcher_unittest.cc
index 400104c19..1e9d0fc 100644
--- a/chrome/browser/browser_switcher/alternative_browser_launcher_unittest.cc
+++ b/chrome/browser/browser_switcher/alternative_browser_launcher_unittest.cc
@@ -41,6 +41,12 @@
     prefs_.registry()->RegisterStringPref(prefs::kAlternativeBrowserPath, "");
     prefs_.registry()->RegisterListPref(prefs::kAlternativeBrowserParameters);
     driver_ = new MockAlternativeBrowserDriver();
+    EXPECT_CALL(*driver_, SetBrowserPath(_))
+        .WillOnce(Invoke([](base::StringPiece path) { EXPECT_EQ("", path); }));
+    EXPECT_CALL(*driver_, SetBrowserParameters(_))
+        .WillOnce(Invoke([](const base::ListValue* parameters) {
+          EXPECT_TRUE(parameters->GetList().empty());
+        }));
     launcher_ = std::make_unique<AlternativeBrowserLauncherImpl>(
         &prefs_, std::unique_ptr<AlternativeBrowserDriver>(driver_));
   }
@@ -87,9 +93,13 @@
 }
 
 TEST_F(AlternativeBrowserLauncherTest, LaunchIgnoresNonManagedPrefs) {
-  EXPECT_CALL(driver(), SetBrowserPath(_)).Times(0);
+  EXPECT_CALL(driver(), SetBrowserPath(_))
+      .WillOnce(Invoke([](base::StringPiece path) { EXPECT_EQ("", path); }));
+  EXPECT_CALL(driver(), SetBrowserParameters(_))
+      .WillOnce(Invoke([](const base::ListValue* parameters) {
+        EXPECT_TRUE(parameters->GetList().empty());
+      }));
   prefs()->Set(prefs::kAlternativeBrowserPath, base::Value("evil.exe"));
-  EXPECT_CALL(driver(), SetBrowserParameters(_)).Times(0);
   std::vector<base::Value> params;
   params.emplace_back("--launch-missiles");
   prefs()->Set(prefs::kAlternativeBrowserParameters,
diff --git a/chrome/browser/browser_switcher/browser_switcher_sitelist.cc b/chrome/browser/browser_switcher/browser_switcher_sitelist.cc
index 47be432..faa735b 100644
--- a/chrome/browser/browser_switcher/browser_switcher_sitelist.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_sitelist.cc
@@ -188,9 +188,12 @@
 }
 
 void BrowserSwitcherSitelistImpl::OnUrlListChanged() {
+  const base::ListValue* url_list = prefs_->GetList(prefs::kUrlList);
+  const base::ListValue empty_list;
+
   // This pref is sensitive. Only set through policies.
   if (!prefs_->IsManagedPreference(prefs::kUrlList))
-    return;
+    url_list = &empty_list;
 
   UMA_HISTOGRAM_COUNTS_100000(
       "BrowserSwitcher.UrlListSize",
@@ -198,7 +201,7 @@
 
   chrome_policies_.sitelist.clear();
   bool has_wildcard = false;
-  for (const auto& url : *prefs_->GetList(prefs::kUrlList)) {
+  for (const auto& url : *url_list) {
     chrome_policies_.sitelist.push_back(url.GetString());
     if (url.GetString() == "*")
       has_wildcard = true;
@@ -208,9 +211,12 @@
 }
 
 void BrowserSwitcherSitelistImpl::OnGreylistChanged() {
+  const base::ListValue* greylist = prefs_->GetList(prefs::kUrlGreylist);
+  const base::ListValue empty_list;
+
   // This pref is sensitive. Only set through policies.
   if (!prefs_->IsManagedPreference(prefs::kUrlGreylist))
-    return;
+    greylist = &empty_list;
 
   UMA_HISTOGRAM_COUNTS_100000(
       "BrowserSwitcher.GreylistSize",
@@ -218,7 +224,7 @@
 
   chrome_policies_.greylist.clear();
   bool has_wildcard = false;
-  for (const auto& url : *prefs_->GetList(prefs::kUrlGreylist)) {
+  for (const auto& url : *greylist) {
     chrome_policies_.greylist.push_back(url.GetString());
     if (url.GetString() == "*")
       has_wildcard = true;
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index ba25ce7a..21eec18c 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -95,8 +95,8 @@
                         content::BrowserContext* browser_context) {
     response_delegate_.reset(new api_test_utils::SendResponseHelper(function));
     std::unique_ptr<base::ListValue> parsed_args(utils::ParseList(args));
-    EXPECT_TRUE(parsed_args.get()) <<
-        "Could not parse extension function arguments: " << args;
+    EXPECT_TRUE(parsed_args.get())
+        << "Could not parse extension function arguments: " << args;
     function->SetArgs(parsed_args.get());
 
     if (!function->extension()) {
@@ -119,8 +119,8 @@
 
   base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
     RunMessageLoopUntilResponse();
-    EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
-                                              << function->GetError();
+    EXPECT_TRUE(function->GetError().empty())
+        << "Unexpected error: " << function->GetError();
     const base::Value* single_result = NULL;
     if (function->GetResultList() != NULL &&
         function->GetResultList()->Get(0, &single_result)) {
@@ -431,9 +431,7 @@
     // creating the browser so that a bunch of classes don't register as
     // observers and end up needing to unregister when the fake is substituted.
     IdentityTestEnvironmentProfileAdaptor::
-        SetIdentityTestEnvironmentFactoriesOnBrowserContext(
-            context,
-            /*create_fake_url_loader_factory_for_cookie_requests=*/false);
+        SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
 
     // Ensure that AccountFetcherService is (1) created at all and (2) created
     // early enough for it to observe the Profile initialization process and
@@ -737,12 +735,7 @@
   }
 
  protected:
-  enum OAuth2Fields {
-    NONE = 0,
-    CLIENT_ID = 1,
-    SCOPES = 2,
-    AS_COMPONENT = 4
-  };
+  enum OAuth2Fields { NONE = 0, CLIENT_ID = 1, SCOPES = 2, AS_COMPONENT = 4 };
 
   void SetUpOnMainThread() override {
     IdentityTestWithSignin::SetUpOnMainThread();
@@ -828,34 +821,31 @@
   std::set<std::string> oauth_scopes_;
 };
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NoClientId) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoClientId) {
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(SCOPES));
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_EQ(std::string(errors::kInvalidClientId), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NoScopes) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoScopes) {
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID));
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_EQ(std::string(errors::kInvalidScopes), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NonInteractiveNotSignedIn) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveNotSignedIn) {
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
@@ -889,8 +879,7 @@
 }
 #endif
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NonInteractiveMintFailure) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveMintFailure) {
   SignIn("primary@example.com");
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -909,8 +898,8 @@
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
   func->set_login_access_token_result(false);
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
                                base::CompareCase::INSENSITIVE_ASCII));
 }
@@ -1001,8 +990,7 @@
 }
 #endif
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NoOptionsSuccess) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoOptionsSuccess) {
   SignIn("primary@example.com");
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -1019,8 +1007,7 @@
             GetCachedToken(std::string()).status());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NonInteractiveSuccess) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveSuccess) {
   SignIn("primary@example.com");
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -1164,8 +1151,7 @@
 }
 #endif
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       InteractiveApprovalAborted) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveApprovalAborted) {
   SignIn("primary@example.com");
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
@@ -1274,10 +1260,9 @@
   error_map.insert(std::make_pair(
       "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
 
-  for (std::map<std::string, std::string>::const_iterator
-           it = error_map.begin();
-       it != error_map.end();
-       ++it) {
+  for (std::map<std::string, std::string>::const_iterator it =
+           error_map.begin();
+       it != error_map.end(); ++it) {
     scoped_refptr<FakeGetAuthTokenFunction> func(
         new FakeGetAuthTokenFunction());
     func->set_extension(extension.get());
@@ -1477,8 +1462,8 @@
 
   // Non-interactive requests fail without hitting GAIA, because a
   // consent UI is known to be up.
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_EQ(std::string(errors::kNoGrant), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
@@ -1486,8 +1471,7 @@
   QueueRequestComplete(type, &queued_request);
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       NonInteractiveCacheHit) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveCacheHit) {
   SignIn("primary@example.com");
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
@@ -1521,15 +1505,14 @@
   SetCachedToken(token);
 
   // Should return an error without a GAIA request.
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[{}]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_EQ(std::string(errors::kNoGrant), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
 }
 
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       InteractiveCacheHit) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveCacheHit) {
   SignIn("primary@example.com");
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
@@ -1569,8 +1552,7 @@
 // The interactive login UI is never shown on ChromeOS, so tests of the
 // interactive login flow being successful are not relevant on that platform.
 #if !defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
-                       LoginInvalidatesTokenCache) {
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, LoginInvalidatesTokenCache) {
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
   func->set_extension(extension.get());
@@ -1968,7 +1950,6 @@
   EXPECT_TRUE(base::ContainsKey(token_key->scopes, "bar"));
 }
 
-
 #if defined(OS_CHROMEOS)
 class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest {
  public:
@@ -2017,8 +1998,8 @@
       base::WrapUnique(user_manager_));
   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
   func->set_extension(CreateTestExtension("test-id"));
-  std::string error = utils::RunFunctionAndReturnError(
-      func.get(), "[]", browser());
+  std::string error =
+      utils::RunFunctionAndReturnError(func.get(), "[]", browser());
   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
@@ -2042,7 +2023,6 @@
 
 #endif
 
-
 class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
  protected:
   bool InvalidateDefaultToken() {
@@ -2060,8 +2040,8 @@
   }
 
   void SetCachedToken(const IdentityTokenCacheValue& token_data) {
-    ExtensionTokenKey key(
-        kExtensionId, "test@example.com", std::set<std::string>());
+    ExtensionTokenKey key(kExtensionId, "test@example.com",
+                          std::set<std::string>());
     id_api()->SetCachedToken(key, token_data);
   }
 
@@ -2138,8 +2118,8 @@
 
   WaitForGURLAndCloseWindow popup_observer(auth_url);
 
-  std::string args = "[{\"interactive\": true, \"url\": \"" +
-      auth_url.spec() + "\"}]";
+  std::string args =
+      "[{\"interactive\": true, \"url\": \"" + auth_url.spec() + "\"}]";
   RunFunctionAsync(function.get(), args);
 
   popup_observer.Wait();
@@ -2161,8 +2141,8 @@
       ExtensionBuilder("Test").Build());
   function->set_extension(empty_extension.get());
 
-  std::string args = "[{\"interactive\": false, \"url\": \"" +
-      auth_url.spec() + "\"}]";
+  std::string args =
+      "[{\"interactive\": false, \"url\": \"" + auth_url.spec() + "\"}]";
   std::string error =
       utils::RunFunctionAndReturnError(function.get(), args, browser());
 
@@ -2182,8 +2162,8 @@
       ExtensionBuilder("Test").Build());
   function->set_extension(empty_extension.get());
 
-  std::string args = "[{\"interactive\": true, \"url\": \"" +
-      auth_url.spec() + "\"}]";
+  std::string args =
+      "[{\"interactive\": true, \"url\": \"" + auth_url.spec() + "\"}]";
   std::string error =
       utils::RunFunctionAndReturnError(function.get(), args, browser());
 
@@ -2210,8 +2190,8 @@
             url);
 }
 
-IN_PROC_BROWSER_TEST_F(
-    LaunchWebAuthFlowFunctionTest, InteractiveFirstNavigationSuccess) {
+IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,
+                       InteractiveFirstNavigationSuccess) {
   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
       new IdentityLaunchWebAuthFlowFunction());
   scoped_refptr<const Extension> empty_extension(
@@ -2246,8 +2226,8 @@
   function->set_extension(empty_extension.get());
 
   function->InitFinalRedirectURLPrefixForTest("abcdefghij");
-  std::string args = "[{\"interactive\": true, \"url\": \"" +
-      auth_url.spec() + "\"}]";
+  std::string args =
+      "[{\"interactive\": true, \"url\": \"" + auth_url.spec() + "\"}]";
   std::unique_ptr<base::Value> value(
       utils::RunFunctionAndReturnSingleResult(function.get(), args, browser()));
 
diff --git a/chrome/browser/extensions/api/management/management_apitest.cc b/chrome/browser/extensions/api/management/management_apitest.cc
index 836fac0..cfea99a 100644
--- a/chrome/browser/extensions/api/management/management_apitest.cc
+++ b/chrome/browser/extensions/api/management/management_apitest.cc
@@ -253,8 +253,8 @@
   ASSERT_TRUE(app_browser->is_app());
 }
 
-// Disabled: http://crbug.com/230165
-#if defined(OS_WIN)
+// Disabled: crbug.com/230165, crbug.com/915339
+#if defined(OS_WIN) || defined(OS_MACOSX)
 #define MAYBE_LaunchTabApp DISABLED_LaunchTabApp
 #else
 #define MAYBE_LaunchTabApp LaunchTabApp
@@ -320,7 +320,13 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, LaunchType) {
+// Flaky on MacOS: crbug.com/915339
+#if defined(OS_MACOSX)
+#define MAYBE_LaunchType DISABLED_LaunchType
+#else
+#define MAYBE_LaunchType LaunchType
+#endif
+IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, MAYBE_LaunchType) {
   LoadExtensions();
   base::FilePath basedir = test_data_dir_.AppendASCII("management");
   LoadNamedExtension(basedir, "packaged_app");
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
index 1d55a6d8..17fb89b 100644
--- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -323,6 +323,7 @@
   manifest.scope = GURL(kAppScope);
   blink::Manifest::ImageResource icon;
   icon.src = GURL(kAppIconURL1);
+  icon.purpose = {blink::Manifest::ImageResource::Purpose::ANY};
   manifest.icons.push_back(icon);
   icon.src = GURL(kAppIconURL2);
   manifest.icons.push_back(icon);
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc
index 258007c..3013ba4 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -13,8 +13,6 @@
 #include "base/optional.h"
 #include "base/system/sys_info.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
-#include "chrome/browser/predictors/loading_predictor.h"
-#include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "components/search_engines/template_url_service.h"
@@ -115,12 +113,7 @@
       preconnect_origin_score_threshold_(base::GetFieldTrialParamByFeatureAsInt(
           blink::features::kRecordAnchorMetricsVisible,
           "preconnect_origin_score_threshold",
-          0)),
-      same_origin_preconnecting_allowed_(
-          base::GetFieldTrialParamByFeatureAsBool(
-              blink::features::kRecordAnchorMetricsVisible,
-              "same_origin_preconnecting_allowed",
-              false))
+          0))
 #ifdef OS_ANDROID
       ,
       application_status_listener_(
@@ -281,40 +274,20 @@
 
 void NavigationPredictor::TakeActionNowOnTabOrAppVisibilityChange(
     Action log_action) {
-  MaybePreconnectNow(log_action);
-}
-
-void NavigationPredictor::MaybePreconnectNow(Action log_action) {
-  base::Optional<url::Origin> preconnect_origin = preconnect_origin_;
-
-  if (prefetch_url_ && !preconnect_origin) {
+  base::Optional<url::Origin> preconnect_origin;
+  if (prefetch_url_) {
     // Preconnect to the origin of the prefetch URL.
     preconnect_origin = url::Origin::Create(prefetch_url_.value());
   }
 
   if (!preconnect_origin)
     return;
-  if (preconnect_origin->scheme() != url::kHttpScheme &&
-      preconnect_origin->scheme() != url::kHttpsScheme) {
-    return;
-  }
 
   std::string action_histogram_name =
       source_is_default_search_engine_page_
           ? "NavigationPredictor.OnDSE.ActionTaken"
           : "NavigationPredictor.OnNonDSE.ActionTaken";
   base::UmaHistogramEnumeration(action_histogram_name, log_action);
-
-  if (!same_origin_preconnecting_allowed_)
-    return;
-
-  auto* loading_predictor = predictors::LoadingPredictorFactory::GetForProfile(
-      Profile::FromBrowserContext(browser_context_));
-  GURL preconnect_url_serialized(preconnect_origin->Serialize());
-  DCHECK(preconnect_url_serialized.is_valid());
-  loading_predictor->PrepareForPageLoad(
-      preconnect_url_serialized, predictors::HintOrigin::NAVIGATION_PREDICTOR,
-      true);
 }
 
 SiteEngagementService* NavigationPredictor::GetEngagementService() const {
@@ -762,7 +735,7 @@
       GetOriginToPreconnect(document_origin, sorted_navigation_scores);
   if (preconnect_origin_.has_value()) {
     DCHECK_EQ(document_origin.host(), preconnect_origin_->host());
-    MaybePreconnectNow(Action::kPreconnect);
+    base::UmaHistogramEnumeration(action_histogram_name, Action::kPreconnect);
     return;
   }
 
@@ -927,9 +900,6 @@
     base::android::ApplicationState application_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!application_status_listener_)
-    return;
-
   if (application_state_ !=
           base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES ||
       application_state !=
@@ -944,9 +914,7 @@
   TakeActionNowOnTabOrAppVisibilityChange(Action::kPreconnectOnAppForeground);
 
   // To keep the overhead as low, Pre* action on app foreground is taken at most
-  // once per page. Stop listening to application change events only if
-  // OnLoad() has been fired implying that prediction computation has finished.
-  if (document_loaded_timing_ != base::TimeTicks())
-    application_status_listener_.reset();
+  // once per page.
+  application_status_listener_.reset();
 }
 #endif  // OS_ANDROID
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.h b/chrome/browser/navigation_predictor/navigation_predictor.h
index 90d9b4b..0f0b9b86 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.h
+++ b/chrome/browser/navigation_predictor/navigation_predictor.h
@@ -183,9 +183,6 @@
   // |log_action| should be set to the reason why this method was called.
   void TakeActionNowOnTabOrAppVisibilityChange(Action log_action);
 
-  // MaybePreconnectNow preconnects to an origin server if it's allowed.
-  void MaybePreconnectNow(Action log_action);
-
   // Used to get keyed services.
   content::BrowserContext* const browser_context_;
 
@@ -226,9 +223,6 @@
   // they are not comparable.
   const int preconnect_origin_score_threshold_;
 
-  // True if |this| is allowed to preconnect to same origin hosts.
-  const bool same_origin_preconnecting_allowed_;
-
   // Timing of document loaded and last click.
   base::TimeTicks document_loaded_timing_;
   base::TimeTicks last_click_timing_;
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
index 55e854f..691ec7f 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -20,7 +20,6 @@
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
 #include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
@@ -45,44 +44,6 @@
   }
 }
 
-// Gets notified by the EmbeddedTestServer on incoming connections being
-// accepted or read from.
-class ConnectionListener
-    : public net::test_server::EmbeddedTestServerConnectionListener {
- public:
-  ConnectionListener() = default;
-
-  ~ConnectionListener() override = default;
-
-  void ResetAcceptedSocketCount() { accepted_socket_count_ = 0; }
-
-  size_t accepted_socket_count() const { return accepted_socket_count_; }
-
-  void SetOnAcceptedSocketCallback(
-      base::OnceCallback<void()> on_accepted_socket_callback) {
-    on_accepted_socket_callback_ = std::move(on_accepted_socket_callback);
-  }
-
- private:
-  // Gets called from the EmbeddedTestServer thread to be notified that
-  // a connection was accepted.
-  void AcceptedSocket(const net::StreamSocket& connection) override {
-    ++accepted_socket_count_;
-    if (on_accepted_socket_callback_)
-      std::move(on_accepted_socket_callback_).Run();
-  }
-
-  // Gets called from the EmbeddedTestServer thread to be notified that
-  // a connection was read from.
-  void ReadFromSocket(const net::StreamSocket& connection, int rv) override {}
-
-  size_t accepted_socket_count_ = 0;
-
-  base::OnceCallback<void()> on_accepted_socket_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConnectionListener);
-};
-
 }  // namespace
 
 class NavigationPredictorBrowserTest
@@ -100,7 +61,6 @@
   void SetUp() override {
     https_server_.reset(
         new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
-    https_server_->SetConnectionListener(&https_connection_listener_);
     https_server_->ServeFilesFromSourceDirectory(
         "chrome/test/data/navigation_predictor");
     ASSERT_TRUE(https_server_->Start());
@@ -119,11 +79,6 @@
     host_resolver()->ClearRules();
   }
 
-  void FlushAllSocketsAndConnections() {
-    http_server_->FlushAllSocketsAndConnectionsOnUIThread();
-    https_server_->FlushAllSocketsAndConnectionsOnUIThread();
-  }
-
   const GURL GetTestURL(const char* file) const {
     return https_server_->GetURL(file);
   }
@@ -132,35 +87,11 @@
     return http_server_->GetURL(file);
   }
 
-  void ResetAcceptedHttpsSocketCount() {
-    https_connection_listener_.ResetAcceptedSocketCount();
-  }
-
-  void WaitUntilHttpsSocketAccepted() {
-    if (accepted_socket_count() > 0)
-      return;
-
-    base::RunLoop open_loop;
-    auto open_callback = base::BindOnce(
-        [](base::OnceClosure quit_closure) { std::move(quit_closure).Run(); },
-        open_loop.QuitClosure());
-
-    https_connection_listener_.SetOnAcceptedSocketCallback(
-        std::move(open_callback));
-    open_loop.Run();
-  }
-
-  size_t accepted_socket_count() const {
-    return https_connection_listener_.accepted_socket_count();
-  }
-
  private:
   std::unique_ptr<net::EmbeddedTestServer> http_server_;
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
   base::test::ScopedFeatureList feature_list_;
 
-  ConnectionListener https_connection_listener_;
-
   DISALLOW_COPY_AND_ASSIGN(NavigationPredictorBrowserTest);
 };
 
@@ -379,9 +310,6 @@
           kPrefetchActionClickToDifferentOrigin,
       1);
 
-  FlushAllSocketsAndConnections();
-  ResetAcceptedHttpsSocketCount();
-
   // Change to visibile.
   browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
   histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
@@ -406,69 +334,6 @@
   browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
   histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
                                     2);
-
-  EXPECT_EQ(0u, accepted_socket_count());
-}
-
-// Test that the action accuracy is properly recorded and when same origin
-// preconnections are enabled, then navigation predictor initiates the
-// preconnection.
-IN_PROC_BROWSER_TEST_F(
-    NavigationPredictorBrowserTest,
-    DISABLE_ON_CHROMEOS(
-        ActionAccuracy_DifferentOrigin_VisibilityChangedPreconnectEnabled)) {
-  std::map<std::string, std::string> parameters;
-  base::test::ScopedFeatureList feature_list;
-  parameters["same_origin_preconnecting_allowed"] = "true";
-  feature_list.InitAndEnableFeatureWithParameters(
-      blink::features::kRecordAnchorMetricsVisible, parameters);
-
-  base::HistogramTester histogram_tester;
-
-  const GURL& url = GetTestURL("/page_with_same_host_anchor_element.html");
-  ui_test_utils::NavigateToURL(browser(), url);
-  base::RunLoop().RunUntilIdle();
-
-  histogram_tester.ExpectUniqueSample(
-      "AnchorElementMetrics.Visible.NumberOfAnchorElements", 2, 1);
-  // Same document anchor element should be removed after merge.
-  histogram_tester.ExpectUniqueSample(
-      "AnchorElementMetrics.Visible.NumberOfAnchorElementsAfterMerge", 2, 1);
-  histogram_tester.ExpectUniqueSample(
-      "NavigationPredictor.OnNonDSE.ActionTaken",
-      NavigationPredictor::Action::kPrefetch, 1);
-
-  // Change to visible.
-  browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
-  histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
-                                    1);
-
-  browser()->tab_strip_model()->GetActiveWebContents()->WasHidden();
-  histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
-                                    1);
-
-  FlushAllSocketsAndConnections();
-  ResetAcceptedHttpsSocketCount();
-
-  browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
-  histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
-                                    2);
-  histogram_tester.ExpectBucketCount(
-      "NavigationPredictor.OnNonDSE.ActionTaken",
-      NavigationPredictor::Action::kPreconnectOnVisibilityChange, 1);
-
-  WaitUntilHttpsSocketAccepted();
-
-  ResetAcceptedHttpsSocketCount();
-
-  // Hiding and showing the tab again should not cause change in histograms
-  // since Pre* on tab foreground is done at most once per page.
-  browser()->tab_strip_model()->GetActiveWebContents()->WasHidden();
-  histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
-                                    2);
-  browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
-  histogram_tester.ExpectTotalCount("NavigationPredictor.OnNonDSE.ActionTaken",
-                                    2);
   histogram_tester.ExpectBucketCount(
       "NavigationPredictor.OnNonDSE.ActionTaken",
       NavigationPredictor::Action::kPreconnectOnVisibilityChange, 1);
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
index 770435b..8badd72 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
@@ -69,6 +69,14 @@
   NavigationPredictorTest() = default;
   ~NavigationPredictorTest() override = default;
 
+  void SetUp() override {
+    SetupFieldTrial(base::nullopt /* preconnect_origin_score_threshold */,
+                    base::nullopt /* prefetch_url_score_threshold */);
+    ChromeRenderViewHostTestHarness::SetUp();
+    predictor_service_helper_ = std::make_unique<TestNavigationPredictor>(
+        mojo::MakeRequest(&predictor_service_), main_rfh());
+  }
+
   // Helper function to generate mojom metrics.
   blink::mojom::AnchorElementMetricsPtr CreateMetricsPtr(
       const std::string& source_url,
@@ -98,18 +106,8 @@
   }
 
  protected:
-  void SetUp() override {
-    ChromeRenderViewHostTestHarness::SetUp();
-    predictor_service_helper_ = std::make_unique<TestNavigationPredictor>(
-        mojo::MakeRequest(&predictor_service_), main_rfh());
-  }
-
   void SetupFieldTrial(base::Optional<int> preconnect_origin_score_threshold,
                        base::Optional<int> prefetch_url_score_threshold) {
-    if (field_trial_initiated_)
-      return;
-
-    field_trial_initiated_ = true;
     const std::string kTrialName = "TrialFoo2";
     const std::string kGroupName = "GroupFoo2";  // Value not used
 
@@ -131,8 +129,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list;
-
-  bool field_trial_initiated_ = false;
 };
 
 }  // namespace
@@ -391,12 +387,10 @@
 // disabled by setting |prefetch_url_score_threshold| to too high.
 class NavigationPredictorPrefetchDisabledTest : public NavigationPredictorTest {
  public:
-  NavigationPredictorPrefetchDisabledTest() {
+  void SetUp() override {
     SetupFieldTrial(0 /* preconnect_origin_score_threshold */,
                     101 /* prefetch_url_score_threshold */);
-  }
 
-  void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     predictor_service_helper_ = std::make_unique<TestNavigationPredictor>(
         mojo::MakeRequest(&predictor_service_), main_rfh());
@@ -487,12 +481,10 @@
 class NavigationPredictorPreconnectPrefetchDisabledTest
     : public NavigationPredictorTest {
  public:
-  NavigationPredictorPreconnectPrefetchDisabledTest() {
+  void SetUp() override {
     SetupFieldTrial(101 /* preconnect_origin_score_threshold */,
                     101 /* prefetch_url_score_threshold */);
-  }
 
-  void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     predictor_service_helper_ = std::make_unique<TestNavigationPredictor>(
         mojo::MakeRequest(&predictor_service_), main_rfh());
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 4559238..3abe4c9 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -3578,51 +3578,61 @@
 // password manager works even though it should be disabled on the previous
 // page.
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, CorrectEntryForHttpAuth) {
-  // The embedded_test_server() is already started at this point and adding the
-  // request handler to it would not be thread safe. Therefore, use a new
-  // server.
-  net::EmbeddedTestServer http_test_server;
+  for (bool new_parser_enabled : {false, true}) {
+    base::test::ScopedFeatureList scoped_feature_list;
+    if (new_parser_enabled) {
+      scoped_feature_list.InitAndEnableFeature(
+          features::kNewPasswordFormParsing);
+    } else {
+      scoped_feature_list.InitAndDisableFeature(
+          features::kNewPasswordFormParsing);
+    }
+    // The embedded_test_server() is already started at this point and adding
+    // the request handler to it would not be thread safe. Therefore, use a new
+    // server.
+    net::EmbeddedTestServer http_test_server;
 
-  // Teach the embedded server to handle requests by issuing the basic auth
-  // challenge.
-  http_test_server.RegisterRequestHandler(base::Bind(&HandleTestAuthRequest));
-  ASSERT_TRUE(http_test_server.Start());
+    // Teach the embedded server to handle requests by issuing the basic auth
+    // challenge.
+    http_test_server.RegisterRequestHandler(base::Bind(&HandleTestAuthRequest));
+    ASSERT_TRUE(http_test_server.Start());
 
-  LoginPromptBrowserTestObserver login_observer;
-  login_observer.Register(content::Source<content::NavigationController>(
-      &WebContents()->GetController()));
+    LoginPromptBrowserTestObserver login_observer;
+    login_observer.Register(content::Source<content::NavigationController>(
+        &WebContents()->GetController()));
 
-  // Navigate to about:blank first. This is a page where password manager should
-  // not work.
-  ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
+    // Navigate to about:blank first. This is a page where password manager
+    // should not work.
+    ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
 
-  // Navigate to a page requiring HTTP auth. Wait for the tab to get the correct
-  // WebContents, but don't wait for navigation, which only finishes after
-  // authentication.
-  ui_test_utils::NavigateToURLWithDisposition(
-      browser(), http_test_server.GetURL("/basic_auth"),
-      WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+    // Navigate to a page requiring HTTP auth. Wait for the tab to get the
+    // correct WebContents, but don't wait for navigation, which only finishes
+    // after authentication.
+    ui_test_utils::NavigateToURLWithDisposition(
+        browser(), http_test_server.GetURL("/basic_auth"),
+        WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
 
-  content::NavigationController* nav_controller =
-      &WebContents()->GetController();
-  NavigationObserver nav_observer(WebContents());
-  WindowedAuthNeededObserver auth_needed_observer(nav_controller);
-  auth_needed_observer.Wait();
+    content::NavigationController* nav_controller =
+        &WebContents()->GetController();
+    NavigationObserver nav_observer(WebContents());
+    WindowedAuthNeededObserver auth_needed_observer(nav_controller);
+    auth_needed_observer.Wait();
 
-  WindowedAuthSuppliedObserver auth_supplied_observer(nav_controller);
-  // Offer valid credentials on the auth challenge.
-  ASSERT_EQ(1u, login_observer.handlers().size());
-  LoginHandler* handler = *login_observer.handlers().begin();
-  ASSERT_TRUE(handler);
-  // Any username/password will work.
-  handler->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
-  auth_supplied_observer.Wait();
+    WindowedAuthSuppliedObserver auth_supplied_observer(nav_controller);
+    // Offer valid credentials on the auth challenge.
+    ASSERT_EQ(1u, login_observer.handlers().size());
+    LoginHandler* handler = *login_observer.handlers().begin();
+    ASSERT_TRUE(handler);
+    // Any username/password will work.
+    handler->SetAuth(base::UTF8ToUTF16("user"), base::UTF8ToUTF16("pwd"));
+    auth_supplied_observer.Wait();
 
-  // The password manager should be working correctly.
-  nav_observer.Wait();
-  WaitForPasswordStore();
-  BubbleObserver bubble_observer(WebContents());
-  EXPECT_TRUE(bubble_observer.IsSavePromptShownAutomatically());
+    // The password manager should be working correctly.
+    nav_observer.Wait();
+    WaitForPasswordStore();
+    BubbleObserver bubble_observer(WebContents());
+    EXPECT_TRUE(bubble_observer.IsSavePromptShownAutomatically());
+  }
 }
 
 // Test that if HTTP auth login (i.e., credentials not put through web forms)
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 62ee5120..9e38b8251 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -616,7 +616,13 @@
   RunTestsInFile("touch_handling_test.js", "test.pdf");
 }
 
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Elements) {
+// Flaky on ASan/LSan bots: https://crbug.com/915555.
+#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER)
+#define MAYBE_Elements DISABLED_Elements
+#else
+#define MAYBE_Elements Elements
+#endif
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, MAYBE_Elements) {
   // Although this test file does not require a PDF to be loaded, loading the
   // elements without loading a PDF is difficult.
   RunTestsInFile("material_elements_test.js", "test.pdf");
diff --git a/chrome/browser/predictors/loading_predictor_config.h b/chrome/browser/predictors/loading_predictor_config.h
index 340f9c81..d8922440 100644
--- a/chrome/browser/predictors/loading_predictor_config.h
+++ b/chrome/browser/predictors/loading_predictor_config.h
@@ -30,7 +30,7 @@
 bool IsPreconnectAllowed(Profile* profile);
 
 // Indicates what caused the page load hint.
-enum class HintOrigin { NAVIGATION, EXTERNAL, OMNIBOX, NAVIGATION_PREDICTOR };
+enum class HintOrigin { NAVIGATION, EXTERNAL, OMNIBOX };
 
 // Represents the config for the Loading predictor.
 struct LoadingPredictorConfig {
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 993a8d79..2d19e31 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -21,6 +21,7 @@
 <link rel="import" href="../settings_page/settings_subpage.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="signout_dialog.html">
+<link rel="import" href="sync_controls.html">
 
 <if expr="chromeos">
 <link rel="import" href="account_manager.html">
@@ -344,6 +345,15 @@
         </settings-subpage>
       </template>
 
+      <template is="dom-if" route-path="/syncSetup/advanced">
+        <settings-subpage page-title="$i18n{syncAdvancedPageTitle}"
+            learn-more-url="$i18n{syncAndGoogleServicesLearnMoreURL}">
+          <settings-sync-controls sync-status="[[syncStatus]]"
+              on-sync-setup-cancel="cancelSyncSetup_">
+          </settings-sync-controls>
+        </settings-subpage>
+      </template>
+
 <if expr="chromeos">
       <template is="dom-if" route-path="/lockScreen">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js
index 977fa30..dd0be9d 100644
--- a/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -580,4 +580,9 @@
       return this.i18n('lockScreenTitleLoginLock');
     return this.i18n('lockScreenTitleLock');
   },
+
+  /** @private */
+  cancelSyncSetup_: function() {
+    this.$$('settings-sync-page').cancelSyncSetup();
+  },
 });
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.html b/chrome/browser/resources/settings/people_page/sync_controls.html
index 83839137..4ddc7d6 100644
--- a/chrome/browser/resources/settings/people_page/sync_controls.html
+++ b/chrome/browser/resources/settings/people_page/sync_controls.html
@@ -5,9 +5,14 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="sync_browser_proxy.html">
+<link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
 
+<if expr="not chromeos">
+<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
+</if>
+
 <dom-module id="settings-sync-controls">
   <template>
     <style include="settings-shared">
@@ -22,6 +27,19 @@
       .list-item > div {
         flex: 1;
       }
+
+<if expr="not chromeos">
+      #toast {
+        color: white;
+        left: 0;
+        z-index: 1;
+      }
+
+      :host-context([dir='rtl']) #toast {
+        left: auto;
+        right: 0;
+      }
+</if>
     </style>
 
     <div class="settings-box first">
@@ -169,6 +187,15 @@
       </div>
     </div>
 
+<if expr="not chromeos">
+  <cr-toast id="toast"
+      open="[[shouldShowSyncSetupToast_(syncStatus.setupInProgress)]]">
+    <div>$i18n{syncWillStart}</div>
+    <paper-button on-click="onCancelSyncClick_">
+      $i18n{cancelSync}
+    </paper-button>
+  </cr-toast>
+</if>
   </template>
   <script src="sync_controls.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.js b/chrome/browser/resources/settings/people_page/sync_controls.js
index 61e5e7bd..859f8874 100644
--- a/chrome/browser/resources/settings/people_page/sync_controls.js
+++ b/chrome/browser/resources/settings/people_page/sync_controls.js
@@ -37,6 +37,12 @@
      * @type {settings.SyncPrefs|undefined}
      */
     syncPrefs: Object,
+
+    /**
+     * The current sync status, supplied by the parent.
+     * @type {settings.SyncStatus}
+     */
+    syncStatus: Object,
   },
 
   /** @private {?settings.SyncBrowserProxy} */
@@ -58,6 +64,9 @@
   attached: function() {
     this.addWebUIListener(
         'sync-prefs-changed', this.handleSyncPrefsChanged_.bind(this));
+
+    if (settings.getCurrentRoute() == settings.routes.SYNC_ADVANCED)
+      this.browserProxy_.didNavigateToSyncPage();
   },
 
   /**
@@ -145,5 +154,19 @@
       syncAllDataTypes, autofillSynced) {
     return syncAllDataTypes || !autofillSynced;
   },
+
+  /**
+   * @private
+   * @return {boolean}
+   */
+  shouldShowSyncSetupToast_: function() {
+    return settings.getCurrentRoute() == settings.routes.SYNC_ADVANCED &&
+        this.syncStatus.setupInProgress;
+  },
+
+  /** @private */
+  onCancelSyncClick_: function() {
+    this.fire('sync-setup-cancel');
+  },
 });
 })();
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 172854be..a0d36058 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -65,7 +65,7 @@
         padding-bottom: 8px;
       }
 
-      #other-sync-items > .list-item {
+      #other-sync-items > .list-item:not(.first) {
         border-top: var(--settings-separator-line);
       }
 
@@ -147,11 +147,11 @@
       </div>
     </template>
 
-    <div class="settings-box first" hidden="[[!unifiedConsentEnabled]]">
-      <h2 class="start">$i18n{sync}</h2>
-    </div>
-
     <div id="sync-section" hidden="[[syncSectionDisabled_]]">
+      <div class="settings-box first" hidden="[[!unifiedConsentEnabled]]">
+        <h2 class="start">$i18n{sync}</h2>
+      </div>
+
       <div id="[[pages_.SPINNER]]" class="settings-box first settings-box-text"
           hidden$="[[!isStatus_(pages_.SPINNER, pageStatus_)]]">
         $i18n{syncLoading}
@@ -194,10 +194,29 @@
           </div>
         </template>
 
-        <settings-sync-controls></settings-sync-controls>
+        <template is="dom-if" if="[[!unifiedConsentEnabled]]">
+          <settings-sync-controls sync-status="syncStatus">
+          </settings-sync-controls>
+        </template>
 
         <div id="other-sync-items"
             class$="[[getListFrameClass_(unifiedConsentEnabled)]]">
+
+          <template is="dom-if" if="[[unifiedConsentEnabled]]">
+            <div id="sync-advanced-row" class="list-item first two-line"
+                on-click="onSyncAdvancedTap_" actionable>
+              <div class="start">
+                $i18n{syncAdvancedPageTitle}
+                <div class="secondary">
+                  [[getSyncAdvancedRowSublabel_(syncPrefs.syncAllDataTypes)]]
+                </div>
+              </div>
+              <paper-icon-button-light class="subpage-arrow">
+                <button aria-label="$i18n{syncAdvancedPageTitle}"></button>
+              </paper-icon-button-light>
+            </div>
+          </template>
+
           <template is="dom-if" if="[[driveSuggestAvailable_]]">
             <settings-toggle-button
                 class$="[[getListItemClass_(unifiedConsentEnabled)]]"
@@ -313,7 +332,7 @@
 <if expr="not chromeos">
     <cr-toast id="toast" open="[[syncStatus.setupInProgress]]">
       <div>$i18n{syncWillStart}</div>
-      <paper-button on-click="onCancelSyncClick_">
+      <paper-button on-click="cancelSyncSetup">
         $i18n{cancelSync}
       </paper-button>
     </cr-toast>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js
index 4596795..e9396d9 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -22,6 +22,7 @@
   is: 'settings-sync-page',
 
   behaviors: [
+    I18nBehavior,
     WebUIListenerBehavior,
     settings.RouteObserverBehavior,
   ],
@@ -184,10 +185,18 @@
     if (settings.getCurrentRoute() == settings.routes.SYNC)
       this.onNavigateToPage_();
   },
+  /**
+   * Can be called from subpages to notify this page (=main sync page) that sync
+   * setup was cancelled.
+   */
+  cancelSyncSetup: function() {
+    this.didAbort_ = true;
+    settings.navigateTo(settings.routes.BASIC);
+  },
 
   /** @override */
   detached: function() {
-    if (settings.getCurrentRoute() == settings.routes.SYNC)
+    if (settings.routes.SYNC.contains(settings.getCurrentRoute()))
       this.onNavigateAwayFromPage_();
 
     if (this.beforeunloadCallback_) {
@@ -220,7 +229,7 @@
   currentRouteChanged: function() {
     if (settings.getCurrentRoute() == settings.routes.SYNC)
       this.onNavigateToPage_();
-    else
+    else if (!settings.routes.SYNC.contains(settings.getCurrentRoute()))
       this.onNavigateAwayFromPage_();
   },
 
@@ -441,12 +450,6 @@
     }
   },
 
-  /** @private */
-  onCancelSyncClick_: function() {
-    this.didAbort_ = true;
-    settings.navigateTo(settings.routes.BASIC);
-  },
-
   /**
    * When unified-consent enabled, the non-toggle items on the bottom of sync
    * section should be wrapped with 'list-frame' in order to be indented
@@ -507,6 +510,21 @@
     return !this.unifiedConsentEnabled && this.syncPrefs !== undefined &&
         !!this.syncPrefs.passphraseRequired;
   },
+
+  /** @private */
+  onSyncAdvancedTap_: function() {
+    settings.navigateTo(settings.routes.SYNC_ADVANCED);
+  },
+
+  /**
+   * @return {string}
+   * @private
+   */
+  getSyncAdvancedRowSublabel_: function() {
+    return this.i18n(
+        this.syncPrefs.syncAllDataTypes ? 'syncEverythingCheckboxLabel' :
+                                          'syncAdvancedRowCustomSettings');
+  },
 });
 
 })();
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index df4e50f..8c8168d 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -101,6 +101,7 @@
  *   STORAGE: (undefined|!settings.Route),
  *   STYLUS: (undefined|!settings.Route),
  *   SYNC: (undefined|!settings.Route),
+ *   SYNC_ADVANCED: (undefined|!settings.Route),
  *   SYSTEM: (undefined|!settings.Route),
  *   TRIGGERED_RESET_DIALOG: (undefined|!settings.Route),
  * }}
@@ -284,6 +285,7 @@
     if (pageVisibility.people !== false) {
       r.PEOPLE = r.BASIC.createSection('/people', 'people');
       r.SYNC = r.PEOPLE.createChild('/syncSetup');
+      r.SYNC_ADVANCED = r.SYNC.createChild('/syncSetup/advanced');
       // <if expr="not chromeos">
       r.MANAGE_PROFILE = r.PEOPLE.createChild('/manageProfile');
       // </if>
diff --git a/chrome/browser/resources/signin/dice_sync_confirmation/sync_confirmation_app.html b/chrome/browser/resources/signin/dice_sync_confirmation/sync_confirmation_app.html
index e804673d..876bf44 100644
--- a/chrome/browser/resources/signin/dice_sync_confirmation/sync_confirmation_app.html
+++ b/chrome/browser/resources/signin/dice_sync_confirmation/sync_confirmation_app.html
@@ -126,6 +126,11 @@
         width: 100%;
       }
 
+      #footer {
+        margin-bottom: 0;
+        padding-top: 12px;
+      }
+
       #settingsButton {
         left: 16px;
         position: absolute;
@@ -187,6 +192,9 @@
           </div>
         </div>
       </div>
+      <div id="footer" class="message-container secondary">
+        $i18n{syncConfirmationSettingsInfo}
+      </div>
       <div class="action-container">
         <paper-button class="action-button" id="confirmButton"
             on-click="onConfirm_" consent-confirmation>
diff --git a/chrome/browser/search_provider_logos/logo_service_factory.cc b/chrome/browser/search_provider_logos/logo_service_factory.cc
index cd845ba..26f07b9 100644
--- a/chrome/browser/search_provider_logos/logo_service_factory.cc
+++ b/chrome/browser/search_provider_logos/logo_service_factory.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/search_provider_logos/logo_service.h"
 #include "components/search_provider_logos/logo_service_impl.h"
@@ -50,7 +50,7 @@
     : BrowserContextKeyedServiceFactory(
           "LogoService",
           BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(GaiaCookieManagerServiceFactory::GetInstance());
+  DependsOn(IdentityManagerFactory::GetInstance());
   DependsOn(TemplateURLServiceFactory::GetInstance());
 }
 
@@ -62,7 +62,7 @@
   DCHECK(!profile->IsOffTheRecord());
   return new LogoServiceImpl(
       profile->GetPath().Append(kCachedLogoDirectory),
-      GaiaCookieManagerServiceFactory::GetForProfile(profile),
+      IdentityManagerFactory::GetForProfile(profile),
       TemplateURLServiceFactory::GetForProfile(profile),
       std::make_unique<suggestions::ImageDecoderImpl>(),
       content::BrowserContext::GetDefaultStoragePartition(profile)
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
index 4eebed63..d2ab6d9 100644
--- a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
+++ b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
@@ -14,7 +14,7 @@
 std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerService(
     content::BrowserContext* context) {
   return BuildFakeGaiaCookieManagerServiceWithOptions(
-      /*create_fake_url_loader_factory_for_cookie_requests=*/true, context);
+      /*create_fake_url_loader_factory_for_cookie_requests=*/false, context);
 }
 
 std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerServiceWithOptions(
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
index fa618ce..8e1437a 100644
--- a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
+++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
@@ -16,7 +16,7 @@
 namespace {
 
 TestingProfile::TestingFactories GetIdentityTestEnvironmentFactories(
-    bool create_fake_url_loader_factory_for_cookie_requests = true) {
+    bool create_fake_url_loader_factory_for_cookie_requests = false) {
   return {
       {GaiaCookieManagerServiceFactory::GetInstance(),
        base::BindRepeating(&BuildFakeGaiaCookieManagerServiceWithOptions,
@@ -78,8 +78,7 @@
 // static
 void IdentityTestEnvironmentProfileAdaptor::
     AppendIdentityTestEnvironmentFactories(
-        TestingProfile::TestingFactories* factories_to_append_to,
-        bool create_fake_url_loader_factory_for_cookie_requests) {
+        TestingProfile::TestingFactories* factories_to_append_to) {
   TestingProfile::TestingFactories identity_factories =
       GetIdentityTestEnvironmentFactories();
   factories_to_append_to->insert(factories_to_append_to->end(),
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.h b/chrome/browser/signin/identity_test_environment_profile_adaptor.h
index 17a17036..951a8fa 100644
--- a/chrome/browser/signin/identity_test_environment_profile_adaptor.h
+++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.h
@@ -25,15 +25,14 @@
   CreateProfileForIdentityTestEnvironment();
 
   // Like the above, but additionally configures the returned Profile with
-  // |input_factories|. By default, internally constructs a
-  // TestURLLoaderFactory to use for cookie-related network requests. If this
-  // isn't desired (e.g., because the test is already using a
-  // TestURLLoaderFactory), set
-  // |create_fake_url_loader_factory_for_cookie_requests| to false.
+  // |input_factories|.
+  // If |create_fake_url_loader_factory_for_cookie_requests| is set to true,
+  // this method will internally construct a TestURLLoaderFactory to use for
+  // cookie-related network requests.
   static std::unique_ptr<TestingProfile>
   CreateProfileForIdentityTestEnvironment(
       const TestingProfile::TestingFactories& input_factories,
-      bool create_fake_url_loader_factory_for_cookie_requests = true);
+      bool create_fake_url_loader_factory_for_cookie_requests = false);
 
   // Creates and returns a TestingProfile that has been configured with the
   // given |builder| and the set of testing factories that
@@ -42,14 +41,14 @@
   static std::unique_ptr<TestingProfile>
   CreateProfileForIdentityTestEnvironment(
       TestingProfile::Builder& builder,
-      bool create_fake_url_loader_factory_for_cookie_requests = true);
+      bool create_fake_url_loader_factory_for_cookie_requests = false);
 
   // Sets the testing factories that identity::IdentityTestEnvironment
   // requires explicitly on a Profile that is passed to it.
   // See the above variant for comments on common parameters.
   static void SetIdentityTestEnvironmentFactoriesOnBrowserContext(
       content::BrowserContext* browser_context,
-      bool create_fake_url_loader_factory_for_cookie_requests = true);
+      bool create_fake_url_loader_factory_for_cookie_requests = false);
 
   // Appends the set of testing factories that identity::IdentityTestEnvironment
   // requires to |factories_to_append_to|, which should be the set of testing
@@ -61,8 +60,7 @@
   // See CreateProfileForIdentityTestEnvironment() for comments on common
   // parameters.
   static void AppendIdentityTestEnvironmentFactories(
-      TestingProfile::TestingFactories* factories_to_append_to,
-      bool create_fake_url_loader_factory_for_cookie_requests = true);
+      TestingProfile::TestingFactories* factories_to_append_to);
 
   // Constructs an adaptor that associates an IdentityTestEnvironment instance
   // with |profile| via the relevant backing objects. Note that
diff --git a/chrome/browser/signin/signin_ui_util_unittest.cc b/chrome/browser/signin/signin_ui_util_unittest.cc
index 3e699b9..5aea7676 100644
--- a/chrome/browser/signin/signin_ui_util_unittest.cc
+++ b/chrome/browser/signin/signin_ui_util_unittest.cc
@@ -132,15 +132,12 @@
 
   // BrowserWithTestWindowTest:
   TestingProfile::TestingFactories GetTestingFactories() override {
-    return {
-        {SigninManagerFactory::GetInstance(),
-         base::BindRepeating(&BuildFakeSigninManagerForTesting)},
-        {ProfileOAuth2TokenServiceFactory::GetInstance(),
-         base::BindRepeating(&BuildFakeProfileOAuth2TokenService)},
-        {GaiaCookieManagerServiceFactory::GetInstance(),
-         base::BindRepeating(
-             &BuildFakeGaiaCookieManagerServiceWithOptions,
-             /*create_fake_url_loader_factory_for_cookie_requests=*/false)}};
+    return {{SigninManagerFactory::GetInstance(),
+             base::BindRepeating(&BuildFakeSigninManagerForTesting)},
+            {ProfileOAuth2TokenServiceFactory::GetInstance(),
+             base::BindRepeating(&BuildFakeProfileOAuth2TokenService)},
+            {GaiaCookieManagerServiceFactory::GetInstance(),
+             base::BindRepeating(&BuildFakeGaiaCookieManagerService)}};
   }
 
   // BrowserWithTestWindowTest:
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
index d9a3db29..c61a71a 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
@@ -34,7 +34,9 @@
                               base::BindRepeating(&BuildTestSigninClient));
     builder.AddTestingFactory(
         GaiaCookieManagerServiceFactory::GetInstance(),
-        base::BindRepeating(&BuildFakeGaiaCookieManagerService));
+        base::BindRepeating(
+            &BuildFakeGaiaCookieManagerServiceWithOptions,
+            /*create_fake_url_loader_factory_for_cookie_requests=*/true));
     profile_ = builder.Build();
     gaia_cookie_manager_service_ = static_cast<FakeGaiaCookieManagerService*>(
         GaiaCookieManagerServiceFactory::GetForProfile(profile_.get()));
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 0c6f9354..9ae3b36 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -86,7 +86,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/storage/backend_task_runner.h"
 #include "extensions/buildflags/buildflags.h"
-#include "ui/base/device_form_factor.h"
 
 #if BUILDFLAG(ENABLE_APP_LIST)
 #include "ash/public/cpp/app_list/app_list_switches.h"
@@ -193,9 +192,7 @@
   // Component factory may already be set in tests.
   if (!GetSyncApiComponentFactory()) {
     component_factory_ = std::make_unique<ProfileSyncComponentsFactoryImpl>(
-        this, chrome::GetChannel(), chrome::GetVersionString(),
-        ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET,
-        prefs::kSavingBrowserHistoryDisabled,
+        this, chrome::GetChannel(), prefs::kSavingBrowserHistoryDisabled,
         base::CreateSingleThreadTaskRunnerWithTraits(
             {content::BrowserThread::UI}),
         web_data_service_thread_, profile_web_data_service_,
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index 4ab1c01..7eb7a3e 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -48,6 +48,7 @@
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/network_time/network_time_tracker.h"
+#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/driver/startup_controller.h"
 #include "components/sync/driver/sync_util.h"
 #include "components/unified_consent/feature.h"
@@ -58,6 +59,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "extensions/buildflags/buildflags.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/device_form_factor.h"
 #include "url/gurl.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -193,7 +195,10 @@
   init_params.network_connection_tracker =
       content::GetNetworkConnectionTracker();
   init_params.debug_identifier = profile->GetDebugName();
-  init_params.channel = chrome::GetChannel();
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          chrome::GetChannel(), chrome::GetVersionString(),
+          ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
 
   bool local_sync_backend_enabled = false;
 // Since the local sync backend is currently only supported on Windows don't
diff --git a/chrome/browser/sync/profile_sync_test_util.cc b/chrome/browser/sync/profile_sync_test_util.cc
index 16c73a7..bfcba6a3 100644
--- a/chrome/browser/sync/profile_sync_test_util.cc
+++ b/chrome/browser/sync/profile_sync_test_util.cc
@@ -22,11 +22,13 @@
 #include "components/browser_sync/profile_sync_test_util.h"
 #include "components/invalidation/impl/invalidation_switches.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
+#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/driver/startup_controller.h"
 #include "components/sync/driver/sync_api_component_factory_mock.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/device_form_factor.h"
 
 using browser_sync::ProfileSyncService;
 using testing::NiceMock;
@@ -70,7 +72,10 @@
       content::BrowserContext::GetDefaultStoragePartition(profile)
           ->GetURLLoaderFactoryForBrowserProcess();
   init_params.debug_identifier = profile->GetDebugName();
-  init_params.channel = chrome::GetChannel();
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          chrome::GetChannel(), chrome::GetVersionString(),
+          ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
 
   return init_params;
 }
diff --git a/chrome/browser/sync/test/integration/secondary_account_helper.cc b/chrome/browser/sync/test/integration/secondary_account_helper.cc
index 528ed6b..dc50be6 100644
--- a/chrome/browser/sync/test/integration/secondary_account_helper.cc
+++ b/chrome/browser/sync/test/integration/secondary_account_helper.cc
@@ -29,7 +29,10 @@
 
 void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
   GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory(
-      context, base::BindRepeating(&BuildFakeGaiaCookieManagerService));
+      context,
+      base::BindRepeating(
+          &BuildFakeGaiaCookieManagerServiceWithOptions,
+          /*create_fake_url_loader_factory_for_cookie_requests=*/true));
 }
 
 }  // namespace
@@ -66,8 +69,8 @@
 void SignInSecondaryAccount(Profile* profile, const std::string& email) {
   identity::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
-  AccountInfo account_info = identity::MakeAccountAvailable(
-      identity_manager, email);
+  AccountInfo account_info =
+      identity::MakeAccountAvailable(identity_manager, email);
   FakeGaiaCookieManagerService* fake_cookie_service =
       static_cast<FakeGaiaCookieManagerService*>(
           GaiaCookieManagerServiceFactory::GetForProfile(profile));
diff --git a/chrome/browser/ui/cocoa/test/cocoa_profile_test.mm b/chrome/browser/ui/cocoa/test/cocoa_profile_test.mm
index 1e9af27e..5de31bc 100644
--- a/chrome/browser/ui/cocoa/test/cocoa_profile_test.mm
+++ b/chrome/browser/ui/cocoa/test/cocoa_profile_test.mm
@@ -58,7 +58,9 @@
   // Always fake out the Gaia service to avoid issuing network requests.
   TestingProfile::TestingFactories testing_factories = {
       {GaiaCookieManagerServiceFactory::GetInstance(),
-       base::BindRepeating(&BuildFakeGaiaCookieManagerService)}};
+       base::BindRepeating(
+           &BuildFakeGaiaCookieManagerServiceWithOptions,
+           /*create_fake_url_loader_factory_for_cookie_requests=*/true)}};
 
   profile_ = profile_manager_.CreateTestingProfile(
       "Person 1", std::unique_ptr<sync_preferences::PrefServiceSyncable>(),
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
index f6e8831f..edec546d 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -75,9 +75,22 @@
          app_url.port() == page_url.port();
 }
 
-// Returns true if |page_url| is in the scope of the app for |app_url|. If the
-// app has no scope defined (as in a bookmark app), we fall back to checking
-// |page_url| has the same origin as |app_url|.
+// Gets the icon to use if the extension app icon is not available.
+gfx::ImageSkia GetFallbackAppIcon(Browser* browser) {
+  gfx::ImageSkia page_icon = browser->GetCurrentPageIcon().AsImageSkia();
+  if (!page_icon.isNull())
+    return page_icon;
+
+  // The extension icon may be loading still. Return a transparent icon rather
+  // than using a placeholder to avoid flickering.
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(gfx::kFaviconSize, gfx::kFaviconSize);
+  bitmap.eraseColor(SK_ColorTRANSPARENT);
+  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+}
+
+}  // namespace
+
 bool IsSameScope(const GURL& app_url,
                  const GURL& page_url,
                  content::BrowserContext* profile) {
@@ -99,22 +112,6 @@
              profile, page_url, extensions::LAUNCH_CONTAINER_WINDOW);
 }
 
-// Gets the icon to use if the extension app icon is not available.
-gfx::ImageSkia GetFallbackAppIcon(Browser* browser) {
-  gfx::ImageSkia page_icon = browser->GetCurrentPageIcon().AsImageSkia();
-  if (!page_icon.isNull())
-    return page_icon;
-
-  // The extension icon may be loading still. Return a transparent icon rather
-  // than using a placeholder to avoid flickering.
-  SkBitmap bitmap;
-  bitmap.allocN32Pixels(gfx::kFaviconSize, gfx::kFaviconSize);
-  bitmap.eraseColor(SK_ColorTRANSPARENT);
-  return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
-}
-
-}  // namespace
-
 const char kPwaWindowEngagementTypeHistogram[] =
     "Webapp.Engagement.EngagementType";
 
@@ -313,6 +310,14 @@
   return entry ? entry->GetTitle() : base::string16();
 }
 
+GURL HostedAppBrowserController::GetAppLaunchURL() const {
+  const Extension* extension = GetExtension();
+  if (!extension)
+    return GURL();
+
+  return AppLaunchInfo::GetLaunchWebURL(extension);
+}
+
 const Extension* HostedAppBrowserController::GetExtension() const {
   return ExtensionRegistry::Get(browser_->profile())
       ->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
index ba4dc95..34e4b6a 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -23,6 +23,13 @@
 
 namespace extensions {
 
+// Returns true if |page_url| is in the scope of the app for |app_url|. If the
+// app has no scope defined (as in a bookmark app), we fall back to checking
+// |page_url| has the same origin as |app_url|.
+bool IsSameScope(const GURL& app_url,
+                 const GURL& page_url,
+                 content::BrowserContext* profile);
+
 extern const char kPwaWindowEngagementTypeHistogram[];
 
 class Extension;
@@ -88,6 +95,9 @@
   // example.com.au).
   base::string16 GetFormattedUrlOrigin() const;
 
+  // Gets the launch url for the app.
+  GURL GetAppLaunchURL() const;
+
   // Gets the extension for this controller.
   const Extension* GetExtensionForTesting() const;
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
index 73e05ead..85c2386 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
@@ -63,18 +63,12 @@
             Profile::FromBrowserContext(profile))));
   }
 
-  bool IsFirstSetupComplete() const override { return first_setup_complete_; }
-
   bool IsSetupInProgress() const override { return setup_in_progress_; }
 
   int GetDisableReasons() const override { return DISABLE_REASON_NONE; }
 
   TransportState GetTransportState() const override { return state_; }
 
-  void set_first_setup_complete(bool complete) {
-    first_setup_complete_ = complete;
-  }
-
   void set_setup_in_progress(bool in_progress) {
     setup_in_progress_ = in_progress;
   }
@@ -84,11 +78,9 @@
  private:
   explicit OneClickTestProfileSyncService(InitParams init_params)
       : browser_sync::TestProfileSyncService(std::move(init_params)),
-        first_setup_complete_(false),
         setup_in_progress_(false),
         state_(TransportState::INITIALIZING) {}
 
-  bool first_setup_complete_;
   bool setup_in_progress_;
   TransportState state_;
 
@@ -203,7 +195,7 @@
 TEST_F(OneClickSigninSyncObserverTest,
        OnSyncStateChanged_SyncConfiguredSuccessfully) {
   CreateSyncObserver(kContinueUrl);
-  sync_service_->set_first_setup_complete(true);
+  sync_service_->GetUserSettings()->SetFirstSetupComplete();
   sync_service_->set_setup_in_progress(false);
   sync_service_->set_state(syncer::SyncService::TransportState::ACTIVE);
 
@@ -217,7 +209,7 @@
 TEST_F(OneClickSigninSyncObserverTest,
        OnSyncStateChanged_SyncConfigurationFailed) {
   CreateSyncObserver(kContinueUrl);
-  sync_service_->set_first_setup_complete(true);
+  sync_service_->GetUserSettings()->SetFirstSetupComplete();
   sync_service_->set_setup_in_progress(false);
   sync_service_->set_state(syncer::SyncService::TransportState::INITIALIZING);
 
@@ -231,7 +223,6 @@
 TEST_F(OneClickSigninSyncObserverTest,
        OnSyncStateChanged_SyncConfigurationInProgress) {
   CreateSyncObserver(kContinueUrl);
-  sync_service_->set_first_setup_complete(false);
   sync_service_->set_setup_in_progress(true);
   sync_service_->set_state(syncer::SyncService::TransportState::INITIALIZING);
 
@@ -251,7 +242,7 @@
       signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
       signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, false);
   CreateSyncObserver(continue_url.spec());
-  sync_service_->set_first_setup_complete(true);
+  sync_service_->GetUserSettings()->SetFirstSetupComplete();
   sync_service_->set_setup_in_progress(false);
   sync_service_->set_state(syncer::SyncService::TransportState::ACTIVE);
 
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.cc b/chrome/browser/ui/views/frame/test_with_browser_view.cc
index 45cf73a..96e60d0 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.cc
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.cc
@@ -68,8 +68,7 @@
                                          bool hosted_app)
     : BrowserWithTestWindowTest(browser_type, hosted_app) {}
 
-TestWithBrowserView::~TestWithBrowserView() {
-}
+TestWithBrowserView::~TestWithBrowserView() {}
 
 void TestWithBrowserView::SetUp() {
 #if defined(OS_CHROMEOS)
@@ -125,5 +124,7 @@
 
 TestingProfile::TestingFactories TestWithBrowserView::GetTestingFactories() {
   return {{GaiaCookieManagerServiceFactory::GetInstance(),
-           base::BindRepeating(&BuildFakeGaiaCookieManagerService)}};
+           base::BindRepeating(
+               &BuildFakeGaiaCookieManagerServiceWithOptions,
+               /*create_fake_url_loader_factory_for_cookie_requests=*/true)}};
 }
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
index ddabb2d..715c67b 100644
--- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -60,14 +60,14 @@
   explicit TestSyncService(Profile* profile)
       : browser_sync::TestProfileSyncService(
             CreateProfileSyncServiceParamsForTest(profile)),
-        state_(TransportState::ACTIVE) {}
+        state_(TransportState::ACTIVE) {
+    GetUserSettings()->SetFirstSetupComplete();
+  }
 
   TransportState GetTransportState() const override { return state_; }
 
   int GetDisableReasons() const override { return DISABLE_REASON_NONE; }
 
-  bool IsFirstSetupComplete() const override { return true; }
-
   syncer::ModelTypeSet GetActiveDataTypes() const override {
     return syncer::ModelTypeSet::All();
   }
@@ -112,6 +112,7 @@
         ProfileSyncServiceFactory::GetForProfile(profile()));
     web_history_service_ = static_cast<history::FakeWebHistoryService*>(
         WebHistoryServiceFactory::GetForProfile(profile()));
+    ASSERT_TRUE(web_history_service_);
 
     web_ui_.reset(new content::TestWebUI);
     web_ui_->set_web_contents(web_contents());
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 2d7e2e0..6d039f13 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1686,7 +1686,9 @@
     {"editPerson", IDS_SETTINGS_EDIT_PERSON},
     {"profileNameAndPicture", IDS_SETTINGS_PROFILE_NAME_AND_PICTURE},
     {"showShortcutLabel", IDS_SETTINGS_PROFILE_SHORTCUT_TOGGLE_LABEL},
-    {"syncWillStart", IDS_SETTINGS_SYNC_WILL_START},
+    {"syncWillStart", is_unified_consent_enabled
+                          ? IDS_SETTINGS_SYNC_WILL_START_UNITY
+                          : IDS_SETTINGS_SYNC_WILL_START},
     {"syncSettingsSavedToast", IDS_SETTINGS_SYNC_SETTINGS_SAVED_TOAST_LABEL},
     {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC},
 #endif  // defined(OS_CHROMEOS)
@@ -1726,8 +1728,7 @@
     {"deleteProfileWarningWithoutCounts",
      IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITHOUT_COUNTS},
     {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
-    {"sync", is_unified_consent_enabled ? IDS_SETTINGS_SYNC_UNIFIED_CONSENT
-                                        : IDS_SETTINGS_SYNC},
+    {"sync", IDS_SETTINGS_SYNC},
     {"nonPersonalizedServicesSectionLabel",
      IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL},
     {"syncAndNonPersonalizedServices",
@@ -1735,6 +1736,9 @@
     {"syncPageTitle", is_unified_consent_enabled
                           ? IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES
                           : IDS_SETTINGS_SYNC_PAGE_TITLE},
+    {"syncAdvancedPageTitle", IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE},
+    {"syncAdvancedRowCustomSettings",
+     IDS_SETTINGS_SYNC_ADVANCED_ROW_CUSTOM_SETTINGS},
     {"syncLoading", IDS_SETTINGS_SYNC_LOADING},
     {"syncTimeout", IDS_SETTINGS_SYNC_TIMEOUT},
     {"syncEverythingCheckboxLabel",
@@ -1752,7 +1756,10 @@
     {"openTabsCheckboxLabel", IDS_SETTINGS_OPEN_TABS_CHECKBOX_LABEL},
     {"driveSuggestPref", IDS_DRIVE_SUGGEST_PREF},
     {"driveSuggestPrefDesc", IDS_DRIVE_SUGGEST_PREF_DESC},
-    {"manageSyncedDataTitle", IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE},
+    {"manageSyncedDataTitle",
+     unified_consent::IsUnifiedConsentFeatureEnabled()
+         ? IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT
+         : IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE},
     {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS},
     {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT},
     {"encryptWithGoogleCredentialsLabel",
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index bf223727..1488264 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -68,6 +68,8 @@
                       IDS_SYNC_CONFIRMATION_UNITY_IMPROVE_CHROME_INFO_TITLE);
     AddStringResource(source, "syncConfirmationImproveChromeInfoDesc",
                       IDS_SYNC_CONFIRMATION_UNITY_IMPROVE_CHROME_INFO_DESC);
+    AddStringResource(source, "syncConfirmationSettingsInfo",
+                      IDS_SYNC_CONFIRMATION_UNITY_SETTINGS_INFO);
 
     AddStringResource(source, "syncConfirmationSettingsLabel",
                       IDS_SYNC_CONFIRMATION_DICE_SETTINGS_BUTTON_LABEL);
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 1cdd83bb..d6295571 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/web_applications/components/web_app_install_utils.h"
 
+#include <utility>
+
+#include "base/stl_util.h"
 #include "chrome/browser/installable/installable_data.h"
 #include "chrome/browser/web_applications/components/web_app_icon_generator.h"
 #include "chrome/common/web_application_info.h"
@@ -59,17 +62,30 @@
   if (manifest.theme_color)
     web_app_info->theme_color = *manifest.theme_color;
 
+  // Create the WebApplicationInfo icons list *outside* of |web_app_info|, so
+  // that we can decide later whether or not to replace the existing icons array
+  // (conditionally on whether there were any that didn't have purpose ANY).
+  std::vector<WebApplicationInfo::IconInfo> web_app_icons;
+  for (const auto& icon : manifest.icons) {
+    // An icon's purpose vector should never be empty (the manifest parser
+    // should have added ANY if there was no purpose specified in the manifest).
+    DCHECK(!icon.purpose.empty());
+
+    if (!base::ContainsValue(icon.purpose,
+                             blink::Manifest::ImageResource::Purpose::ANY)) {
+      continue;
+    }
+
+    // TODO(benwells): Take the declared icon density and sizes into account.
+    WebApplicationInfo::IconInfo info;
+    info.url = icon.src;
+    web_app_icons.push_back(info);
+  }
+
   // If any icons are specified in the manifest, they take precedence over any
   // we picked up from the web_app stuff.
-  if (!manifest.icons.empty()) {
-    web_app_info->icons.clear();
-    for (const auto& icon : manifest.icons) {
-      // TODO(benwells): Take the declared icon density and sizes into account.
-      WebApplicationInfo::IconInfo info;
-      info.url = icon.src;
-      web_app_info->icons.push_back(info);
-    }
-  }
+  if (!web_app_icons.empty())
+    web_app_info->icons = std::move(web_app_icons);
 }
 
 std::set<int> SizesToGenerate() {
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
index 3d90072..5b3af0b 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -51,9 +51,14 @@
 
   blink::Manifest::ImageResource icon;
   icon.src = GURL(kAppIcon2);
+  icon.purpose = {blink::Manifest::ImageResource::Purpose::ANY,
+                  blink::Manifest::ImageResource::Purpose::BADGE};
   manifest.icons.push_back(icon);
   icon.src = GURL(kAppIcon3);
   manifest.icons.push_back(icon);
+  // Add an icon without purpose ANY (expect to be ignored).
+  icon.purpose = {blink::Manifest::ImageResource::Purpose::BADGE};
+  manifest.icons.push_back(icon);
 
   UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                ForInstallableSite::kNo);
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 6db55b1..2530f98a 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -68,7 +68,6 @@
 #include "chrome/installer/util/delete_tree_work_item.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/google_update_settings.h"
-#include "chrome/installer/util/google_update_util.h"
 #include "chrome/installer/util/helper.h"
 #include "chrome/installer/util/html_dialog.h"
 #include "chrome/installer/util/install_util.h"
@@ -86,6 +85,10 @@
 #include "components/crash/content/app/run_as_crashpad_handler_win.h"
 #include "content/public/common/content_switches.h"
 
+#if defined(GOOGLE_CHROME_BUILD)
+#include "chrome/installer/util/google_update_util.h"
+#endif
+
 using installer::InstallerState;
 using installer::InstallationState;
 using installer::MasterPreferences;
@@ -641,6 +644,7 @@
   if (!system_level_cmd.GetProgram().empty())
     base::LaunchProcess(system_level_cmd, base::LaunchOptions());
 
+#if defined(GOOGLE_CHROME_BUILD)
   // Tell Google Update that an uninstall has taken place if this install did
   // not originate from the MSI. Google Update has its own logic relating to
   // MSI-driven uninstalls that conflicts with this. Ignore the return value:
@@ -648,6 +652,7 @@
   // failure of Chrome's uninstallation.
   if (!installer_state.is_msi())
     google_update::UninstallGoogleUpdate(installer_state.system_install());
+#endif  // defined(GOOGLE_CHROME_BUILD)
 
   return install_status;
 }
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc
index b5f7f936..b615ef3 100644
--- a/chrome/test/base/web_ui_browser_test.cc
+++ b/chrome/test/base/web_ui_browser_test.cc
@@ -219,12 +219,7 @@
   bool should_wait_flag = base::CommandLine::ForCurrentProcess()->HasSwitch(
       ::content::kWaitForDebuggerWebUI);
 
-  const std::string debugger_port =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          ::switches::kRemoteDebuggingPort);
-
-  // Only wait if there is a debugger port, so user can issue go() command.
-  if (should_wait_flag && !debugger_port.empty())
+  if (should_wait_flag)
     RunJavascriptUsingHandler("setWaitUser", {}, false, false, preload_host);
 }
 
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 4a552ebd..1bc6213 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -610,7 +610,7 @@
     '../test_browser_proxy.js',
     'test_sync_browser_proxy.js',
     'test_util.js',
-    'people_page_sync_controls.js',
+    'people_page_sync_controls_test.js',
   ]),
 };
 
diff --git a/chrome/test/data/webui/settings/people_page_sync_controls.js b/chrome/test/data/webui/settings/people_page_sync_controls_test.js
similarity index 74%
rename from chrome/test/data/webui/settings/people_page_sync_controls.js
rename to chrome/test/data/webui/settings/people_page_sync_controls_test.js
index 5a79974f..7eac1b4 100644
--- a/chrome/test/data/webui/settings/people_page_sync_controls.js
+++ b/chrome/test/data/webui/settings/people_page_sync_controls_test.js
@@ -105,5 +105,49 @@
       }
       return browserProxy.whenCalled('setSyncDatatypes').then(verifyPrefs);
     });
+
+    if (!cr.isChromeOS) {
+      test('ToastNotShownWhenEmbedded', function() {
+        syncControls.syncStatus = {setupInProgress: false};
+        assertFalse(syncControls.$.toast.open);
+
+        syncControls.syncStatus = {setupInProgress: true};
+        assertFalse(syncControls.$.toast.open);
+      });
+    }
+  });
+
+  suite('SyncControlsSubpageTest', function() {
+    let syncControls = null;
+    let browserProxy = null;
+
+    setup(function() {
+      browserProxy = new TestSyncBrowserProxy();
+      settings.SyncBrowserProxyImpl.instance_ = browserProxy;
+
+      PolymerTest.clearBody();
+
+      syncControls = document.createElement('settings-sync-controls');
+      settings.navigateTo(settings.routes.SYNC_ADVANCED);
+      document.body.appendChild(syncControls);
+
+      Polymer.dom.flush();
+    });
+
+    teardown(function() {
+      syncControls.remove();
+    });
+
+    if (!cr.isChromeOS) {
+      test('ToastShownForSyncSetup', function() {
+        syncControls.syncStatus = {setupInProgress: false};
+        assertFalse(syncControls.$.toast.open);
+
+        syncControls.syncStatus = {setupInProgress: true};
+        assertTrue(syncControls.$.toast.open);
+
+        syncControls.$.toast.querySelector('paper-button').click();
+      });
+    }
   });
 });
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js
index 1d56c444..16e4403 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -151,7 +151,7 @@
       assertFalse(syncSection.hidden);
       assertTrue(otherItems.classList.contains('list-frame'));
       assertEquals(
-          otherItems.querySelectorAll(':scope > .list-item').length, 3);
+          otherItems.querySelectorAll(':scope > .list-item').length, 4);
 
       // Test sync paused state.
       syncPage.syncStatus = {
@@ -471,6 +471,19 @@
       });
     });
 
+    test('SyncAdvancedRow', function() {
+      syncPage.unifiedConsentEnabled = true;
+      Polymer.dom.flush();
+
+      const syncAdvancedRow = syncPage.$$('#sync-advanced-row');
+      assertFalse(syncAdvancedRow.hidden);
+
+      syncAdvancedRow.click();
+      Polymer.dom.flush();
+
+      assertEquals(settings.routes.SYNC_ADVANCED, settings.getCurrentRoute());
+    });
+
     if (!cr.isChromeOS) {
       test('FirstTimeSetupNotification', function() {
         assertTrue(!!syncPage.$.toast);
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js
index 573c02a..bb038a4 100644
--- a/chrome/test/data/webui/settings/people_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -580,5 +580,23 @@
 
       assertEquals(settings.getCurrentRoute(), settings.routes.SYNC);
     });
+
+    if (!cr.isChromeOS) {
+      test('CancelSyncSetupOnSyncControlsPage', function() {
+        settings.navigateTo(settings.routes.SYNC);
+        settings.navigateTo(settings.routes.SYNC_ADVANCED);
+        peoplePage.syncStatus = {setupInProgress: true};
+        Polymer.dom.flush();
+
+        peoplePage.$$('settings-sync-controls')
+            .$.toast.querySelector('paper-button')
+            .click();
+
+        return browserProxy.whenCalled('didNavigateAwayFromSyncPage')
+            .then(abort => {
+              assertTrue(abort);
+            });
+      });
+    }
   });
 });
diff --git a/chrome/test/data/webui/signin/sync_confirmation_test.js b/chrome/test/data/webui/signin/sync_confirmation_test.js
index 614ba63..592b27d 100644
--- a/chrome/test/data/webui/signin/sync_confirmation_test.js
+++ b/chrome/test/data/webui/signin/sync_confirmation_test.js
@@ -59,7 +59,7 @@
       'Fix spelling errors with enhanced spell check',
       'The text you type in text fields will be sent to Google.',
       'Help improve Chrome and its security',
-      'Anonymous system and usage data will be sent to Google.'
+      'Sends some system information and page content to Google anonymously.'
     ];
 
 
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index f5c2371a..023e49d1 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -2471,6 +2471,11 @@
   // If the full Sync feature isn't enabled, then do NOT convert any Wallet
   // addresses to local ones.
   if (!IsSyncFeatureEnabled()) {
+    // TODO(crbug.com/915229): Remove once the investigation is over.
+    DLOG(WARNING) << this
+                  << " not converting as sync feature is not enabled, probably "
+                     "due to sync_service_ being "
+                  << sync_service_;
     return false;
   }
 
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index b807a77..1ae14f77 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -31,7 +31,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/reading_list/features/reading_list_switches.h"
 #include "components/sync/base/report_unrecoverable_error.h"
-#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/driver/async_directory_type_controller.h"
 #include "components/sync/driver/data_type_manager_impl.h"
 #include "components/sync/driver/glue/sync_backend_host_impl.h"
@@ -108,8 +107,6 @@
 ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
     syncer::SyncClient* sync_client,
     version_info::Channel channel,
-    const std::string& version,
-    bool is_tablet,
     const char* history_disabled_pref,
     const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
     const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
@@ -121,8 +118,6 @@
     sync_bookmarks::BookmarkSyncService* bookmark_sync_service)
     : sync_client_(sync_client),
       channel_(channel),
-      version_(version),
-      is_tablet_(is_tablet),
       history_disabled_pref_(history_disabled_pref),
       ui_thread_(ui_thread),
       db_thread_(db_thread),
@@ -436,12 +431,6 @@
       name, sync_client_, invalidator, sync_prefs, sync_data_folder);
 }
 
-std::unique_ptr<syncer::LocalDeviceInfoProvider>
-ProfileSyncComponentsFactoryImpl::CreateLocalDeviceInfoProvider() {
-  return std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
-      channel_, version_, is_tablet_);
-}
-
 syncer::SyncApiComponentFactory::SyncComponents
 ProfileSyncComponentsFactoryImpl::CreateBookmarkSyncComponents(
     std::unique_ptr<syncer::DataTypeErrorHandler> error_handler,
diff --git a/components/browser_sync/profile_sync_components_factory_impl.h b/components/browser_sync/profile_sync_components_factory_impl.h
index 9526074..bcd2b05 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/components/browser_sync/profile_sync_components_factory_impl.h
@@ -43,8 +43,6 @@
   ProfileSyncComponentsFactoryImpl(
       syncer::SyncClient* sync_client,
       version_info::Channel channel,
-      const std::string& version,
-      bool is_tablet,
       const char* history_disabled_pref,
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
       const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
@@ -73,8 +71,6 @@
       invalidation::InvalidationService* invalidator,
       const base::WeakPtr<syncer::SyncPrefs>& sync_prefs,
       const base::FilePath& sync_data_folder) override;
-  std::unique_ptr<syncer::LocalDeviceInfoProvider>
-  CreateLocalDeviceInfoProvider() override;
   syncer::SyncApiComponentFactory::SyncComponents CreateBookmarkSyncComponents(
       std::unique_ptr<syncer::DataTypeErrorHandler> error_handler,
       syncer::UserShare* user_share) override;
@@ -111,8 +107,6 @@
   // Client/platform specific members.
   syncer::SyncClient* const sync_client_;
   const version_info::Channel channel_;
-  const std::string version_;
-  const bool is_tablet_;
   const char* history_disabled_pref_;
   const scoped_refptr<base::SingleThreadTaskRunner> ui_thread_;
   const scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 560edb5..a4b797d9 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -161,6 +161,7 @@
 
 ProfileSyncService::ProfileSyncService(InitParams init_params)
     : sync_client_(std::move(init_params.sync_client)),
+      local_device_(std::move(init_params.local_device_info_provider)),
       sync_prefs_(sync_client_->GetPrefService()),
       identity_manager_(init_params.identity_manager),
       user_settings_(this, &sync_prefs_),
@@ -171,11 +172,10 @@
                               base::Unretained(this)),
           base::BindRepeating(&ProfileSyncService::CredentialsChanged,
                               base::Unretained(this)))),
-      channel_(init_params.channel),
       debug_identifier_(init_params.debug_identifier),
       sync_service_url_(
           syncer::GetSyncServiceURL(*base::CommandLine::ForCurrentProcess(),
-                                    init_params.channel)),
+                                    local_device_->GetChannel())),
       crypto_(
           base::BindRepeating(&ProfileSyncService::NotifyObservers,
                               base::Unretained(this)),
@@ -205,6 +205,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(signin_scoped_device_id_callback_);
   DCHECK(sync_client_);
+  DCHECK(local_device_);
 
   // If Sync is disabled via command line flag, then ProfileSyncService
   // shouldn't be instantiated.
@@ -247,9 +248,7 @@
                           base::Unretained(this)),
       base::BindRepeating(&ProfileSyncService::StartUpSlowEngineComponents,
                           base::Unretained(this)));
-  local_device_ = sync_client_->GetSyncApiComponentFactory()
-                      ->CreateLocalDeviceInfoProvider();
-  DCHECK(local_device_);
+
   sync_stopped_reporter_ = std::make_unique<syncer::SyncStoppedReporter>(
       sync_service_url_, local_device_->GetSyncUserAgent(), url_loader_factory_,
       syncer::SyncStoppedReporter::ResultCallback());
@@ -265,7 +264,7 @@
       std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
           syncer::DEVICE_INFO,
           /*dump_stack=*/base::BindRepeating(&syncer::ReportUnrecoverableError,
-                                             channel_)));
+                                             local_device_->GetChannel())));
   data_type_controllers_[syncer::DEVICE_INFO] =
       std::make_unique<syncer::ModelTypeController>(
           syncer::DEVICE_INFO,
@@ -594,8 +593,8 @@
       std::make_unique<EngineComponentsFactoryImpl>(
           EngineSwitchesFromCommandLine());
   params.unrecoverable_error_handler = GetUnrecoverableErrorHandler();
-  params.report_unrecoverable_error_function =
-      base::BindRepeating(syncer::ReportUnrecoverableError, channel_);
+  params.report_unrecoverable_error_function = base::BindRepeating(
+      syncer::ReportUnrecoverableError, local_device_->GetChannel());
   params.saved_nigori_state = crypto_.TakeSavedNigoriState();
   sync_prefs_.GetInvalidationVersions(&params.invalidation_versions);
   params.short_poll_interval = sync_prefs_.GetShortPollInterval();
@@ -726,11 +725,13 @@
       ShutdownImpl(syncer::STOP_SYNC);
       break;
     case CLEAR_DATA:
-      // Clear prefs (including SyncSetupHasCompleted) before shutting down so
-      // PSS clients don't think we're set up while we're shutting down.
-      sync_prefs_.ClearPreferences();
       ClearUnrecoverableError();
       ShutdownImpl(syncer::DISABLE_SYNC);
+      // Clear prefs (including SyncSetupHasCompleted) before shutting down so
+      // PSS clients don't think we're set up while we're shutting down.
+      // Note: We do this after shutting down, so that notifications about the
+      // changed pref values don't mess up our state.
+      sync_prefs_.ClearPreferences();
       break;
   }
 }
@@ -833,15 +834,7 @@
 
 bool ProfileSyncService::IsFirstSetupComplete() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return sync_prefs_.IsFirstSetupComplete();
-}
-
-void ProfileSyncService::SetFirstSetupComplete() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  sync_prefs_.SetFirstSetupComplete();
-  if (engine_initialized_) {
-    ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false);
-  }
+  return user_settings_.IsFirstSetupComplete();
 }
 
 void ProfileSyncService::UpdateLastSyncedTime() {
@@ -1000,7 +993,7 @@
   // Auto-start means IsFirstSetupComplete gets set automatically.
   if (start_behavior_ == AUTO_START && !IsFirstSetupComplete()) {
     // This will trigger a configure if it completes setup.
-    SetFirstSetupComplete();
+    user_settings_.SetFirstSetupComplete();
   } else if (CanConfigureDataTypes(/*bypass_setup_in_progress_check=*/false)) {
     // Datatype downloads on restart are generally due to newly supported
     // datatypes (although it's also possible we're picking up where a failed
@@ -1749,6 +1742,13 @@
   }
 }
 
+void ProfileSyncService::OnFirstSetupCompletePrefChange(
+    bool is_first_setup_complete) {
+  if (engine_initialized_) {
+    ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false);
+  }
+}
+
 void ProfileSyncService::OnGaiaAccountsInCookieUpdated(
     const std::vector<gaia::ListedAccount>& accounts,
     const std::vector<gaia::ListedAccount>& signed_out_accounts,
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 356a291..f1a6444 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -60,6 +60,7 @@
 class BackendMigrator;
 class DeviceInfoSyncBridge;
 class DeviceInfoTracker;
+class LocalDeviceInfoProvider;
 class NetworkResources;
 class SyncTypePreferenceProvider;
 class TypeDebugInfoObserver;
@@ -182,6 +183,7 @@
 
     std::unique_ptr<syncer::SyncClient> sync_client;
     identity::IdentityManager* identity_manager = nullptr;
+    // TODO(mastiz): Move this to LocalDeviceInfoProviderImpl.
     SigninScopedDeviceIdCallback signin_scoped_device_id_callback;
     GaiaCookieManagerService* gaia_cookie_manager_service = nullptr;
     std::vector<invalidation::IdentityProvider*>
@@ -191,7 +193,7 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
     network::NetworkConnectionTracker* network_connection_tracker = nullptr;
     std::string debug_identifier;
-    version_info::Channel channel = version_info::Channel::UNKNOWN;
+    std::unique_ptr<syncer::LocalDeviceInfoProvider> local_device_info_provider;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(InitParams);
@@ -203,6 +205,7 @@
 
   // Initializes the object. This must be called at most once, and
   // immediately after an object of this class is constructed.
+  // TODO(mastiz): Rename this to Start().
   void Initialize();
 
   // syncer::SyncService implementation
@@ -226,7 +229,6 @@
   syncer::ModelTypeSet GetActiveDataTypes() const override;
   void OnUserChoseDatatypes(bool sync_everything,
                             syncer::ModelTypeSet chosen_types);
-  virtual void SetFirstSetupComplete();  // Virtual for testing.
   std::unique_ptr<syncer::SyncSetupInProgressHandle> GetSetupInProgressHandle()
       override;
   bool IsSetupInProgress() const override;
@@ -370,6 +372,7 @@
 
   // SyncPrefObserver implementation.
   void OnSyncManagedPrefChange(bool is_sync_managed) override;
+  void OnFirstSetupCompletePrefChange(bool is_first_setup_complete) override;
 
   // See the SyncServiceCrypto header.
   // Virtual for testing.
@@ -538,6 +541,8 @@
   // the Sync API component factory.
   const std::unique_ptr<syncer::SyncClient> sync_client_;
 
+  const std::unique_ptr<syncer::LocalDeviceInfoProvider> local_device_;
+
   // The class that handles getting, setting, and persisting sync preferences.
   syncer::SyncPrefs sync_prefs_;
 
@@ -551,9 +556,6 @@
   // Only null after Shutdown().
   std::unique_ptr<SyncAuthManager> auth_manager_;
 
-  // The product channel of the embedder.
-  const version_info::Channel channel_;
-
   // An identifier representing this instance for debugging purposes.
   const std::string debug_identifier_;
 
@@ -658,8 +660,6 @@
   std::vector<invalidation::IdentityProvider*> const
       invalidations_identity_providers_;
 
-  std::unique_ptr<syncer::LocalDeviceInfoProvider> local_device_;
-
   std::unique_ptr<syncer::DeviceInfoSyncBridge> device_info_sync_bridge_;
 
   // List of available data type controllers.
diff --git a/components/browser_sync/profile_sync_service_mock.cc b/components/browser_sync/profile_sync_service_mock.cc
index cf833f274..979804a 100644
--- a/components/browser_sync/profile_sync_service_mock.cc
+++ b/components/browser_sync/profile_sync_service_mock.cc
@@ -76,10 +76,6 @@
   return user_settings_.IsFirstSetupComplete();
 }
 
-void ProfileSyncServiceMock::SetFirstSetupComplete() {
-  user_settings_.SetFirstSetupComplete();
-}
-
 syncer::PassphraseType ProfileSyncServiceMock::GetPassphraseType() const {
   return user_settings_.GetPassphraseType();
 }
diff --git a/components/browser_sync/profile_sync_service_mock.h b/components/browser_sync/profile_sync_service_mock.h
index 51cad7e..ca31491 100644
--- a/components/browser_sync/profile_sync_service_mock.h
+++ b/components/browser_sync/profile_sync_service_mock.h
@@ -93,7 +93,6 @@
 
   // ProfileSyncService overrides.
   bool IsFirstSetupComplete() const override;
-  void SetFirstSetupComplete() override;
 
   MOCK_CONST_METHOD1(IsDataTypeControllerRunning, bool(syncer::ModelType));
 
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc
index 1258a65..6417891 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/browser_sync/profile_sync_test_util.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/sync/base/pref_names.h"
+#include "components/sync/device_info/local_device_info_provider.h"
 #include "components/sync/driver/configure_context.h"
 #include "components/sync/driver/fake_data_type_controller.h"
 #include "components/sync/driver/sync_api_component_factory_mock.h"
diff --git a/components/browser_sync/profile_sync_test_util.cc b/components/browser_sync/profile_sync_test_util.cc
index 8160ec9..876cf0c 100644
--- a/components/browser_sync/profile_sync_test_util.cc
+++ b/components/browser_sync/profile_sync_test_util.cc
@@ -17,6 +17,7 @@
 #include "components/history/core/browser/sync/history_model_worker.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync/base/sync_prefs.h"
+#include "components/sync/device_info/local_device_info_provider_mock.h"
 #include "components/sync/engine/passive_model_worker.h"
 #include "components/sync/engine/sequenced_model_worker.h"
 #include "components/sync/engine/ui_model_worker.h"
@@ -238,7 +239,8 @@
   init_params.network_connection_tracker =
       network::TestNetworkConnectionTracker::GetInstance();
   init_params.debug_identifier = "dummyDebugName";
-  init_params.channel = version_info::Channel::UNKNOWN;
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderMock>();
 
   return init_params;
 }
diff --git a/components/browser_sync/sync_user_settings_impl.cc b/components/browser_sync/sync_user_settings_impl.cc
index 2d3fb1d..67272f9c 100644
--- a/components/browser_sync/sync_user_settings_impl.cc
+++ b/components/browser_sync/sync_user_settings_impl.cc
@@ -46,13 +46,11 @@
 }
 
 bool SyncUserSettingsImpl::IsFirstSetupComplete() const {
-  // TODO(crbug.com/884159): Query prefs directly.
-  return service_->IsFirstSetupComplete();
+  return prefs_->IsFirstSetupComplete();
 }
 
 void SyncUserSettingsImpl::SetFirstSetupComplete() {
-  // TODO(crbug.com/884159): Write to prefs directly.
-  service_->SetFirstSetupComplete();
+  prefs_->SetFirstSetupComplete();
 }
 
 bool SyncUserSettingsImpl::IsSyncEverythingEnabled() const {
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 5c58556d..6d63c45 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -775,7 +775,14 @@
                       pending_login_managers_.size());
   }
 
-  if (is_only_new_parser_enabled_)
+  bool html_scheme =
+      !forms.empty() && forms[0].scheme == PasswordForm::SCHEME_HTML;
+
+  // Create PasswordFormManager for non-html scheme even if
+  // |is_only_new_parser_enabled_|.
+  // TODO(https://crbug.com/915161) Implement support of non-html schemes in
+  // NewPasswordFormManager.
+  if (html_scheme && is_only_new_parser_enabled_)
     return;
 
   for (const PasswordForm& form : forms) {
@@ -1313,6 +1320,13 @@
 }
 
 PasswordFormManagerInterface* PasswordManager::GetSubmittedManager() const {
+  // TODO(https://crbug.com/915161) Implement support of non-html schemes in
+  // NewPasswordFormManager remove using PasswordFormManager for such forms.
+  if (provisional_save_manager_ &&
+      provisional_save_manager_->GetPendingCredentials().scheme !=
+          PasswordForm::SCHEME_HTML)
+    return provisional_save_manager_.get();
+
   if (!is_new_form_parsing_for_saving_enabled_)
     return provisional_save_manager_.get();
 
@@ -1330,6 +1344,13 @@
 
 std::unique_ptr<PasswordFormManagerForUI>
 PasswordManager::MoveOwnedSubmittedManager() {
+  // TODO(https://crbug.com/915161) Implement support of non-html schemes in
+  // NewPasswordFormManager remove using PasswordFormManager for such forms.
+  if (provisional_save_manager_ &&
+      provisional_save_manager_->GetPendingCredentials().scheme !=
+          PasswordForm::SCHEME_HTML)
+    return std::move(provisional_save_manager_);
+
   if (!is_new_form_parsing_for_saving_enabled_)
     return std::move(provisional_save_manager_);
 
diff --git a/components/search_provider_logos/BUILD.gn b/components/search_provider_logos/BUILD.gn
index d0a30917..9d9dad4 100644
--- a/components/search_provider_logos/BUILD.gn
+++ b/components/search_provider_logos/BUILD.gn
@@ -35,6 +35,7 @@
     "//components/search_engines",
     "//components/signin/core/browser",
     "//net",
+    "//services/identity/public/cpp",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
     "//ui/gfx",
@@ -100,6 +101,7 @@
     "//components/signin/core/browser:test_support",
     "//components/sync_preferences:test_support",
     "//net:test_support",
+    "//services/identity/public/cpp:test_support",
     "//services/network:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/search_provider_logos/DEPS b/components/search_provider_logos/DEPS
index cb441f1..b1b176fd 100644
--- a/components/search_provider_logos/DEPS
+++ b/components/search_provider_logos/DEPS
@@ -6,6 +6,7 @@
   "+components/signin/core/browser",
   "+components/sync_preferences/testing_pref_service_syncable.h",
   "+net",
+  "+services/identity/public/cpp",
   "+services/network/public/cpp",
   "+services/network/public/mojom",
   "+services/network/test",
diff --git a/components/search_provider_logos/logo_service_impl.cc b/components/search_provider_logos/logo_service_impl.cc
index 38a724b5..cd61ca1 100644
--- a/components/search_provider_logos/logo_service_impl.cc
+++ b/components/search_provider_logos/logo_service_impl.cc
@@ -27,9 +27,9 @@
 #include "components/search_provider_logos/logo_cache.h"
 #include "components/search_provider_logos/logo_observer.h"
 #include "components/search_provider_logos/switches.h"
-#include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/identity/public/cpp/identity_manager.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "ui/gfx/image/image.h"
@@ -179,39 +179,37 @@
 }  // namespace
 
 class LogoServiceImpl::SigninObserver
-    : public GaiaCookieManagerService::Observer {
+    : public identity::IdentityManager::Observer {
  public:
   using SigninStatusChangedCallback = base::RepeatingClosure;
 
-  SigninObserver(GaiaCookieManagerService* cookie_service,
+  SigninObserver(identity::IdentityManager* identity_manager,
                  const SigninStatusChangedCallback& callback)
-      : cookie_service_(cookie_service), callback_(callback) {
-    if (cookie_service_) {
-      cookie_service_->AddObserver(this);
+      : identity_manager_(identity_manager), callback_(callback) {
+    if (identity_manager_) {
+      identity_manager_->AddObserver(this);
     }
   }
 
   ~SigninObserver() override {
-    if (cookie_service_) {
-      cookie_service_->RemoveObserver(this);
+    if (identity_manager_) {
+      identity_manager_->RemoveObserver(this);
     }
   }
 
  private:
-  // GaiaCookieManagerService::Observer implementation.
-  void OnGaiaAccountsInCookieUpdated(const std::vector<gaia::ListedAccount>&,
-                                     const std::vector<gaia::ListedAccount>&,
-                                     const GoogleServiceAuthError&) override {
+  // identity::IdentityManager::Observer implementation.
+  void OnAccountsInCookieUpdated(const std::vector<AccountInfo>&) override {
     callback_.Run();
   }
 
-  GaiaCookieManagerService* const cookie_service_;
+  identity::IdentityManager* const identity_manager_;
   SigninStatusChangedCallback callback_;
 };
 
 LogoServiceImpl::LogoServiceImpl(
     const base::FilePath& cache_directory,
-    GaiaCookieManagerService* cookie_service,
+    identity::IdentityManager* identity_manager,
     TemplateURLService* template_url_service,
     std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
@@ -222,7 +220,7 @@
       want_gray_logo_getter_(std::move(want_gray_logo_getter)),
       image_decoder_(std::move(image_decoder)),
       signin_observer_(std::make_unique<SigninObserver>(
-          cookie_service,
+          identity_manager,
           base::BindRepeating(&LogoServiceImpl::SigninStatusChanged,
                               base::Unretained(this)))),
       is_idle_(true),
@@ -237,7 +235,7 @@
 LogoServiceImpl::~LogoServiceImpl() = default;
 
 void LogoServiceImpl::Shutdown() {
-  // The GaiaCookieManagerService may be destroyed at any point after Shutdown,
+  // The IdentityManager may be destroyed at any point after Shutdown,
   // so make sure we drop any references to it.
   signin_observer_.reset();
   ReturnToIdle(kDownloadOutcomeNotTracked);
diff --git a/components/search_provider_logos/logo_service_impl.h b/components/search_provider_logos/logo_service_impl.h
index 276d72f23..e9ad413a 100644
--- a/components/search_provider_logos/logo_service_impl.h
+++ b/components/search_provider_logos/logo_service_impl.h
@@ -20,7 +20,6 @@
 #include "components/search_provider_logos/logo_common.h"
 #include "components/search_provider_logos/logo_service.h"
 
-class GaiaCookieManagerService;
 class TemplateURLService;
 
 namespace base {
@@ -31,6 +30,10 @@
 class ImageDecoder;
 }  // namespace image_fetcher
 
+namespace identity {
+class IdentityManager;
+}  // namespace identity
+
 namespace network {
 class SimpleURLLoader;
 class SharedURLLoaderFactory;
@@ -45,7 +48,7 @@
  public:
   LogoServiceImpl(
       const base::FilePath& cache_directory,
-      GaiaCookieManagerService* cookie_service,
+      identity::IdentityManager* identity_manager,
       TemplateURLService* template_url_service,
       std::unique_ptr<image_fetcher::ImageDecoder> image_decoder,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc
index 2329e6996..9fa8113 100644
--- a/components/search_provider_logos/logo_service_impl_unittest.cc
+++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -39,6 +39,7 @@
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_signin_manager.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "net/base/url_util.h"
@@ -46,6 +47,7 @@
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/identity/public/cpp/identity_test_environment.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -76,6 +78,12 @@
 using MockLogoCallback = base::MockCallback<LogoCallback>;
 using MockEncodedLogoCallback = base::MockCallback<EncodedLogoCallback>;
 
+#if defined(OS_CHROMEOS)
+using SigninManagerForTest = FakeSigninManagerBase;
+#else
+using SigninManagerForTest = FakeSigninManager;
+#endif  // OS_CHROMEOS
+
 scoped_refptr<base::RefCountedString> EncodeBitmapAsPNG(
     const SkBitmap& bitmap) {
   scoped_refptr<base::RefCountedMemory> png_bytes =
@@ -287,13 +295,27 @@
         token_service_(&pref_service_),
         cookie_service_(&token_service_,
                         &signin_client_,
-                        &test_url_loader_factory_) {
+                        &test_url_loader_factory_),
+#if defined(OS_CHROMEOS)
+        signin_manager_(&signin_client_, &account_tracker_service_),
+#else
+        signin_manager_(&signin_client_,
+                        &token_service_,
+                        &account_tracker_service_,
+                        &cookie_service_),
+#endif
+        identity_test_env_(&account_tracker_service_,
+                           &token_service_,
+                           &signin_manager_,
+                           &cookie_service_) {
     // GaiaCookieManagerService calls static methods of AccountTrackerService
     // which access prefs.
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
   }
 
-  GaiaCookieManagerService* cookie_service() { return &cookie_service_; }
+  identity::IdentityManager* identity_manager() {
+    return identity_test_env_.identity_manager();
+  }
 
   void SignIn() {
     cookie_service_.SetListAccountsResponseOneAccount("user@gmail.com",
@@ -314,8 +336,11 @@
   TestingPrefServiceSyncable pref_service_;
   TestSigninClient signin_client_;
   FakeProfileOAuth2TokenService token_service_;
+  AccountTrackerService account_tracker_service_;
   network::TestURLLoaderFactory test_url_loader_factory_;
   FakeGaiaCookieManagerService cookie_service_;
+  SigninManagerForTest signin_manager_;
+  identity::IdentityTestEnvironment identity_test_env_;
 };
 
 class LogoServiceImplTest : public ::testing::Test {
@@ -339,7 +364,7 @@
 
     test_clock_.SetNow(base::Time::FromJsTime(INT64_C(1388686828000)));
     logo_service_ = std::make_unique<LogoServiceImpl>(
-        base::FilePath(), signin_helper_.cookie_service(),
+        base::FilePath(), signin_helper_.identity_manager(),
         &template_url_service_, std::make_unique<FakeImageDecoder>(),
         shared_factory_,
         base::BindRepeating(&LogoServiceImplTest::use_gray_background,
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 4b6d131..c553e78 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -8,6 +8,11 @@
 import("//components/sync/protocol/protocol_sources.gni")
 import("//testing/test.gni")
 
+declare_args() {
+  # Controls the product part of the user agent calculated in sync_util.cc.
+  sync_user_agent_product = "Chrome"
+}
+
 jumbo_static_library("sync") {
   sources = [
     "base/bind_to_task_runner.h",
@@ -622,6 +627,8 @@
     ]
   }
 
+  defines = [ "SYNC_USER_AGENT_PRODUCT=$sync_user_agent_product" ]
+
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 }
 
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index b267351..7de3c795 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -71,7 +71,12 @@
   // appropriate action.
   pref_sync_managed_.Init(
       prefs::kSyncManaged, pref_service_,
-      base::Bind(&SyncPrefs::OnSyncManagedPrefChanged, base::Unretained(this)));
+      base::BindRepeating(&SyncPrefs::OnSyncManagedPrefChanged,
+                          base::Unretained(this)));
+  pref_first_setup_complete_.Init(
+      prefs::kSyncFirstSetupComplete, pref_service_,
+      base::BindRepeating(&SyncPrefs::OnFirstSetupCompletePrefChange,
+                          base::Unretained(this)));
   // Cache the value of the kEnableLocalSyncBackend pref to avoid it flipping
   // during the lifetime of the service.
   local_sync_enabled_ =
@@ -421,6 +426,12 @@
     observer.OnSyncManagedPrefChange(*pref_sync_managed_);
 }
 
+void SyncPrefs::OnFirstSetupCompletePrefChange() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (auto& observer : sync_pref_observers_)
+    observer.OnFirstSetupCompletePrefChange(*pref_first_setup_complete_);
+}
+
 void SyncPrefs::SetManagedForTest(bool is_managed) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   pref_service_->SetBoolean(prefs::kSyncManaged, is_managed);
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h
index 03992e3..b852ceb6 100644
--- a/components/sync/base/sync_prefs.h
+++ b/components/sync/base/sync_prefs.h
@@ -32,8 +32,8 @@
 
 class SyncPrefObserver {
  public:
-  // Called whenever the pref that controls whether sync is managed changes.
   virtual void OnSyncManagedPrefChange(bool is_sync_managed) = 0;
+  virtual void OnFirstSetupCompletePrefChange(bool is_first_setup_complete) = 0;
 
  protected:
   virtual ~SyncPrefObserver();
@@ -217,6 +217,7 @@
   void SetDataTypePreferred(ModelType type, bool is_preferred);
 
   void OnSyncManagedPrefChanged();
+  void OnFirstSetupCompletePrefChange();
 
   // Never null.
   PrefService* const pref_service_;
@@ -227,6 +228,8 @@
   // configuration management.
   BooleanPrefMember pref_sync_managed_;
 
+  BooleanPrefMember pref_first_setup_complete_;
+
   bool local_sync_enabled_;
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/components/sync/base/sync_prefs_unittest.cc b/components/sync/base/sync_prefs_unittest.cc
index d106ddec..81ac2e1f 100644
--- a/components/sync/base/sync_prefs_unittest.cc
+++ b/components/sync/base/sync_prefs_unittest.cc
@@ -74,6 +74,7 @@
 class MockSyncPrefObserver : public SyncPrefObserver {
  public:
   MOCK_METHOD1(OnSyncManagedPrefChange, void(bool));
+  MOCK_METHOD1(OnFirstSetupCompletePrefChange, void(bool));
 };
 
 TEST_F(SyncPrefsTest, ObservedPrefs) {
@@ -81,8 +82,11 @@
   InSequence dummy;
   EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(true));
   EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(false));
+  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(true));
+  EXPECT_CALL(mock_sync_pref_observer, OnFirstSetupCompletePrefChange(false));
 
   EXPECT_FALSE(sync_prefs_->IsManaged());
+  EXPECT_FALSE(sync_prefs_->IsFirstSetupComplete());
 
   sync_prefs_->AddSyncPrefObserver(&mock_sync_pref_observer);
 
@@ -91,6 +95,13 @@
   sync_prefs_->SetManagedForTest(false);
   EXPECT_FALSE(sync_prefs_->IsManaged());
 
+  sync_prefs_->SetFirstSetupComplete();
+  EXPECT_TRUE(sync_prefs_->IsFirstSetupComplete());
+  // There's no direct way to clear the first-setup-complete bit, so just reset
+  // all prefs instead.
+  sync_prefs_->ClearPreferences();
+  EXPECT_FALSE(sync_prefs_->IsFirstSetupComplete());
+
   sync_prefs_->RemoveSyncPrefObserver(&mock_sync_pref_observer);
 }
 
diff --git a/components/sync/device_info/local_device_info_provider.h b/components/sync/device_info/local_device_info_provider.h
index 678f77e..7ff6b5b 100644
--- a/components/sync/device_info/local_device_info_provider.h
+++ b/components/sync/device_info/local_device_info_provider.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/callback_list.h"
+#include "components/version_info/version_info.h"
 
 namespace syncer {
 
@@ -22,6 +23,8 @@
 
   virtual ~LocalDeviceInfoProvider() {}
 
+  virtual version_info::Channel GetChannel() const = 0;
+
   // Returns sync's representation of the local device info, or nullptr if the
   // device info is unavailable (e.g. Initialize() hasn't been called). The
   // returned object is fully owned by LocalDeviceInfoProvider; it must not be
diff --git a/components/sync/device_info/local_device_info_provider_impl.cc b/components/sync/device_info/local_device_info_provider_impl.cc
index 6a4651a..5b42c212 100644
--- a/components/sync/device_info/local_device_info_provider_impl.cc
+++ b/components/sync/device_info/local_device_info_provider_impl.cc
@@ -46,6 +46,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+version_info::Channel LocalDeviceInfoProviderImpl::GetChannel() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return channel_;
+}
+
 const DeviceInfo* LocalDeviceInfoProviderImpl::GetLocalDeviceInfo() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return local_device_info_.get();
diff --git a/components/sync/device_info/local_device_info_provider_impl.h b/components/sync/device_info/local_device_info_provider_impl.h
index 304ca0c0..0268004 100644
--- a/components/sync/device_info/local_device_info_provider_impl.h
+++ b/components/sync/device_info/local_device_info_provider_impl.h
@@ -25,6 +25,7 @@
   ~LocalDeviceInfoProviderImpl() override;
 
   // LocalDeviceInfoProvider implementation.
+  version_info::Channel GetChannel() const override;
   const DeviceInfo* GetLocalDeviceInfo() const override;
   std::string GetSyncUserAgent() const override;
   std::string GetLocalSyncCacheGUID() const override;
diff --git a/components/sync/device_info/local_device_info_provider_mock.cc b/components/sync/device_info/local_device_info_provider_mock.cc
index 77cd315..7203c69 100644
--- a/components/sync/device_info/local_device_info_provider_mock.cc
+++ b/components/sync/device_info/local_device_info_provider_mock.cc
@@ -25,6 +25,10 @@
 
 LocalDeviceInfoProviderMock::~LocalDeviceInfoProviderMock() {}
 
+version_info::Channel LocalDeviceInfoProviderMock::GetChannel() const {
+  return version_info::Channel::UNKNOWN;
+}
+
 const DeviceInfo* LocalDeviceInfoProviderMock::GetLocalDeviceInfo() const {
   return is_initialized_ ? local_device_info_.get() : nullptr;
 }
diff --git a/components/sync/device_info/local_device_info_provider_mock.h b/components/sync/device_info/local_device_info_provider_mock.h
index 1122a087..c08fd0cd 100644
--- a/components/sync/device_info/local_device_info_provider_mock.h
+++ b/components/sync/device_info/local_device_info_provider_mock.h
@@ -10,6 +10,7 @@
 
 #include "components/sync/device_info/device_info.h"
 #include "components/sync/device_info/local_device_info_provider.h"
+#include "components/version_info/version_info.h"
 
 namespace syncer {
 
@@ -26,6 +27,7 @@
                               const std::string& signin_scoped_device_id);
   ~LocalDeviceInfoProviderMock() override;
 
+  version_info::Channel GetChannel() const override;
   const DeviceInfo* GetLocalDeviceInfo() const override;
   std::string GetSyncUserAgent() const override;
   std::string GetLocalSyncCacheGUID() const override;
diff --git a/components/sync/driver/fake_sync_client.cc b/components/sync/driver/fake_sync_client.cc
index d5dd474..513203a8 100644
--- a/components/sync/driver/fake_sync_client.cc
+++ b/components/sync/driver/fake_sync_client.cc
@@ -15,9 +15,6 @@
 FakeSyncClient::FakeSyncClient() : bridge_(nullptr), factory_(nullptr) {
   // Register sync preferences and set them to "Sync everything" state.
   SyncPrefs::RegisterProfilePrefs(pref_service_.registry());
-  SyncPrefs sync_prefs(GetPrefService());
-  sync_prefs.SetFirstSetupComplete();
-  sync_prefs.SetKeepEverythingSynced(true);
 }
 
 FakeSyncClient::FakeSyncClient(SyncApiComponentFactory* factory)
diff --git a/components/sync/driver/sync_api_component_factory.h b/components/sync/driver/sync_api_component_factory.h
index 31f7b99..80ab038 100644
--- a/components/sync/driver/sync_api_component_factory.h
+++ b/components/sync/driver/sync_api_component_factory.h
@@ -30,7 +30,6 @@
 class DataTypeEncryptionHandler;
 class DataTypeManager;
 class DataTypeManagerObserver;
-class LocalDeviceInfoProvider;
 class SyncEngine;
 class SyncPrefs;
 class SyncService;
@@ -84,10 +83,6 @@
       const base::WeakPtr<SyncPrefs>& sync_prefs,
       const base::FilePath& sync_folder) = 0;
 
-  // Creating this in the factory helps us mock it out in testing.
-  virtual std::unique_ptr<LocalDeviceInfoProvider>
-  CreateLocalDeviceInfoProvider() = 0;
-
   // Legacy datatypes that need to be converted to the SyncableService API.
   virtual SyncComponents CreateBookmarkSyncComponents(
       std::unique_ptr<DataTypeErrorHandler> error_handler,
diff --git a/components/sync/driver/sync_api_component_factory_mock.cc b/components/sync/driver/sync_api_component_factory_mock.cc
index e675211c..d77d51c 100644
--- a/components/sync/driver/sync_api_component_factory_mock.cc
+++ b/components/sync/driver/sync_api_component_factory_mock.cc
@@ -4,20 +4,9 @@
 
 #include "components/sync/driver/sync_api_component_factory_mock.h"
 
-#include <utility>
-
-#include "components/sync/device_info/local_device_info_provider_mock.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
 namespace syncer {
 
-SyncApiComponentFactoryMock::SyncApiComponentFactoryMock() {
-  // To avoid returning nulls and crashes in many tests, we default to create
-  // a mock device info provider.
-  ON_CALL(*this, CreateLocalDeviceInfoProvider())
-      .WillByDefault(testing::Invoke(
-          []() { return std::make_unique<LocalDeviceInfoProviderMock>(); }));
-}
+SyncApiComponentFactoryMock::SyncApiComponentFactoryMock() = default;
 
 SyncApiComponentFactoryMock::~SyncApiComponentFactoryMock() = default;
 
diff --git a/components/sync/driver/sync_api_component_factory_mock.h b/components/sync/driver/sync_api_component_factory_mock.h
index de90d434..fe6167b 100644
--- a/components/sync/driver/sync_api_component_factory_mock.h
+++ b/components/sync/driver/sync_api_component_factory_mock.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "components/sync/base/model_type.h"
-#include "components/sync/device_info/local_device_info_provider.h"
 #include "components/sync/driver/data_type_controller.h"
 #include "components/sync/driver/data_type_manager.h"
 #include "components/sync/driver/model_associator.h"
@@ -45,8 +44,6 @@
                    invalidation::InvalidationService* invalidator,
                    const base::WeakPtr<SyncPrefs>& sync_prefs,
                    const base::FilePath& sync_folder));
-  MOCK_METHOD0(CreateLocalDeviceInfoProvider,
-               std::unique_ptr<LocalDeviceInfoProvider>());
   MOCK_METHOD2(
       CreateBookmarkSyncComponents,
       SyncComponents(std::unique_ptr<DataTypeErrorHandler> error_handler,
diff --git a/components/sync/driver/sync_session_durations_metrics_recorder.cc b/components/sync/driver/sync_session_durations_metrics_recorder.cc
index c56b089..e5a7ac8 100644
--- a/components/sync/driver/sync_session_durations_metrics_recorder.cc
+++ b/components/sync/driver/sync_session_durations_metrics_recorder.cc
@@ -58,6 +58,8 @@
 }
 
 SyncSessionDurationsMetricsRecorder::~SyncSessionDurationsMetricsRecorder() {
+  DCHECK(!total_session_timer_) << "Missing a call to OnSessionEnded().";
+
   gaia_cookie_observer_.RemoveAll();
   sync_observer_.RemoveAll();
   identity_manager_observer_.RemoveAll();
diff --git a/components/sync/driver/sync_util.cc b/components/sync/driver/sync_util.cc
index 47d3c6d..e0af30a 100644
--- a/components/sync/driver/sync_util.cc
+++ b/components/sync/driver/sync_util.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/strings/stringize_macros.h"
 #include "build/build_config.h"
 #include "components/sync/driver/sync_driver_switches.h"
 #include "url/gurl.h"
@@ -55,8 +56,9 @@
 
 std::string FormatUserAgentForSync(const std::string& system,
                                    version_info::Channel channel) {
+  std::string product = STRINGIZE(SYNC_USER_AGENT_PRODUCT);
   std::string user_agent;
-  user_agent = "Chrome ";
+  user_agent = product + " ";
   user_agent += system;
   user_agent += version_info::GetVersionNumber();
   user_agent += " (" + version_info::GetLastChange() + ")";
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc
index 63c9eacd..3e8f18c 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -195,6 +195,10 @@
   return bookmark_tracker_.get();
 }
 
+bool BookmarkModelTypeProcessor::IsConnectedForTest() const {
+  return worker_ != nullptr;
+}
+
 std::string BookmarkModelTypeProcessor::EncodeSyncMetadata() const {
   std::string metadata_str;
   if (bookmark_tracker_) {
@@ -382,7 +386,10 @@
   bookmark_model_->RemoveObserver(bookmark_model_observer_.get());
   bookmark_model_ = nullptr;
   bookmark_model_observer_.reset();
-  DisconnectSync();
+
+  if (worker_) {
+    DisconnectSync();
+  }
 }
 
 void BookmarkModelTypeProcessor::StartTrackingMetadata(
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.h b/components/sync_bookmarks/bookmark_model_type_processor.h
index 2e1f269..f0a9ce58 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor.h
+++ b/components/sync_bookmarks/bookmark_model_type_processor.h
@@ -83,6 +83,7 @@
   size_t EstimateMemoryUsage() const;
 
   const SyncedBookmarkTracker* GetTrackerForTest() const;
+  bool IsConnectedForTest() const;
 
   base::WeakPtr<syncer::ModelTypeControllerDelegate> GetWeakPtr();
 
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index b1d5c46..13d820d 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -135,8 +135,8 @@
 class BookmarkModelTypeProcessorTest : public testing::Test {
  public:
   BookmarkModelTypeProcessorTest()
-      : bookmark_model_(bookmarks::TestBookmarkClient::CreateModel()),
-        processor_(&bookmark_undo_service_) {
+      : processor_(&bookmark_undo_service_),
+        bookmark_model_(bookmarks::TestBookmarkClient::CreateModel()) {
     // TODO(crbug.com/516866): This class assumes model is loaded and sync has
     // started before running tests. We should test other variations (i.e. model
     // isn't loaded yet and/or sync didn't start yet).
@@ -155,6 +155,8 @@
     processor_.OnSyncStarting(request, base::DoNothing());
   }
 
+  void DestroyBookmarkModel() { bookmark_model_.reset(); }
+
   bookmarks::BookmarkModel* bookmark_model() { return bookmark_model_.get(); }
   BookmarkUndoService* bookmark_undo_service() {
     return &bookmark_undo_service_;
@@ -168,10 +170,10 @@
  private:
   base::test::ScopedTaskEnvironment task_environment_;
   NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
-  std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
   BookmarkUndoService bookmark_undo_service_;
   NiceMock<favicon::MockFaviconService> favicon_service_;
   BookmarkModelTypeProcessor processor_;
+  std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
 };
 
 TEST_F(BookmarkModelTypeProcessorTest, ShouldUpdateModelAfterRemoteCreation) {
@@ -367,6 +369,13 @@
                                  bookmark_model());
 
   AssertState(&new_processor, bookmarks);
+
+  // Make sure shutdown doesn't crash.
+  DestroyBookmarkModel();
+  EXPECT_FALSE(processor()->IsConnectedForTest());
+  EXPECT_FALSE(new_processor.IsConnectedForTest());
+  EXPECT_THAT(processor()->GetTrackerForTest(), NotNull());
+  EXPECT_THAT(new_processor.GetTrackerForTest(), NotNull());
 }
 
 TEST_F(BookmarkModelTypeProcessorTest,
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index c225dfb..00ed4c34 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -532,37 +532,10 @@
 
 void SyncedBookmarkTracker::CheckAllNodesTracked(
     const bookmarks::BookmarkModel* bookmark_model) const {
-  // TODO(crbug.com/516866): The method is added to debug some crashes.
-  // Since it's relatively expensive, it should run on debug enabled
-  // builds only after the root cause is found.
+  // TODO(crbug.com/516866): Introduce logic to validate the invariant of the
+  // tracker.
   CHECK(GetEntityForBookmarkNode(bookmark_model->bookmark_bar_node()));
   CHECK(GetEntityForBookmarkNode(bookmark_model->other_node()));
-
-  ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
-      bookmark_model->root_node());
-  while (iterator.has_next()) {
-    const bookmarks::BookmarkNode* node = iterator.Next();
-    if (!bookmark_model->client()->CanSyncNode(node)) {
-      // TODO(crbug.com/516866): The below CHECK is added to debug some crashes.
-      // Should be converted to a DCHECK after the root cause if found.
-      CHECK(!GetEntityForBookmarkNode(node));
-      continue;
-    }
-    // Root node is usually tracked, except the sync data has been provided by
-    // the USS migrator.
-    if (node == bookmark_model->root_node()) {
-      continue;
-    }
-    // Mobile bookmarks folder is created on the server only after signing-in
-    // with a mobile client. Therefore, it should not be considered for
-    // validation.
-    if (node == bookmark_model->mobile_node()) {
-      continue;
-    }
-    // TODO(crbug.com/516866): The below CHECK is added to debug some crashes.
-    // Should be converted to a DCHECK after the root cause if found.
-    CHECK(GetEntityForBookmarkNode(node));
-  }
 }
 
 }  // namespace sync_bookmarks
diff --git a/content/browser/media/midi_host.cc b/content/browser/media/midi_host.cc
index 138349915..5b20f75 100644
--- a/content/browser/media/midi_host.cc
+++ b/content/browser/media/midi_host.cc
@@ -79,8 +79,6 @@
         ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMidiSysExMessage(
             renderer_process_id_);
     midi_session_.Bind(std::move(pending_session_request_));
-    midi_session_.set_connection_error_handler(
-        base::BindOnce(&MidiHost::EndSession, base::Unretained(this)));
   }
   midi_client_->SessionStarted(result);
 }
@@ -176,6 +174,8 @@
 
   DCHECK(!midi_client_);
   midi_client_ = std::move(client);
+  midi_client_.set_connection_error_handler(
+      base::BindOnce(&MidiHost::EndSession, base::Unretained(this)));
 
   if (midi_service_)
     midi_service_->StartSession(this);
diff --git a/content/browser/media/midi_host_unittest.cc b/content/browser/media/midi_host_unittest.cc
index dd2a58d..d345361 100644
--- a/content/browser/media/midi_host_unittest.cc
+++ b/content/browser/media/midi_host_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "media/midi/midi_manager.h"
 #include "media/midi/midi_service.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -105,6 +106,22 @@
   DISALLOW_COPY_AND_ASSIGN(MidiHostForTesting);
 };
 
+class MidiSessionClientForTesting : public midi::mojom::MidiSessionClient {
+ public:
+  MidiSessionClientForTesting() = default;
+  ~MidiSessionClientForTesting() override = default;
+
+  void AddInputPort(midi::mojom::PortInfoPtr info) override {}
+  void AddOutputPort(midi::mojom::PortInfoPtr info) override {}
+  void SetInputPortState(uint32_t port, PortState state) override {}
+  void SetOutputPortState(uint32_t port, PortState state) override {}
+  void SessionStarted(midi::mojom::Result result) override {}
+  void AcknowledgeSentData(uint32_t bytes) override {}
+  void DataReceived(uint32_t port,
+                    const std::vector<uint8_t>& data,
+                    base::TimeTicks timestamp) override {}
+};
+
 class MidiHostTest : public testing::Test {
  public:
   MidiHostTest() : data_(kNoteOn, kNoteOn + base::size(kNoteOn)), port_id_(0) {
@@ -117,6 +134,8 @@
     host_ = std::make_unique<MidiHostForTesting>(rph_->GetID(), service_.get());
     midi::mojom::MidiSessionClientPtr ptr;
     midi::mojom::MidiSessionClientRequest request = mojo::MakeRequest(&ptr);
+    mojo::MakeStrongBinding(std::make_unique<MidiSessionClientForTesting>(),
+                            std::move(request));
     midi::mojom::MidiSessionRequest session_request =
         mojo::MakeRequest(&session_);
     host_->StartSession(std::move(session_request), std::move(ptr));
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 642e956..3d7e7270 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1427,9 +1427,13 @@
 
 bool RenderWidgetHostViewAura::SetEditableSelectionRange(
     const gfx::Range& range) {
-  // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
-  NOTIMPLEMENTED_LOG_ONCE();
-  return false;
+  // TODO(crbug.com/915630): Write an unit test for this method.
+  RenderFrameHostImpl* rfh = GetFocusedFrame();
+  if (!rfh)
+    return false;
+  rfh->GetFrameInputHandler()->SetEditableSelectionOffsets(range.start(),
+                                                           range.end());
+  return true;
 }
 
 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index e5bc2cc..0ca25204 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -262,9 +262,10 @@
       DispatchFetchEventCallback callback) override {
     if (!helper_)
       return;
-    helper_->OnFetchEventStub(
-        embedded_worker_id_, params->request, std::move(params->preload_handle),
-        std::move(response_callback), std::move(callback));
+    helper_->OnFetchEventStub(embedded_worker_id_, std::move(params->request),
+                              std::move(params->preload_handle),
+                              std::move(response_callback),
+                              std::move(callback));
   }
 
   void DispatchNotificationClickEvent(
@@ -633,7 +634,7 @@
 
 void EmbeddedWorkerTestHelper::OnFetchEvent(
     int /* embedded_worker_id */,
-    const network::ResourceRequest& /* request */,
+    blink::mojom::FetchAPIRequestPtr /* request */,
     blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
     blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
     mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
@@ -923,15 +924,16 @@
 
 void EmbeddedWorkerTestHelper::OnFetchEventStub(
     int embedded_worker_id,
-    const network::ResourceRequest& request,
+    blink::mojom::FetchAPIRequestPtr request,
     blink::mojom::FetchEventPreloadHandlePtr preload_handle,
     blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
     mojom::ServiceWorker::DispatchFetchEventCallback finish_callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::BindOnce(&EmbeddedWorkerTestHelper::OnFetchEvent, AsWeakPtr(),
-                     embedded_worker_id, request, std::move(preload_handle),
-                     std::move(response_callback), std::move(finish_callback)));
+                     embedded_worker_id, std::move(request),
+                     std::move(preload_handle), std::move(response_callback),
+                     std::move(finish_callback)));
 }
 
 void EmbeddedWorkerTestHelper::OnNotificationClickEventStub(
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index cd98877..00efb09 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -197,7 +197,7 @@
       mojom::ServiceWorker::DispatchInstallEventCallback callback);
   virtual void OnFetchEvent(
       int embedded_worker_id,
-      const network::ResourceRequest& request,
+      blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::FetchEventPreloadHandlePtr preload_handle,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
@@ -291,7 +291,7 @@
       mojom::ServiceWorker::DispatchInstallEventCallback callback);
   void OnFetchEventStub(
       int embedded_worker_id,
-      const network::ResourceRequest& request,
+      blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::FetchEventPreloadHandlePtr preload_handle,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback);
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 994565847..5928b82 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -935,15 +935,13 @@
     base::OnceClosure prepare_callback = CreatePrepareReceiver(prepare_result);
     ServiceWorkerFetchDispatcher::FetchCallback fetch_callback =
         CreateResponseReceiver(std::move(done), blob_context_.get(), result);
-    auto request = std::make_unique<network::ResourceRequest>();
+    auto request = blink::mojom::FetchAPIRequest::New();
     request->url = url;
     request->method = "GET";
-    request->resource_type = resource_type;
     fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
-        std::move(request), std::string() /* request_body_blob_uuid */,
-        0 /* request_body_blob_size */, nullptr /* request_body_blob */,
-        std::string() /* client_id */, version_, net::NetLogWithSource(),
-        std::move(prepare_callback), std::move(fetch_callback));
+        std::move(request), resource_type, std::string() /* client_id */,
+        version_, net::NetLogWithSource(), std::move(prepare_callback),
+        std::move(fetch_callback));
     fetch_dispatcher_->Run();
   }
 
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 609a0ff..413842d 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -409,32 +409,25 @@
 };
 
 ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
-    std::unique_ptr<network::ResourceRequest> request,
-    const std::string& request_body_blob_uuid,
-    uint64_t request_body_blob_size,
-    blink::mojom::BlobPtr request_body_blob,
+    blink::mojom::FetchAPIRequestPtr request,
+    ResourceType resource_type,
     const std::string& client_id,
     scoped_refptr<ServiceWorkerVersion> version,
     const net::NetLogWithSource& net_log,
     base::OnceClosure prepare_callback,
     FetchCallback fetch_callback)
     : request_(std::move(request)),
-      request_body_blob_uuid_(request_body_blob_uuid),
-      request_body_blob_size_(request_body_blob_size),
-      request_body_blob_(std::move(request_body_blob)),
       client_id_(client_id),
       version_(std::move(version)),
-      resource_type_(static_cast<ResourceType>(request_->resource_type)),
+      resource_type_(resource_type),
       net_log_(net_log),
       prepare_callback_(std::move(prepare_callback)),
       fetch_callback_(std::move(fetch_callback)),
       did_complete_(false),
       weak_factory_(this) {
 #if DCHECK_IS_ON()
-  if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
-    DCHECK((request_body_blob_uuid_.empty() && request_body_blob_size_ == 0 &&
-            !request_body_blob_));
-  }
+  if (blink::ServiceWorkerUtils::IsServicificationEnabled())
+    DCHECK(!request_->blob);
 #endif  // DCHECK_IS_ON()
   net_log_.BeginEvent(net::NetLogEventType::SERVICE_WORKER_DISPATCH_FETCH_EVENT,
                       net::NetLog::StringCallback(
@@ -538,10 +531,7 @@
 
   // Dispatch the fetch event.
   auto params = blink::mojom::DispatchFetchEventParams::New();
-  params->request = *request_;
-  params->request_body_blob_uuid = request_body_blob_uuid_;
-  params->request_body_blob_size = request_body_blob_size_;
-  params->request_body_blob = request_body_blob_.PassInterface();
+  params->request = std::move(request_);
   params->client_id = client_id_;
   params->preload_handle = std::move(preload_handle_);
   // |endpoint()| is owned by |version_|. So it is safe to pass the
@@ -611,7 +601,7 @@
   if (!version_->navigation_preload_state().enabled)
     return false;
   // TODO(horo): Currently NavigationPreload doesn't support request body.
-  if (request_body_blob_)
+  if (request_->blob)
     return false;
 
   ResourceRequestInfoImpl* original_info =
@@ -698,7 +688,7 @@
   if (!version_->navigation_preload_state().enabled)
     return false;
   // TODO(horo): Currently NavigationPreload doesn't support request body.
-  if (request_->request_body)
+  if (request_->body)
     return false;
 
   network::ResourceRequest resource_request(original_request);
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
index 384033a..af8c31c 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -22,7 +22,7 @@
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
-#include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
 
@@ -54,17 +54,13 @@
                               blink::mojom::ServiceWorkerFetchEventTimingPtr,
                               scoped_refptr<ServiceWorkerVersion>)>;
 
-  // |request_body_*| and |client_id| are used in non-S13nServiceWorker only.
-  ServiceWorkerFetchDispatcher(
-      std::unique_ptr<network::ResourceRequest> request,
-      const std::string& request_body_blob_uuid,
-      uint64_t request_body_blob_size,
-      blink::mojom::BlobPtr request_body_blob,
-      const std::string& client_id,
-      scoped_refptr<ServiceWorkerVersion> version,
-      const net::NetLogWithSource& net_log,
-      base::OnceClosure prepare_callback,
-      FetchCallback fetch_callback);
+  ServiceWorkerFetchDispatcher(blink::mojom::FetchAPIRequestPtr request,
+                               ResourceType resource_type,
+                               const std::string& client_id,
+                               scoped_refptr<ServiceWorkerVersion> version,
+                               const net::NetLogWithSource& net_log,
+                               base::OnceClosure prepare_callback,
+                               FetchCallback fetch_callback);
   ~ServiceWorkerFetchDispatcher();
 
   // If appropriate, starts the navigation preload request and creates
@@ -119,17 +115,10 @@
 
   ServiceWorkerMetrics::EventType GetEventType() const;
 
-  std::unique_ptr<network::ResourceRequest> request_;
-
-  // Non-S13nServiceWorker uses these. ///////////////////////////////
-  std::string request_body_blob_uuid_;
-  uint64_t request_body_blob_size_ = 0;
-  blink::mojom::BlobPtr request_body_blob_;
+  blink::mojom::FetchAPIRequestPtr request_;
   std::string client_id_;
-  ///////////////////////////////////////////////////////////////////
-
   scoped_refptr<ServiceWorkerVersion> version_;
-  ResourceType resource_type_;
+  const ResourceType resource_type_;
   net::NetLogWithSource net_log_;
   base::OnceClosure prepare_callback_;
   FetchCallback fetch_callback_;
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index 8c3c4f3..35d8749 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -13,6 +13,7 @@
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/browser/url_loader_factory_getter.h"
+#include "content/common/fetch/fetch_request_type_converters.h"
 #include "content/common/service_worker/service_worker_loader_helpers.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/browser_thread.h"
@@ -205,19 +206,13 @@
     return;
   }
 
-  // ServiceWorkerFetchDispatcher requires a std::unique_ptr<ResourceRequest>
-  // so make one here.
-  // TODO(crbug.com/803125): Try to eliminate unnecessary copying?
-  auto resource_request_to_pass =
-      std::make_unique<network::ResourceRequest>(resource_request_);
-
   // Passing the request body over Mojo moves out the DataPipeGetter elements,
   // which would mean we should clone the body like
   // ServiceWorkerSubresourceLoader does. But we don't expect DataPipeGetters
   // here yet: they are only created by the renderer when converting from a
   // Blob, which doesn't happen for navigations. In interest of speed, just
   // don't clone until proven necessary.
-  DCHECK(BodyHasNoDataPipeGetters(resource_request_to_pass->request_body.get()))
+  DCHECK(BodyHasNoDataPipeGetters(resource_request_.request_body.get()))
       << "We assumed there would be no data pipe getter elements here, but "
          "there are. Add code here to clone the body before proceeding.";
 
@@ -230,9 +225,8 @@
 
   // Dispatch the fetch event.
   fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
-      std::move(resource_request_to_pass),
-      std::string() /* request_body_blob_uuid */,
-      0 /* request_body_blob_size */, nullptr /* request_body_blob */,
+      blink::mojom::FetchAPIRequest::From(resource_request_),
+      static_cast<ResourceType>(resource_request_.resource_type),
       provider_host_->client_uuid(), active_worker,
       net::NetLogWithSource() /* TODO(scottmg): net log? */,
       base::BindOnce(&ServiceWorkerNavigationLoader::DidPrepareFetchEvent,
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index 7482fb6..3d8a2b5 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -275,22 +275,22 @@
  protected:
   void OnFetchEvent(
       int embedded_worker_id,
-      const network::ResourceRequest& request,
+      blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::FetchEventPreloadHandlePtr preload_handle,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
       override {
     // Basic checks on DispatchFetchEvent parameters.
-    EXPECT_TRUE(ServiceWorkerUtils::IsMainResourceType(
-        static_cast<ResourceType>(request.resource_type)));
+    EXPECT_TRUE(request->is_main_resource_load);
 
     has_received_fetch_event_ = true;
-    request_body_ = request.request_body;
+    if (request->body)
+      request_body_ = request->body.value();
 
     switch (response_mode_) {
       case ResponseMode::kDefault:
         EmbeddedWorkerTestHelper::OnFetchEvent(
-            embedded_worker_id, request, std::move(preload_handle),
+            embedded_worker_id, std::move(request), std::move(preload_handle),
             std::move(response_callback), std::move(finish_callback));
         break;
       case ResponseMode::kBlob:
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc
index 36b3109..4fb9c4d 100644
--- a/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -29,6 +29,7 @@
 #include "content/browser/service_worker/service_worker_data_pipe_reader.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_response_info.h"
+#include "content/common/fetch/fetch_request_type_converters.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/blob_handle.h"
@@ -542,12 +543,15 @@
   NOTREACHED();
 }
 
+// The network::ResourceRequest will be converted to
+// blink::mojom::FetchAPIRequestPtr to be passed to the renderer and be
+// converted to blink::WebServiceWorkerRequest in
+// ServiceWorkerContextClient::ToWebServiceWorkerRequestForFetchEvent. So make
+// sure the fields set here are consistent with the fields read there.
+// TODO(crbug.com/911930): Create blink::mojom::FetchAPIRequestPtr directly here
+// instead of network::ResourceRequest.
 std::unique_ptr<network::ResourceRequest>
 ServiceWorkerURLRequestJob::CreateResourceRequest() {
-  // The network::ResourceRequest will be passed to the renderer and be
-  // converted to blink::WebServiceWorkerRequest in
-  // ServiceWorkerContextClient::ToWebServiceWorkerRequest. So make sure the
-  // fields set here are consistent with the fields read there.
   auto request = std::make_unique<network::ResourceRequest>();
   request->url = request_->url();
   request->method = request_->method();
@@ -995,9 +999,20 @@
     blob = CreateRequestBodyBlob(&blob_uuid, &blob_size);
   }
 
+  auto fetch_api_request =
+      blink::mojom::FetchAPIRequest::From(*resource_request);
+  // Use |fetch_api_request->blob| to represent body for non-S13nServiceWorker
+  // case, please see dispatch_fetch_event_params.mojom for details.
+  // TODO(crbug.com/911930): Use |fetch_api_request->body| instead.
+  fetch_api_request->body.reset();
+  DCHECK(!fetch_api_request->blob);
+  if (blob) {
+    fetch_api_request->blob = blink::mojom::SerializedBlob::New(
+        blob_uuid, std::string(), blob_size, blob.PassInterface());
+  }
   DCHECK(!fetch_dispatcher_);
   fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>(
-      std::move(resource_request), blob_uuid, blob_size, std::move(blob),
+      std::move(fetch_api_request), resource_type_,
       provider_host_->client_uuid(), base::WrapRefCounted(active_worker),
       request()->net_log(),
       base::BindOnce(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 2b393b2..2156f842 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -521,7 +521,7 @@
 
   void OnFetchEvent(
       int embedded_worker_id,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr preload_handle,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
@@ -699,7 +699,7 @@
  protected:
   void OnFetchEvent(
       int /* embedded_worker_id */,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
@@ -778,7 +778,7 @@
  protected:
   void OnFetchEvent(
       int /* embedded_worker_id */,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
@@ -879,7 +879,7 @@
  protected:
   void OnFetchEvent(
       int /* embedded_worker_id */,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
@@ -1262,7 +1262,7 @@
  protected:
   void OnFetchEvent(
       int embedded_worker_id,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
       blink::mojom::
           ServiceWorkerFetchResponseCallbackPtr /* response_callback */,
@@ -1354,7 +1354,7 @@
  protected:
   void OnFetchEvent(
       int /* embedded_worker_id */,
-      const network::ResourceRequest& /* request */,
+      blink::mojom::FetchAPIRequestPtr /* request */,
       blink::mojom::FetchEventPreloadHandlePtr /* preload_handle */,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       mojom::ServiceWorker::DispatchFetchEventCallback finish_callback)
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 28a0f35..a483eae 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -103,6 +103,8 @@
     "drag_messages.h",
     "drag_traits.h",
     "edit_command.h",
+    "fetch/fetch_request_type_converters.cc",
+    "fetch/fetch_request_type_converters.h",
     "fileapi/webblob_messages.h",
     "font_cache_dispatcher_win.cc",
     "font_list.cc",
diff --git a/content/common/background_fetch/background_fetch_types.cc b/content/common/background_fetch/background_fetch_types.cc
index 4cc2e141..8357c7a 100644
--- a/content/common/background_fetch/background_fetch_types.cc
+++ b/content/common/background_fetch/background_fetch_types.cc
@@ -45,8 +45,9 @@
       request->mode, request->is_main_resource_load,
       request->request_context_type, request->frame_type, request->url,
       request->method, request->headers, CloneSerializedBlob(request->blob),
-      request->referrer.Clone(), request->credentials_mode, request->cache_mode,
-      request->redirect_mode, request->integrity, request->keepalive,
+      request->body, request->referrer.Clone(), request->credentials_mode,
+      request->cache_mode, request->redirect_mode, request->integrity,
+      request->priority, request->fetch_window_id, request->keepalive,
       request->client_id, request->is_reload, request->is_history_navigation);
 }
 }  // namespace content
diff --git a/content/common/fetch/OWNERS b/content/common/fetch/OWNERS
new file mode 100644
index 0000000..a166098
--- /dev/null
+++ b/content/common/fetch/OWNERS
@@ -0,0 +1,2 @@
+per-file *_type_converter*.*=set noparent
+per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/content/common/fetch/fetch_request_type_converters.cc b/content/common/fetch/fetch_request_type_converters.cc
new file mode 100644
index 0000000..5ec5e59
--- /dev/null
+++ b/content/common/fetch/fetch_request_type_converters.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/fetch/fetch_request_type_converters.h"
+
+#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
+
+namespace mojo {
+
+blink::mojom::FetchAPIRequestPtr TypeConverter<
+    blink::mojom::FetchAPIRequestPtr,
+    network::ResourceRequest>::Convert(const network::ResourceRequest& input) {
+  auto output = blink::mojom::FetchAPIRequest::New();
+  output->url = input.url;
+  output->method = input.method;
+  if (!input.headers.IsEmpty()) {
+    for (net::HttpRequestHeaders::Iterator it(input.headers); it.GetNext();)
+      output->headers.insert(std::make_pair(it.name(), it.value()));
+  }
+  // We put the request body data into |output->body| rather than
+  // |output->blob|. The |blob| is used in cases without
+  // network::ResourceRequest involved. See fetch_api_request.mojom.
+  // We leave |output->body| as base::nullopt when |input.request_body| is
+  // nullptr.
+  if (input.request_body)
+    output->body = input.request_body;
+  output->referrer = blink::mojom::Referrer::New(
+      input.referrer, content::Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
+                          input.referrer_policy));
+  output->mode = input.fetch_request_mode;
+  output->is_main_resource_load =
+      content::ServiceWorkerUtils::IsMainResourceType(
+          static_cast<content::ResourceType>(input.resource_type));
+  output->credentials_mode = input.fetch_credentials_mode;
+  output->cache_mode =
+      content::ServiceWorkerUtils::GetCacheModeFromLoadFlags(input.load_flags);
+  output->redirect_mode = input.fetch_redirect_mode;
+  output->request_context_type = static_cast<blink::mojom::RequestContextType>(
+      input.fetch_request_context_type);
+  output->frame_type = input.fetch_frame_type;
+  output->is_reload = ui::PageTransitionCoreTypeIs(
+      static_cast<ui::PageTransition>(input.transition_type),
+      ui::PAGE_TRANSITION_RELOAD);
+  output->integrity = input.fetch_integrity;
+  output->priority = input.priority;
+  output->fetch_window_id = input.fetch_window_id;
+  output->keepalive = input.keepalive;
+  output->is_history_navigation =
+      input.transition_type & ui::PAGE_TRANSITION_FORWARD_BACK;
+  return output;
+}
+
+}  // namespace mojo
diff --git a/content/common/fetch/fetch_request_type_converters.h b/content/common/fetch/fetch_request_type_converters.h
new file mode 100644
index 0000000..f6cf9754
--- /dev/null
+++ b/content/common/fetch/fetch_request_type_converters.h
@@ -0,0 +1,23 @@
+// Copyright 2018 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_COMMON_FETCH_FETCH_REQUEST_TYPE_CONVERTERS_H_
+#define CONTENT_COMMON_FETCH_FETCH_REQUEST_TYPE_CONVERTERS_H_
+
+#include "services/network/public/cpp/resource_request.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+
+// This is used only by Service Workers for now.
+namespace mojo {
+
+template <>
+struct TypeConverter<blink::mojom::FetchAPIRequestPtr,
+                     network::ResourceRequest> {
+  static blink::mojom::FetchAPIRequestPtr Convert(
+      const network::ResourceRequest& input);
+};
+
+}  // namespace mojo
+
+#endif  // CONTENT_COMMON_FETCH_FETCH_REQUEST_TYPE_CONVERTERS_H_
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 5158ace..0222c42 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1684,12 +1684,7 @@
   bool should_wait_flag =
       base::CommandLine::ForCurrentProcess()->HasSwitch(kWaitForDebuggerWebUI);
 
-  const std::string debugger_port =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          ::switches::kRemoteDebuggingPort);
-
-  // Only wait if there is a debugger port, so user can issue go() command.
-  if (should_wait_flag && !debugger_port.empty()) {
+  if (should_wait_flag) {
     ExecuteScriptAsync(
         web_contents,
         "window.waitUser = true; "
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 3099486..0b9c873 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -397,10 +397,10 @@
     "media/webrtc/webrtc_uma_histograms.cc",
     "media/webrtc/webrtc_uma_histograms.h",
     "media/webrtc/webrtc_util.h",
-    "media/webrtc/webrtc_video_capturer_adapter.cc",
-    "media/webrtc/webrtc_video_capturer_adapter.h",
     "media/webrtc/webrtc_video_frame_adapter.cc",
     "media/webrtc/webrtc_video_frame_adapter.h",
+    "media/webrtc/webrtc_video_track_source.cc",
+    "media/webrtc/webrtc_video_track_source.h",
     "media/webrtc/webrtc_video_utils.cc",
     "media/webrtc/webrtc_video_utils.h",
     "media/webrtc_local_audio_source_provider.cc",
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
index 886fb45..e93f565a 100644
--- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
+++ b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
@@ -20,9 +20,9 @@
 #include "content/renderer/media/stream/media_stream_constraints_util.h"
 #include "content/renderer/media/stream/media_stream_video_track.h"
 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#include "content/renderer/media/webrtc/webrtc_video_track_source.h"
 #include "media/base/limits.h"
 #include "third_party/webrtc/api/videosourceproxy.h"
-#include "third_party/webrtc/pc/videotracksource.h"
 
 namespace content {
 
@@ -34,37 +34,6 @@
 
 }  // namespace
 
-class MediaStreamVideoWebRtcSink::WebRtcVideoSource
-    : public webrtc::VideoTrackSource {
- public:
-  WebRtcVideoSource(WebRtcVideoCapturerAdapter* capture_adapter,
-                    bool is_screencast,
-                    absl::optional<bool> needs_denoising)
-      : VideoTrackSource(false),
-        capture_adapter_(capture_adapter),
-        is_screencast_(is_screencast),
-        needs_denoising_(needs_denoising) {}
-
-  WebRtcVideoCapturerAdapter* capture_adapter() const {
-    return capture_adapter_.get();
-  }
-
-  bool is_screencast() const override { return is_screencast_; }
-  absl::optional<bool> needs_denoising() const override {
-    return needs_denoising_;
-  }
-
- protected:
-  rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override {
-    return capture_adapter_.get();
-  }
-
- private:
-  std::unique_ptr<WebRtcVideoCapturerAdapter> const capture_adapter_;
-  const bool is_screencast_;
-  const absl::optional<bool> needs_denoising_;
-};
-
 namespace {
 
 // The default number of microseconds that should elapse since the last video
@@ -108,7 +77,7 @@
   WebRtcVideoSourceAdapter(
       const scoped_refptr<base::SingleThreadTaskRunner>&
           libjingle_worker_thread,
-      const scoped_refptr<WebRtcVideoSource>& source,
+      const scoped_refptr<WebRtcVideoTrackSource>& source,
       base::TimeDelta refresh_interval,
       const base::RepeatingClosure& refresh_callback,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
@@ -148,15 +117,13 @@
   // IO-thread.
   scoped_refptr<base::SingleThreadTaskRunner> libjingle_worker_thread_;
 
-  scoped_refptr<webrtc::VideoTrackSourceInterface> video_source_;
+  scoped_refptr<WebRtcVideoTrackSource> video_source_;
 
-  // Used to protect |capture_adapter_|. It is taken by libjingle's worker
+  // Used to protect |video_source_|. It is taken by libjingle's worker
   // thread for each video frame that is delivered but only taken on the
   // main render thread in ReleaseSourceOnMainThread() when
   // the owning MediaStreamVideoWebRtcSink is being destroyed.
-  base::Lock capture_adapter_stop_lock_;
-  // |capture_adapter_| is owned by |video_source_|
-  WebRtcVideoCapturerAdapter* capture_adapter_;
+  base::Lock video_source_stop_lock_;
 
   // Requests a refresh frame at regular intervals. The delay on this timer is
   // reset each time a frame is received so that it will not fire for at least
@@ -175,14 +142,13 @@
 
 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
     const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread,
-    const scoped_refptr<WebRtcVideoSource>& source,
+    const scoped_refptr<WebRtcVideoTrackSource>& source,
     base::TimeDelta refresh_interval,
     const base::RepeatingClosure& refresh_callback,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
     : render_task_runner_(std::move(task_runner)),
       libjingle_worker_thread_(libjingle_worker_thread),
-      video_source_(source),
-      capture_adapter_(source->capture_adapter()) {
+      video_source_(source) {
   DCHECK(render_task_runner_->RunsTasksInCurrentSequence());
   io_thread_checker_.DetachFromThread();
   if (!refresh_interval.is_zero()) {
@@ -195,7 +161,7 @@
 MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
     ~WebRtcVideoSourceAdapter() {
   DVLOG(3) << "~WebRtcVideoSourceAdapter()";
-  DCHECK(!capture_adapter_);
+  DCHECK(!video_source_);
   // This object can be destroyed on the main render thread or libjingles worker
   // thread since it posts video frames on that thread. But |video_source_| must
   // be released on the main render thread before the PeerConnectionFactory has
@@ -216,9 +182,7 @@
   // Since frames are posted to the worker thread, this object might be deleted
   // on that thread. However, since |video_source_| was created on the render
   // thread, it should be released on the render thread.
-  base::AutoLock auto_lock(capture_adapter_stop_lock_);
-  // |video_source| owns |capture_adapter_|.
-  capture_adapter_ = nullptr;
+  base::AutoLock auto_lock(video_source_stop_lock_);
   video_source_ = nullptr;
 }
 
@@ -239,9 +203,9 @@
 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
     OnVideoFrameOnWorkerThread(const scoped_refptr<media::VideoFrame>& frame) {
   DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
-  base::AutoLock auto_lock(capture_adapter_stop_lock_);
-  if (capture_adapter_)
-    capture_adapter_->OnFrameCaptured(frame);
+  base::AutoLock auto_lock(video_source_stop_lock_);
+  if (video_source_)
+    video_source_->OnFrameCaptured(frame);
 }
 
 MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
@@ -289,10 +253,9 @@
 
   // TODO(pbos): Consolidate WebRtcVideoCapturerAdapter into WebRtcVideoSource
   // by removing the need for and dependency on a cricket::VideoCapturer.
-  video_source_ = scoped_refptr<WebRtcVideoSource>(
-      new rtc::RefCountedObject<WebRtcVideoSource>(
-          new WebRtcVideoCapturerAdapter(is_screencast), is_screencast,
-          needs_denoising));
+  video_source_ = scoped_refptr<WebRtcVideoTrackSource>(
+      new rtc::RefCountedObject<WebRtcVideoTrackSource>(is_screencast,
+                                                        needs_denoising));
 
   // TODO(pbos): Consolidate the local video track with the source proxy and
   // move into PeerConnectionDependencyFactory. This now separately holds on a
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
index d803928..4c0161f 100644
--- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
+++ b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
@@ -9,7 +9,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "content/public/renderer/media_stream_video_sink.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/webrtc/api/mediastreaminterface.h"
 
@@ -21,6 +20,7 @@
 
 class MediaStreamVideoTrack;
 class PeerConnectionDependencyFactory;
+class WebRtcVideoTrackSource;
 
 // MediaStreamVideoWebRtcSink is an adapter between a
 // content::MediaStreamVideoTrack object and a webrtc VideoTrack that is
@@ -59,11 +59,10 @@
   // Used to DCHECK that we are called on the correct thread.
   base::ThreadChecker thread_checker_;
 
-  // |video_source_| and |video_track_source_proxy_| are held as references to
-  // outlive |video_track_| since the interfaces between them don't use
-  // reference counting.
-  class WebRtcVideoSource;
-  scoped_refptr<WebRtcVideoSource> video_source_;
+  // |video_source_| and |video_source_proxy_| are held as
+  // references to outlive |video_track_| since the interfaces between them
+  // don't use reference counting.
+  scoped_refptr<WebRtcVideoTrackSource> video_source_;
   scoped_refptr<webrtc::VideoTrackSourceInterface> video_source_proxy_;
   scoped_refptr<webrtc::VideoTrackInterface> video_track_;
 
diff --git a/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
index 2a48dee4..c2994a5 100644
--- a/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_impl.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/webrtc/api/mediastreaminterface.h"
 #include "third_party/webrtc/rtc_base/scoped_ref_ptr.h"
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index f8a8e5bd..56cc00ac 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -38,7 +38,6 @@
 #include "content/renderer/media/webrtc/video_codec_factory.h"
 #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h"
 #include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 #include "content/renderer/media/webrtc_logging.h"
 #include "content/renderer/p2p/empty_network_manager.h"
 #include "content/renderer/p2p/filtering_network_manager.h"
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
deleted file mode 100644
index 546b26d..0000000
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/paint/skia_paint_canvas.h"
-#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
-#include "media/base/timestamp_constants.h"
-#include "media/base/video_util.h"
-#include "third_party/libyuv/include/libyuv/convert_from.h"
-#include "third_party/libyuv/include/libyuv/scale.h"
-#include "third_party/webrtc/api/video/video_rotation.h"
-#include "third_party/webrtc/rtc_base/refcountedobject.h"
-
-namespace content {
-
-namespace {
-
-// Empty method used for keeping a reference to the original media::VideoFrame.
-// The reference to |frame| is kept in the closure that calls this method.
-void CapturerReleaseOriginalFrame(
-    const scoped_refptr<media::VideoFrame>& frame) {}
-
-}  // anonymous namespace
-
-WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast)
-    : is_screencast_(is_screencast), running_(false) {
-  thread_checker_.DetachFromThread();
-}
-
-WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() {
-  DVLOG(3) << __func__;
-}
-
-void WebRtcVideoCapturerAdapter::OnFrameCaptured(
-    const scoped_refptr<media::VideoFrame>& input_frame) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  TRACE_EVENT0("media", "WebRtcVideoCapturerAdapter::OnFrameCaptured");
-  if (!(input_frame->IsMappable() &&
-        (input_frame->format() == media::PIXEL_FORMAT_I420 ||
-         input_frame->format() == media::PIXEL_FORMAT_I420A)) &&
-      !input_frame->HasTextures()) {
-    // Since connecting sources and sinks do not check the format, we need to
-    // just ignore formats that we can not handle.
-    LOG(ERROR) << "We cannot send frame with storage type: "
-               << input_frame->AsHumanReadableString();
-    NOTREACHED();
-    return;
-  }
-  scoped_refptr<media::VideoFrame> frame = input_frame;
-  const int orig_width = frame->natural_size().width();
-  const int orig_height = frame->natural_size().height();
-  int adapted_width;
-  int adapted_height;
-  // The VideoAdapter is only used for cpu-adaptation downscaling, no
-  // aspect changes. So we ignore these crop-related outputs.
-  int crop_width;
-  int crop_height;
-  int crop_x;
-  int crop_y;
-  int64_t translated_camera_time_us;
-
-  if (!AdaptFrame(orig_width, orig_height,
-                  frame->timestamp().InMicroseconds(),
-                  rtc::TimeMicros(),
-                  &adapted_width, &adapted_height,
-                  &crop_width, &crop_height, &crop_x, &crop_y,
-                  &translated_camera_time_us)) {
-    return;
-  }
-
-  // Return |frame| directly if it is texture backed, because there is no
-  // cropping support for texture yet. See http://crbug/503653.
-  if (frame->HasTextures()) {
-    OnFrame(webrtc::VideoFrame(
-                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame),
-                webrtc::kVideoRotation_0, translated_camera_time_us),
-            orig_width, orig_height);
-    return;
-  }
-
-  // Translate crop rectangle from natural size to visible size.
-  gfx::Rect cropped_visible_rect(
-      frame->visible_rect().x() +
-          crop_x * frame->visible_rect().width() / orig_width,
-      frame->visible_rect().y() +
-          crop_y * frame->visible_rect().height() / orig_height,
-      crop_width * frame->visible_rect().width() / orig_width,
-      crop_height * frame->visible_rect().height() / orig_height);
-
-  const gfx::Size adapted_size(adapted_width, adapted_height);
-  scoped_refptr<media::VideoFrame> video_frame =
-      media::VideoFrame::WrapVideoFrame(frame, frame->format(),
-                                        cropped_visible_rect, adapted_size);
-  if (!video_frame)
-    return;
-
-  video_frame->AddDestructionObserver(
-      base::BindOnce(&CapturerReleaseOriginalFrame, frame));
-
-  // If no scaling is needed, return a wrapped version of |frame| directly.
-  if (video_frame->natural_size() == video_frame->visible_rect().size()) {
-    OnFrame(webrtc::VideoFrame(
-                new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(video_frame),
-                webrtc::kVideoRotation_0, translated_camera_time_us),
-            orig_width, orig_height);
-    return;
-  }
-
-  // We need to scale the frame before we hand it over to webrtc.
-  const bool has_alpha = video_frame->format() == media::PIXEL_FORMAT_I420A;
-  scoped_refptr<media::VideoFrame> scaled_frame =
-      scaled_frame_pool_.CreateFrame(
-          has_alpha ? media::PIXEL_FORMAT_I420A : media::PIXEL_FORMAT_I420,
-          adapted_size, gfx::Rect(adapted_size), adapted_size,
-          frame->timestamp());
-  libyuv::I420Scale(video_frame->visible_data(media::VideoFrame::kYPlane),
-                    video_frame->stride(media::VideoFrame::kYPlane),
-                    video_frame->visible_data(media::VideoFrame::kUPlane),
-                    video_frame->stride(media::VideoFrame::kUPlane),
-                    video_frame->visible_data(media::VideoFrame::kVPlane),
-                    video_frame->stride(media::VideoFrame::kVPlane),
-                    video_frame->visible_rect().width(),
-                    video_frame->visible_rect().height(),
-                    scaled_frame->data(media::VideoFrame::kYPlane),
-                    scaled_frame->stride(media::VideoFrame::kYPlane),
-                    scaled_frame->data(media::VideoFrame::kUPlane),
-                    scaled_frame->stride(media::VideoFrame::kUPlane),
-                    scaled_frame->data(media::VideoFrame::kVPlane),
-                    scaled_frame->stride(media::VideoFrame::kVPlane),
-                    adapted_width, adapted_height, libyuv::kFilterBilinear);
-  if (has_alpha) {
-    libyuv::ScalePlane(video_frame->visible_data(media::VideoFrame::kAPlane),
-                       video_frame->stride(media::VideoFrame::kAPlane),
-                       video_frame->visible_rect().width(),
-                       video_frame->visible_rect().height(),
-                       scaled_frame->data(media::VideoFrame::kAPlane),
-                       scaled_frame->stride(media::VideoFrame::kAPlane),
-                       adapted_width, adapted_height, libyuv::kFilterBilinear);
-  }
-
-  OnFrame(webrtc::VideoFrame(
-              new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(scaled_frame),
-              webrtc::kVideoRotation_0, translated_camera_time_us),
-          orig_width, orig_height);
-}
-
-cricket::CaptureState WebRtcVideoCapturerAdapter::Start(
-    const cricket::VideoFormat& capture_format) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!running_);
-  DVLOG(3) << __func__ << " capture format: " << capture_format.ToString();
-
-  running_ = true;
-  return cricket::CS_RUNNING;
-}
-
-void WebRtcVideoCapturerAdapter::Stop() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(3) << __func__;
-  DCHECK(running_);
-  running_ = false;
-  SetCaptureFormat(nullptr);
-  SignalStateChange(this, cricket::CS_STOPPED);
-}
-
-bool WebRtcVideoCapturerAdapter::IsRunning() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return running_;
-}
-
-bool WebRtcVideoCapturerAdapter::GetPreferredFourccs(
-    std::vector<uint32_t>* fourccs) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!fourccs)
-    return false;
-  DCHECK(fourccs->empty());
-  fourccs->push_back(cricket::FOURCC_I420);
-  return true;
-}
-
-bool WebRtcVideoCapturerAdapter::IsScreencast() const {
-  return is_screencast_;
-}
-
-bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat(
-    const cricket::VideoFormat& desired,
-    cricket::VideoFormat* best_format) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DVLOG(3) << __func__ << " desired: " << desired.ToString();
-
-  // Capability enumeration is done in MediaStreamVideoSource. The adapter can
-  // just use what is provided.
-  // Use the desired format as the best format.
-  best_format->width = desired.width;
-  best_format->height = desired.height;
-  best_format->fourcc = cricket::FOURCC_I420;
-  best_format->interval = desired.interval;
-  return true;
-}
-
-}  // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
deleted file mode 100644
index 2b72f681..0000000
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_CAPTURER_ADAPTER_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_CAPTURER_ADAPTER_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "media/base/video_frame.h"
-#include "media/base/video_frame_pool.h"
-#include "media/capture/video_capture_types.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/webrtc/media/base/videocapturer.h"
-
-namespace content {
-
-// WebRtcVideoCapturerAdapter implements a simple cricket::VideoCapturer that is
-// used for VideoCapturing in libJingle and especially in PeerConnections.
-// The class is created and destroyed on the main render thread.
-// PeerConnection access cricket::VideoCapturer from a libJingle worker thread.
-// An instance of WebRtcVideoCapturerAdapter is owned by an instance of
-// webrtc::VideoTrackSourceInterface in libJingle. The implementation of
-// webrtc::VideoTrackSourceInterface guarantees that this object is not deleted
-// while it is still used in libJingle.
-class CONTENT_EXPORT WebRtcVideoCapturerAdapter
-    : public cricket::VideoCapturer {
- public:
-  WebRtcVideoCapturerAdapter(bool is_screencast);
-  ~WebRtcVideoCapturerAdapter() override;
-
-  // OnFrameCaptured delivers video frames to libjingle. It must be called on
-  // libjingles worker thread.
-  // This method is virtual for testing purposes.
-  virtual void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
-
- private:
-  // cricket::VideoCapturer implementation.
-  // These methods are accessed from a libJingle worker thread.
-  cricket::CaptureState Start(
-      const cricket::VideoFormat& capture_format) override;
-  void Stop() override;
-  bool IsRunning() override;
-  bool GetPreferredFourccs(std::vector<uint32_t>* fourccs) override;
-  bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
-                            cricket::VideoFormat* best_format) override;
-  bool IsScreencast() const override;
-
-  // |thread_checker_| is bound to the libjingle worker thread.
-  base::ThreadChecker thread_checker_;
-
-  const bool is_screencast_;
-  bool running_;
-
-  media::VideoFramePool scaled_frame_pool_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCapturerAdapter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_CAPTURER_ADAPTER_H_
diff --git a/content/renderer/media/webrtc/webrtc_video_track_source.cc b/content/renderer/media/webrtc/webrtc_video_track_source.cc
new file mode 100644
index 0000000..46ea7b5
--- /dev/null
+++ b/content/renderer/media/webrtc/webrtc_video_track_source.cc
@@ -0,0 +1,151 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc/webrtc_video_track_source.h"
+
+#include "base/trace_event/trace_event.h"
+#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
+#include "third_party/libyuv/include/libyuv/scale.h"
+#include "third_party/webrtc/rtc_base/refcountedobject.h"
+
+namespace content {
+
+WebRtcVideoTrackSource::WebRtcVideoTrackSource(
+    bool is_screencast,
+    absl::optional<bool> needs_denoising)
+    : AdaptedVideoTrackSource(/*required_alignment=*/1),
+      is_screencast_(is_screencast),
+      needs_denoising_(needs_denoising) {
+  DETACH_FROM_THREAD(thread_checker_);
+}
+
+WebRtcVideoTrackSource::~WebRtcVideoTrackSource() = default;
+
+WebRtcVideoTrackSource::SourceState WebRtcVideoTrackSource::state() const {
+  // TODO(nisse): What's supposed to change this state?
+  return MediaSourceInterface::SourceState::kLive;
+}
+
+bool WebRtcVideoTrackSource::remote() const {
+  return false;
+}
+
+bool WebRtcVideoTrackSource::is_screencast() const {
+  return is_screencast_;
+}
+
+absl::optional<bool> WebRtcVideoTrackSource::needs_denoising() const {
+  return needs_denoising_;
+}
+
+void WebRtcVideoTrackSource::OnFrameCaptured(
+    const scoped_refptr<media::VideoFrame>& frame) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  TRACE_EVENT0("media", "WebRtcVideoSource::OnFrameCaptured");
+  if (!(frame->IsMappable() &&
+        (frame->format() == media::PIXEL_FORMAT_I420 ||
+         frame->format() == media::PIXEL_FORMAT_I420A)) &&
+      !frame->HasTextures()) {
+    // Since connecting sources and sinks do not check the format, we need to
+    // just ignore formats that we can not handle.
+    LOG(ERROR) << "We cannot send frame with storage type: "
+               << frame->AsHumanReadableString();
+    NOTREACHED();
+    return;
+  }
+
+  const int orig_width = frame->natural_size().width();
+  const int orig_height = frame->natural_size().height();
+  const int64_t now_us = rtc::TimeMicros();
+  int adapted_width;
+  int adapted_height;
+  int crop_width;
+  int crop_height;
+  int crop_x;
+  int crop_y;
+
+  if (!AdaptFrame(orig_width, orig_height, now_us, &adapted_width,
+                  &adapted_height, &crop_width, &crop_height, &crop_x,
+                  &crop_y)) {
+    return;
+  }
+
+  const int64_t translated_camera_time_us =
+      timestamp_aligner_.TranslateTimestamp(frame->timestamp().InMicroseconds(),
+                                            now_us);
+
+  // Return |frame| directly if it is texture backed, because there is no
+  // cropping support for texture yet. See http://crbug/503653.
+  if (frame->HasTextures()) {
+    OnFrame(webrtc::VideoFrame(
+        new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame),
+        webrtc::kVideoRotation_0, translated_camera_time_us));
+    return;
+  }
+
+  // Translate crop rectangle from natural size to visible size.
+  gfx::Rect cropped_visible_rect(
+      frame->visible_rect().x() +
+          crop_x * frame->visible_rect().width() / orig_width,
+      frame->visible_rect().y() +
+          crop_y * frame->visible_rect().height() / orig_height,
+      crop_width * frame->visible_rect().width() / orig_width,
+      crop_height * frame->visible_rect().height() / orig_height);
+
+  const gfx::Size adapted_size(adapted_width, adapted_height);
+  scoped_refptr<media::VideoFrame> video_frame =
+      media::VideoFrame::WrapVideoFrame(frame, frame->format(),
+                                        cropped_visible_rect, adapted_size);
+  if (!video_frame)
+    return;
+
+  video_frame->AddDestructionObserver(base::BindOnce(
+      base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(), frame));
+
+  // If no scaling is needed, return a wrapped version of |frame| directly.
+  if (video_frame->natural_size() == video_frame->visible_rect().size()) {
+    OnFrame(webrtc::VideoFrame(
+        new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(video_frame),
+        webrtc::kVideoRotation_0, translated_camera_time_us));
+    return;
+  }
+
+  // We need to scale the frame before we hand it over to webrtc.
+  const bool has_alpha = video_frame->format() == media::PIXEL_FORMAT_I420A;
+  scoped_refptr<media::VideoFrame> scaled_frame =
+      scaled_frame_pool_.CreateFrame(
+          has_alpha ? media::PIXEL_FORMAT_I420A : media::PIXEL_FORMAT_I420,
+          adapted_size, gfx::Rect(adapted_size), adapted_size,
+          frame->timestamp());
+  libyuv::I420Scale(video_frame->visible_data(media::VideoFrame::kYPlane),
+                    video_frame->stride(media::VideoFrame::kYPlane),
+                    video_frame->visible_data(media::VideoFrame::kUPlane),
+                    video_frame->stride(media::VideoFrame::kUPlane),
+                    video_frame->visible_data(media::VideoFrame::kVPlane),
+                    video_frame->stride(media::VideoFrame::kVPlane),
+                    video_frame->visible_rect().width(),
+                    video_frame->visible_rect().height(),
+                    scaled_frame->data(media::VideoFrame::kYPlane),
+                    scaled_frame->stride(media::VideoFrame::kYPlane),
+                    scaled_frame->data(media::VideoFrame::kUPlane),
+                    scaled_frame->stride(media::VideoFrame::kUPlane),
+                    scaled_frame->data(media::VideoFrame::kVPlane),
+                    scaled_frame->stride(media::VideoFrame::kVPlane),
+                    adapted_width, adapted_height, libyuv::kFilterBilinear);
+  if (has_alpha) {
+    libyuv::ScalePlane(video_frame->visible_data(media::VideoFrame::kAPlane),
+                       video_frame->stride(media::VideoFrame::kAPlane),
+                       video_frame->visible_rect().width(),
+                       video_frame->visible_rect().height(),
+                       scaled_frame->data(media::VideoFrame::kAPlane),
+                       scaled_frame->stride(media::VideoFrame::kAPlane),
+                       adapted_width, adapted_height, libyuv::kFilterBilinear);
+  }
+
+  OnFrame(webrtc::VideoFrame(
+      new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(scaled_frame),
+      webrtc::kVideoRotation_0, translated_camera_time_us));
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc/webrtc_video_track_source.h b/content/renderer/media/webrtc/webrtc_video_track_source.h
new file mode 100644
index 0000000..90417ba9
--- /dev/null
+++ b/content/renderer/media/webrtc/webrtc_video_track_source.h
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_TRACK_SOURCE_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_TRACK_SOURCE_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "media/base/video_frame_pool.h"
+#include "third_party/webrtc/media/base/adaptedvideotracksource.h"
+#include "third_party/webrtc/rtc_base/timestampaligner.h"
+
+namespace content {
+
+class CONTENT_EXPORT WebRtcVideoTrackSource
+    : public rtc::AdaptedVideoTrackSource {
+ public:
+  WebRtcVideoTrackSource(bool is_screencast,
+                         absl::optional<bool> needs_denoising);
+  ~WebRtcVideoTrackSource() override;
+
+  SourceState state() const override;
+
+  bool remote() const override;
+  bool is_screencast() const override;
+  absl::optional<bool> needs_denoising() const override;
+  void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
+
+  using webrtc::VideoTrackSourceInterface::AddOrUpdateSink;
+  using webrtc::VideoTrackSourceInterface::RemoveSink;
+
+ private:
+  // |thread_checker_| is bound to the libjingle worker thread.
+  THREAD_CHECKER(thread_checker_);
+  media::VideoFramePool scaled_frame_pool_;
+  // State for the timestamp translation.
+  rtc::TimestampAligner timestamp_aligner_;
+
+  const bool is_screencast_;
+  const absl::optional<bool> needs_denoising_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcVideoTrackSource);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_TRACK_SOURCE_H_
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_video_track_source_unittest.cc
similarity index 72%
rename from content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
rename to content/renderer/media/webrtc/webrtc_video_track_source_unittest.cc
index 996ba07..e62c137 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_video_track_source_unittest.cc
@@ -6,24 +6,27 @@
 
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
+#include "content/renderer/media/webrtc/webrtc_video_track_source.h"
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/rtc_base/refcountedobject.h"
 
 namespace content {
 
-class WebRtcVideoCapturerAdapterTest
+class WebRtcVideoTrackSourceTest
     : public rtc::VideoSinkInterface<webrtc::VideoFrame>,
       public ::testing::Test {
  public:
-  WebRtcVideoCapturerAdapterTest()
-      : adapter_(new WebRtcVideoCapturerAdapter(false)),
+  WebRtcVideoTrackSourceTest()
+      : track_source_(new rtc::RefCountedObject<WebRtcVideoTrackSource>(
+            /*is_screencast=*/false,
+            /*needs_denoising=*/absl::nullopt)),
         output_frame_width_(0),
         output_frame_height_(0) {
-    adapter_->AddOrUpdateSink(this, rtc::VideoSinkWants());
+    track_source_->AddOrUpdateSink(this, rtc::VideoSinkWants());
   }
-  ~WebRtcVideoCapturerAdapterTest() override { adapter_->RemoveSink(this); }
+  ~WebRtcVideoTrackSourceTest() override { track_source_->RemoveSink(this); }
 
   void TestSourceCropFrame(int capture_width,
                            int capture_height,
@@ -40,7 +43,7 @@
     scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame(
         media::PIXEL_FORMAT_I420, coded_size, view_rect, natural_size,
         base::TimeDelta());
-    adapter_->OnFrameCaptured(frame);
+    track_source_->OnFrameCaptured(frame);
     EXPECT_EQ(natural_width, output_frame_width_);
     EXPECT_EQ(natural_height, output_frame_height_);
   }
@@ -52,20 +55,20 @@
   }
 
  private:
-  std::unique_ptr<WebRtcVideoCapturerAdapter> adapter_;
+  scoped_refptr<WebRtcVideoTrackSource> track_source_;
   int output_frame_width_;
   int output_frame_height_;
 };
 
-TEST_F(WebRtcVideoCapturerAdapterTest, CropFrameTo640360) {
+TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo640360) {
   TestSourceCropFrame(640, 480, 640, 360, 640, 360);
 }
 
-TEST_F(WebRtcVideoCapturerAdapterTest, CropFrameTo320320) {
+TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo320320) {
   TestSourceCropFrame(640, 480, 480, 480, 320, 320);
 }
 
-TEST_F(WebRtcVideoCapturerAdapterTest, Scale720To640360) {
+TEST_F(WebRtcVideoTrackSourceTest, Scale720To640360) {
   TestSourceCropFrame(1280, 720, 1280, 720, 640, 360);
 }
 
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 23039ca..23f4ddd 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -179,11 +179,6 @@
   std::unique_ptr<ServiceWorkerTimeoutTimer::StayAwakeToken> token_;
 };
 
-blink::mojom::RequestContextType GetBlinkRequestContext(
-    blink::mojom::RequestContextType request_context_type) {
-  return static_cast<blink::mojom::RequestContextType>(request_context_type);
-}
-
 blink::WebServiceWorkerClientInfo ToWebServiceWorkerClientInfo(
     blink::mojom::ServiceWorkerClientInfoPtr client_info) {
   DCHECK(!client_info->client_uuid.empty());
@@ -237,73 +232,64 @@
 }
 
 void ToWebServiceWorkerRequestForFetchEvent(
-    const network::ResourceRequest& request,
-    const std::string request_body_blob_uuid,
-    uint64_t request_body_blob_size,
-    blink::mojom::BlobPtrInfo request_body_blob,
-    const std::string& client_id,
+    blink::mojom::FetchAPIRequestPtr request,
     std::vector<blink::mojom::BlobPtrInfo> blob_ptrs,
+    const std::string& client_id,
     blink::WebServiceWorkerRequest* web_request) {
   DCHECK(web_request);
-  web_request->SetURL(blink::WebURL(request.url));
-  web_request->SetMethod(blink::WebString::FromUTF8(request.method));
-  if (!request.headers.IsEmpty()) {
-    for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();) {
-      if (!GetContentClient()
-               ->renderer()
-               ->IsExcludedHeaderForServiceWorkerFetchEvent(it.name())) {
-        web_request->SetHeader(blink::WebString::FromUTF8(it.name()),
-                               blink::WebString::FromUTF8(it.value()));
-      }
+  web_request->SetURL(blink::WebURL(request->url));
+  web_request->SetMethod(blink::WebString::FromUTF8(request->method));
+  for (const auto& pair : request->headers) {
+    if (!GetContentClient()
+             ->renderer()
+             ->IsExcludedHeaderForServiceWorkerFetchEvent(pair.first)) {
+      web_request->SetHeader(blink::WebString::FromUTF8(pair.first),
+                             blink::WebString::FromUTF8(pair.second));
     }
   }
 
   // Non-S13nServiceWorker: The body is provided as a blob.
-  if (request_body_blob) {
+  if (request->blob) {
     DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-    mojo::ScopedMessagePipeHandle blob_pipe = request_body_blob.PassHandle();
-    web_request->SetBlob(blink::WebString::FromASCII(request_body_blob_uuid),
-                         request_body_blob_size, std::move(blob_pipe));
+    web_request->SetBlob(blink::WebString::FromASCII(request->blob->uuid),
+                         request->blob->size, request->blob->blob.PassHandle());
   }
-  // S13nServiceWorker: The body is provided in |request|.
-  else if (request.request_body) {
+  // S13nServiceWorker: The body is provided in |request->body|.
+  else if (request->body.has_value()) {
+    DCHECK(request->body.value());
     DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
     // |blob_ptrs| should be empty when Network Service is enabled.
     DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
            blob_ptrs.empty());
     blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
-        *request.request_body, std::move(blob_ptrs));
+        *(request->body.value()), std::move(blob_ptrs));
     body.SetUniqueBoundary();
     web_request->SetBody(body);
   }
 
-  web_request->SetReferrer(blink::WebString::FromUTF8(request.referrer.spec()),
-                           Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
-                               request.referrer_policy));
-  web_request->SetMode(request.fetch_request_mode);
-  web_request->SetIsMainResourceLoad(ServiceWorkerUtils::IsMainResourceType(
-      static_cast<ResourceType>(request.resource_type)));
-  web_request->SetCredentialsMode(request.fetch_credentials_mode);
-  web_request->SetCacheMode(
-      ServiceWorkerUtils::GetCacheModeFromLoadFlags(request.load_flags));
-  web_request->SetRedirectMode(request.fetch_redirect_mode);
-  web_request->SetRequestContext(
-      GetBlinkRequestContext(static_cast<blink::mojom::RequestContextType>(
-          request.fetch_request_context_type)));
-  web_request->SetFrameType(request.fetch_frame_type);
+  if (request->referrer) {
+    web_request->SetReferrer(
+        blink::WebString::FromUTF8(request->referrer->url.spec()),
+        request->referrer->policy);
+  }
+  web_request->SetMode(request->mode);
+  web_request->SetIsMainResourceLoad(request->is_main_resource_load);
+  web_request->SetCredentialsMode(request->credentials_mode);
+  web_request->SetCacheMode(request->cache_mode);
+  web_request->SetRedirectMode(request->redirect_mode);
+  web_request->SetRequestContext(request->request_context_type);
+  web_request->SetFrameType(request->frame_type);
   web_request->SetClientId(blink::WebString::FromUTF8(client_id));
-  web_request->SetIsReload(ui::PageTransitionCoreTypeIs(
-      static_cast<ui::PageTransition>(request.transition_type),
-      ui::PAGE_TRANSITION_RELOAD));
-  web_request->SetIntegrity(
-      blink::WebString::FromUTF8(request.fetch_integrity));
+  web_request->SetIsReload(request->is_reload);
+  if (request->integrity) {
+    web_request->SetIntegrity(blink::WebString::FromUTF8(*request->integrity));
+  }
   web_request->SetPriority(
-      ConvertNetPriorityToWebKitPriority(request.priority));
-  web_request->SetKeepalive(request.keepalive);
-  web_request->SetIsHistoryNavigation(request.transition_type &
-                                      ui::PAGE_TRANSITION_FORWARD_BACK);
-  if (request.fetch_window_id)
-    web_request->SetWindowId(*request.fetch_window_id);
+      ConvertNetPriorityToWebKitPriority(request->priority));
+  web_request->SetKeepalive(request->keepalive);
+  web_request->SetIsHistoryNavigation(request->is_history_navigation);
+  if (request->fetch_window_id)
+    web_request->SetWindowId(*request->fetch_window_id);
 }
 
 // Finds an event callback keyed by |event_id| from |map|, and runs the callback
@@ -1283,7 +1269,7 @@
     DispatchFetchEventCallback callback) {
   TRACE_EVENT2("ServiceWorker",
                "ServiceWorkerContextClient::DispatchOrQueueFetchEvent", "url",
-               params->request.url.spec(), "queued",
+               params->request->url.spec(), "queued",
                RequestedTermination() ? "true" : "false");
   if (RequestedTermination()) {
     context_->timeout_timer->PushPendingTask(base::BindOnce(
@@ -1606,22 +1592,20 @@
       "ServiceWorker", "ServiceWorkerContextClient::DispatchFetchEvent",
       TRACE_ID_WITH_SCOPE(kServiceWorkerContextClientScope,
                           TRACE_ID_LOCAL(event_id)),
-      TRACE_EVENT_FLAG_FLOW_OUT, "url", params->request.url.spec());
+      TRACE_EVENT_FLAG_FLOW_OUT, "url", params->request->url.spec());
 
   // Set up for navigation preload (FetchEvent#preloadResponse) if needed.
   const bool navigation_preload_sent = !!params->preload_handle;
   if (navigation_preload_sent) {
-    SetupNavigationPreload(event_id, params->request.url,
+    SetupNavigationPreload(event_id, params->request->url,
                            std::move(params->preload_handle));
   }
 
   // Dispatch the event to the service worker execution context.
   blink::WebServiceWorkerRequest web_request;
   ToWebServiceWorkerRequestForFetchEvent(
-      std::move(params->request), params->request_body_blob_uuid,
-      params->request_body_blob_size, std::move(params->request_body_blob),
-      params->client_id, std::move(params->request_body_blob_ptrs),
-      &web_request);
+      std::move(params->request), std::move(params->request_body_blob_ptrs),
+      params->client_id, &web_request);
   proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent);
 }
 
diff --git a/content/renderer/service_worker/service_worker_context_client_unittest.cc b/content/renderer/service_worker/service_worker_context_client_unittest.cc
index 02b25bc..b416c78 100644
--- a/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ b/content/renderer/service_worker/service_worker_context_client_unittest.cc
@@ -338,13 +338,13 @@
   EXPECT_TRUE(mock_proxy.fetch_events().empty());
 
   const GURL expected_url("https://example.com/expected");
-  auto request = std::make_unique<network::ResourceRequest>();
+  auto request = blink::mojom::FetchAPIRequest::New();
   request->url = expected_url;
   blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
   blink::mojom::ServiceWorkerFetchResponseCallbackRequest
       fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
   auto params = blink::mojom::DispatchFetchEventParams::New();
-  params->request = *request;
+  params->request = std::move(request);
   pipes.service_worker->DispatchFetchEvent(
       std::move(params), std::move(fetch_callback_ptr),
       base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
@@ -375,15 +375,15 @@
   EXPECT_TRUE(mock_proxy.fetch_events().empty());
 
   const GURL expected_url("https://example.com/expected");
-  auto request = std::make_unique<network::ResourceRequest>();
+  auto request = blink::mojom::FetchAPIRequest::New();
   request->url = expected_url;
-  request->headers.SetHeader("x-bye-bye", "excluded");
-  request->headers.SetHeader("x-hi-hi", "present");
+  request->headers.emplace("x-bye-bye", "excluded");
+  request->headers.emplace("x-hi-hi", "present");
   blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
   blink::mojom::ServiceWorkerFetchResponseCallbackRequest
       fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
   auto params = blink::mojom::DispatchFetchEventParams::New();
-  params->request = *request;
+  params->request = std::move(request);
   pipes.service_worker->DispatchFetchEvent(
       std::move(params), std::move(fetch_callback_ptr),
       base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
@@ -426,10 +426,10 @@
   blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
   blink::mojom::ServiceWorkerFetchResponseCallbackRequest
       fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
-  auto request = std::make_unique<network::ResourceRequest>();
+  auto request = blink::mojom::FetchAPIRequest::New();
   request->url = expected_url;
   auto params = blink::mojom::DispatchFetchEventParams::New();
-  params->request = *request;
+  params->request = std::move(request);
   context_client->DispatchOrQueueFetchEvent(
       std::move(params), std::move(fetch_callback_ptr),
       base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
@@ -473,10 +473,10 @@
     blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
     blink::mojom::ServiceWorkerFetchResponseCallbackRequest
         fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr);
-    auto request = std::make_unique<network::ResourceRequest>();
+    auto request = blink::mojom::FetchAPIRequest::New();
     request->url = expected_url;
     auto params = blink::mojom::DispatchFetchEventParams::New();
-    params->request = *request;
+    params->request = std::move(request);
     pipes.controller->DispatchFetchEvent(
         std::move(params), std::move(fetch_callback_ptr),
         base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
@@ -523,10 +523,10 @@
   {
     blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
     fetch_callback_request_1 = mojo::MakeRequest(&fetch_callback_ptr);
-    auto request = std::make_unique<network::ResourceRequest>();
+    auto request = blink::mojom::FetchAPIRequest::New();
     request->url = expected_url_1;
     auto params = blink::mojom::DispatchFetchEventParams::New();
-    params->request = *request;
+    params->request = std::move(request);
     pipes.controller->DispatchFetchEvent(
         std::move(params), std::move(fetch_callback_ptr),
         base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
@@ -539,10 +539,10 @@
   {
     blink::mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr;
     fetch_callback_request_2 = mojo::MakeRequest(&fetch_callback_ptr);
-    auto request = std::make_unique<network::ResourceRequest>();
+    auto request = blink::mojom::FetchAPIRequest::New();
     request->url = expected_url_2;
     auto params = blink::mojom::DispatchFetchEventParams::New();
-    params->request = *request;
+    params->request = std::move(request);
     pipes.service_worker->DispatchFetchEvent(
         std::move(params), std::move(fetch_callback_ptr),
         base::BindOnce([](blink::mojom::ServiceWorkerEventStatus) {}));
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index b3e9f40..f57bdbb 100644
--- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -185,7 +185,7 @@
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       DispatchFetchEventCallback callback) override {
     fetch_event_count_++;
-    fetch_event_request_ = params->request;
+    fetch_event_request_ = std::move(params->request);
     std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED);
     if (fetch_event_callback_)
       std::move(fetch_event_callback_).Run();
@@ -198,15 +198,15 @@
     fetch_event_callback_ = std::move(closure);
   }
   int fetch_event_count() const { return fetch_event_count_; }
-  const network::ResourceRequest& fetch_event_request() const {
-    return fetch_event_request_;
+  const blink::mojom::FetchAPIRequest& fetch_event_request() const {
+    return *fetch_event_request_;
   }
 
   void Disconnect() { bindings_.CloseAllBindings(); }
 
  private:
   int fetch_event_count_ = 0;
-  network::ResourceRequest fetch_event_request_;
+  blink::mojom::FetchAPIRequestPtr fetch_event_request_;
   base::OnceClosure fetch_event_callback_;
   mojo::BindingSet<blink::mojom::ControllerServiceWorker> bindings_;
 
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index b9f55a30..6dde51c 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -12,6 +12,7 @@
 #include "base/optional.h"
 #include "base/strings/strcat.h"
 #include "base/trace_event/trace_event.h"
+#include "content/common/fetch/fetch_request_type_converters.h"
 #include "content/common/service_worker/service_worker_loader_helpers.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/common/service_worker/service_worker_utils.h"
@@ -278,7 +279,7 @@
   }
 
   auto params = blink::mojom::DispatchFetchEventParams::New();
-  params->request = resource_request_;
+  params->request = blink::mojom::FetchAPIRequest::From(resource_request_);
   params->client_id = controller_connector_->client_id();
 
   // S13nServiceWorker without NetworkService:
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index da51d55..3ff3347 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -251,12 +251,12 @@
       blink::mojom::DispatchFetchEventParamsPtr params,
       blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
       DispatchFetchEventCallback callback) override {
-    EXPECT_FALSE(ServiceWorkerUtils::IsMainResourceType(
-        static_cast<ResourceType>(params->request.resource_type)));
-    request_body_ = params->request.request_body;
+    EXPECT_FALSE(params->request->is_main_resource_load);
+    if (params->request->body)
+      request_body_ = params->request->body.value();
 
     fetch_event_count_++;
-    fetch_event_request_ = params->request;
+    fetch_event_request_ = std::move(params->request);
 
     auto timing = blink::mojom::ServiceWorkerFetchEventTiming::New();
     timing->dispatch_event_time = base::TimeTicks::Now();
@@ -292,9 +292,11 @@
         // Parse the Range header.
         std::string range_header;
         std::vector<net::HttpByteRange> ranges;
-        ASSERT_TRUE(params->request.headers.GetHeader(
-            net::HttpRequestHeaders::kRange, &range_header));
-        ASSERT_TRUE(net::HttpUtil::ParseRangeHeader(range_header, &ranges));
+        ASSERT_TRUE(fetch_event_request_->headers.contains(
+            std::string(net::HttpRequestHeaders::kRange)));
+        ASSERT_TRUE(net::HttpUtil::ParseRangeHeader(
+            fetch_event_request_->headers[net::HttpRequestHeaders::kRange],
+            &ranges));
         ASSERT_EQ(1u, ranges.size());
         ASSERT_TRUE(ranges[0].ComputeBounds(blob_range_body_.size()));
         const net::HttpByteRange& range = ranges[0];
@@ -355,8 +357,8 @@
   }
 
   int fetch_event_count() const { return fetch_event_count_; }
-  const network::ResourceRequest& fetch_event_request() const {
-    return fetch_event_request_;
+  const blink::mojom::FetchAPIRequest& fetch_event_request() const {
+    return *fetch_event_request_;
   }
 
  private:
@@ -375,7 +377,7 @@
   scoped_refptr<network::ResourceRequestBody> request_body_;
 
   int fetch_event_count_ = 0;
-  network::ResourceRequest fetch_event_request_;
+  blink::mojom::FetchAPIRequestPtr fetch_event_request_;
   base::OnceClosure fetch_event_callback_;
   mojo::BindingSet<blink::mojom::ControllerServiceWorker> bindings_;
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index e3d1c15..5913921 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1780,7 +1780,7 @@
     "../renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc",
     "../renderer/media/webrtc/webrtc_set_description_observer_unittest.cc",
     "../renderer/media/webrtc/webrtc_uma_histograms_unittest.cc",
-    "../renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc",
+    "../renderer/media/webrtc/webrtc_video_track_source_unittest.cc",
     "../renderer/media/webrtc_local_audio_source_provider_unittest.cc",
     "../renderer/media_capture_from_element/canvas_capture_handler_unittest.cc",
     "../renderer/media_capture_from_element/html_audio_element_capturer_source_unittest.cc",
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc
index 6ce27c5..c1185f0 100644
--- a/device/bluetooth/test/fake_central.cc
+++ b/device/bluetooth/test/fake_central.cc
@@ -40,9 +40,7 @@
 
 FakeCentral::FakeCentral(mojom::CentralState state,
                          mojom::FakeCentralRequest request)
-    : has_pending_or_active_discovery_session_(false),
-      state_(state),
-      binding_(this, std::move(request)) {}
+    : state_(state), binding_(this, std::move(request)) {}
 
 void FakeCentral::SimulatePreconnectedPeripheral(
     const std::string& address,
@@ -552,11 +550,7 @@
     return;
   }
 
-  // TODO(https://crbug.com/820113): Currently, multiple discovery sessions are
-  // not supported, so we DCHECK to ensure that there is not an active session
-  // already.
-  DCHECK(!has_pending_or_active_discovery_session_);
-  has_pending_or_active_discovery_session_ = true;
+  ++num_discovery_sessions_;
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                 base::BindOnce(callback));
 }
@@ -574,11 +568,15 @@
     return;
   }
 
-  // TODO(https://crbug.com/820113): Currently, multiple discovery sessions are
-  // not supported, so we DCHECK to ensure that there is currently an active
-  // session already.
-  DCHECK(has_pending_or_active_discovery_session_);
-  has_pending_or_active_discovery_session_ = false;
+  if (num_discovery_sessions_ == 0) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(error_callback),
+                       device::UMABluetoothDiscoverySessionOutcome::UNKNOWN));
+    return;
+  }
+
+  --num_discovery_sessions_;
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                 base::BindOnce(callback));
 }
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h
index cec3b96..405e998 100644
--- a/device/bluetooth/test/fake_central.h
+++ b/device/bluetooth/test/fake_central.h
@@ -214,10 +214,9 @@
       const std::string& characteristic_id,
       const std::string& descriptor_id) const;
 
-  bool has_pending_or_active_discovery_session_;
-
   mojom::CentralState state_;
   mojo::Binding<mojom::FakeCentral> binding_;
+  size_t num_discovery_sessions_ = 0;
 };
 
 }  // namespace bluetooth
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn
index 93bba5f..988daef 100644
--- a/ios/chrome/browser/signin/BUILD.gn
+++ b/ios/chrome/browser/signin/BUILD.gn
@@ -26,7 +26,10 @@
     "constants.mm",
     "gaia_auth_fetcher_ios.h",
     "gaia_auth_fetcher_ios.mm",
-    "gaia_auth_fetcher_ios_private.h",
+    "gaia_auth_fetcher_ios_bridge.h",
+    "gaia_auth_fetcher_ios_bridge.mm",
+    "gaia_auth_fetcher_ios_wk_webview_bridge.h",
+    "gaia_auth_fetcher_ios_wk_webview_bridge.mm",
     "gaia_cookie_manager_service_factory.cc",
     "gaia_cookie_manager_service_factory.h",
     "identity_manager_factory.cc",
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.h
index 6c8b03eaf..8df56ea9 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.h
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
 class GaiaAuthFetcherIOSBridge;
@@ -31,10 +32,10 @@
 //
 // Authenticate a user against the Google Accounts ClientLogin API
 // with various capabilities and return results to a GaiaAuthConsumer.
-//
-// If necessary (cookies needed and WKWebView enabled), the queries will
-// be fetched via a WKWebView instead of a net::URLFetcher.
-class GaiaAuthFetcherIOS : public GaiaAuthFetcher {
+// The queries are fetched using native APIs.
+class GaiaAuthFetcherIOS
+    : public GaiaAuthFetcher,
+      public GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate {
  public:
   // Sets whether the iOS specialization of the GaiaAuthFetcher should be used.
   // Mainly used for testing.
@@ -60,16 +61,18 @@
   friend class GaiaAuthFetcherIOSBridge;
   friend class GaiaAuthFetcherIOSTest;
 
+  // GaiaAuthFetcher.
   void CreateAndStartGaiaFetcher(
       const std::string& body,
       const std::string& headers,
       const GURL& gaia_gurl,
       int load_flags,
       const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
-  void FetchComplete(const GURL& url,
-                     const std::string& data,
-                     const net::URLRequestStatus& status,
-                     int response_code);
+  // GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate.
+  void OnFetchComplete(const GURL& url,
+                       const std::string& data,
+                       const net::URLRequestStatus& status,
+                       int response_code) override;
 
   std::unique_ptr<GaiaAuthFetcherIOSBridge> bridge_;
   web::BrowserState* browser_state_;
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
index f9b1e12c..35ac343 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
@@ -6,20 +6,11 @@
 
 #import <WebKit/WebKit.h>
 
-#include "base/ios/ios_util.h"
-#include "base/json/string_escape.h"
 #include "base/logging.h"
 #import "base/mac/foundation_util.h"
-#include "base/mac/scoped_block.h"
-#include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h"
+#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h"
 #include "ios/web/public/browser_state.h"
-#import "ios/web/public/web_view_creation_util.h"
 #include "net/base/load_flags.h"
-#import "net/base/mac/url_conversions.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/url_request/url_request_status.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -31,311 +22,18 @@
 // Whether the iOS specialization of the GaiaAuthFetcher should be used.
 bool g_should_use_gaia_auth_fetcher_ios = true;
 
-// JavaScript template to do a POST request using an XMLHttpRequest.
-// The request is retried once on failure, as it can be marked as failing to
-// load the resource because of 302s on POST request (the cookies of the first
-// response are correctly set).
-//
-// The template takes three arguments (in order):
-// * The quoted and escaped URL to send a POST request to.
-// * The HTTP headers of the request. They should be written as valid JavaScript
-//   statements, adding headers to the XMLHttpRequest variable named 'req'
-//   (e.g. 'req.setRequestHeader("Foo", "Bar");').
-// * The quoted and escaped body of the POST request.
-NSString* const kPostRequestTemplate =
-    @"<html><script>"
-     "function __gCrWebDoPostRequest() {"
-     "  function createAndSendPostRequest() {"
-     "    var req = new XMLHttpRequest();"
-     "    req.open(\"POST\", %@, false);"
-     "    req.setRequestHeader(\"Content-Type\","
-     "\"application/x-www-form-urlencoded\");"
-     "%@"
-     "    req.send(%@);"
-     "    if (req.status != 200) {"
-     "      throw req.status;"
-     "    }"
-     "    return req.responseText;"
-     "  }"
-     "  try {"
-     "    return createAndSendPostRequest();"
-     "  } catch(err) {"
-     "    return createAndSendPostRequest();"
-     "  }"
-     "}"
-     "</script></html>";
-
-// JavaScript template to read the response to a GET or POST request. There is
-// two different cases:
-// * GET request, which was made by simply loading a request to the correct
-//   URL. The response is the inner text (to avoid formatting in case of JSON
-//   answers) of the body.
-// * POST request, in case the "__gCrWebDoPostRequest" function is defined.
-//   Running the function will do a POST request via a XMLHttpRequest and
-//   return the response. See DoPostRequest below to know why this is necessary.
-NSString* const kReadResponseTemplate =
-    @"if (typeof __gCrWebDoPostRequest === 'function') {"
-     "  __gCrWebDoPostRequest();"
-     "} else {"
-     "  document.body.innerText;"
-     "}";
-
-// Creates an NSURLRequest to |url| that can be loaded by a WebView from |body|
-// and |headers|.
-// The request is a GET if |body| is empty and a POST otherwise.
-NSURLRequest* GetRequest(const std::string& body,
-                         const std::string& headers,
-                         const GURL& url) {
-  NSMutableURLRequest* request =
-      [[NSMutableURLRequest alloc] initWithURL:net::NSURLWithGURL(url)];
-  net::HttpRequestHeaders request_headers;
-  request_headers.AddHeadersFromString(headers);
-  for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) {
-    [request setValue:base::SysUTF8ToNSString(it.value())
-        forHTTPHeaderField:base::SysUTF8ToNSString(it.name())];
-  }
-  if (!body.empty()) {
-    NSData* post_data =
-        [base::SysUTF8ToNSString(body) dataUsingEncoding:NSUTF8StringEncoding];
-    [request setHTTPBody:post_data];
-    [request setHTTPMethod:@"POST"];
-    DCHECK(![[request allHTTPHeaderFields] objectForKey:@"Content-Type"]);
-    [request setValue:@"application/x-www-form-urlencoded"
-        forHTTPHeaderField:@"Content-Type"];
-  }
-  return request;
-}
-
-// Escapes and quotes |value| and converts the result to an NSString.
-NSString* EscapeAndQuoteToNSString(const std::string& value) {
-  return base::SysUTF8ToNSString(base::GetQuotedJSONString(value));
-}
-
-// Simulates a POST request on |web_view| using a XMLHttpRequest in
-// JavaScript.
-// This is needed because WKWebView ignores the HTTPBody in a POST request
-// before iOS11 and because WKWebView cannot read response body if
-// content-disposition header is set. See
-// https://bugs.webkit.org/show_bug.cgi?id=145410
-// TODO(crbug.com/889471) Remove this once requests are done using
-// NSUrlSession in iOS.
-void DoPostRequest(WKWebView* web_view,
-                   const std::string& body,
-                   const std::string& headers,
-                   const GURL& url) {
-  NSMutableString* header_data = [NSMutableString string];
-  net::HttpRequestHeaders request_headers;
-  request_headers.AddHeadersFromString(headers);
-  for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) {
-    if (it.name() == "Origin") {
-      // The Origin request header cannot be set on an XMLHttpRequest.
-      continue;
-    }
-    // net::HttpRequestHeaders escapes the name and value for a header. Some
-    // escaping might still be necessary for the JavaScript layer.
-    [header_data appendFormat:@"req.setRequestHeader(%@, %@);",
-                              EscapeAndQuoteToNSString(it.name()),
-                              EscapeAndQuoteToNSString(it.value())];
-  }
-  NSString* html_string =
-      [NSString stringWithFormat:kPostRequestTemplate,
-                                 EscapeAndQuoteToNSString(url.spec()),
-                                 header_data, EscapeAndQuoteToNSString(body)];
-  // |url| is used as the baseURL to avoid CORS issues.
-  [web_view loadHTMLString:html_string baseURL:net::NSURLWithGURL(url)];
-}
 }  // namespace
 
-#pragma mark - GaiaAuthFetcherNavigationDelegate
-
-@implementation GaiaAuthFetcherNavigationDelegate {
-  GaiaAuthFetcherIOSBridge* bridge_;  // weak
-}
-- (instancetype)initWithBridge:(GaiaAuthFetcherIOSBridge*)bridge {
-  self = [super init];
-  if (self) {
-    bridge_ = bridge;
-  }
-  return self;
-}
-
-#pragma mark WKNavigationDelegate
-
-- (void)webView:(WKWebView*)webView
-    didFailNavigation:(WKNavigation*)navigation
-            withError:(NSError*)error {
-  DVLOG(1) << "Gaia fetcher navigation failed: "
-           << base::SysNSStringToUTF8(error.localizedDescription);
-  bridge_->URLFetchFailure(false /* is_cancelled */);
-}
-
-- (void)webView:(WKWebView*)webView
-    didFailProvisionalNavigation:(WKNavigation*)navigation
-                       withError:(NSError*)error {
-  DVLOG(1) << "Gaia fetcher provisional navigation failed: "
-           << base::SysNSStringToUTF8(error.localizedDescription);
-  bridge_->URLFetchFailure(false /* is_cancelled */);
-}
-
-- (void)webView:(WKWebView*)webView
-    didFinishNavigation:(WKNavigation*)navigation {
-  // A WKNavigation is an opaque object. The only way to access the body of the
-  // response is via Javascript.
-  DVLOG(2) << "WKWebView loaded:" << net::GURLWithNSURL(webView.URL);
-  [webView evaluateJavaScript:kReadResponseTemplate
-            completionHandler:^(NSString* result, NSError* error) {
-              if (error || !result) {
-                DVLOG(1) << "Gaia fetcher extract body failed:"
-                         << base::SysNSStringToUTF8(error.localizedDescription);
-                bridge_->URLFetchFailure(false /* is_cancelled */);
-              } else {
-                DCHECK([result isKindOfClass:[NSString class]]);
-                bridge_->URLFetchSuccess(base::SysNSStringToUTF8(result));
-              }
-            }];
-}
-
-@end
-
-#pragma mark - GaiaAuthFetcherIOSBridge::Request
-
-GaiaAuthFetcherIOSBridge::Request::Request()
-    : pending(false),
-      url(),
-      headers(),
-      body(),
-      shouldUseXmlHTTPRequest(false) {}
-
-GaiaAuthFetcherIOSBridge::Request::Request(const GURL& request_url,
-                                           const std::string& request_headers,
-                                           const std::string& request_body,
-                                           bool shouldUseXmlHTTPRequest)
-    : pending(true),
-      url(request_url),
-      headers(request_headers),
-      body(request_body),
-      shouldUseXmlHTTPRequest(shouldUseXmlHTTPRequest) {}
-
-#pragma mark - GaiaAuthFetcherIOSBridge
-
-GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridge(
-    GaiaAuthFetcherIOS* fetcher,
-    web::BrowserState* browser_state)
-    : browser_state_(browser_state), fetcher_(fetcher), request_() {
-  ActiveStateManager::FromBrowserState(browser_state_)->AddObserver(this);
-}
-
-GaiaAuthFetcherIOSBridge::~GaiaAuthFetcherIOSBridge() {
-  ActiveStateManager::FromBrowserState(browser_state_)->RemoveObserver(this);
-  ResetWKWebView();
-}
-
-void GaiaAuthFetcherIOSBridge::Fetch(const GURL& url,
-                                     const std::string& headers,
-                                     const std::string& body,
-                                     bool shouldUseXmlHTTPRequest) {
-  request_ = Request(url, headers, body, shouldUseXmlHTTPRequest);
-  FetchPendingRequest();
-}
-
-void GaiaAuthFetcherIOSBridge::Cancel() {
-  if (!request_.pending) {
-    return;
-  }
-  [GetWKWebView() stopLoading];
-  URLFetchFailure(true /* is_cancelled */);
-}
-
-void GaiaAuthFetcherIOSBridge::URLFetchSuccess(const std::string& data) {
-  if (!request_.pending) {
-    return;
-  }
-  GURL url = FinishPendingRequest();
-  // WKWebViewNavigationDelegate API doesn't give any way to get the HTTP
-  // response code of a navigation. Default to 200 for success.
-  fetcher_->FetchComplete(url, data, net::URLRequestStatus(), 200);
-}
-
-void GaiaAuthFetcherIOSBridge::URLFetchFailure(bool is_cancelled) {
-  if (!request_.pending) {
-    return;
-  }
-  GURL url = FinishPendingRequest();
-  // WKWebViewNavigationDelegate API doesn't give any way to get the HTTP
-  // response code of a navigation. Default to 500 for error.
-  int error = is_cancelled ? net::ERR_ABORTED : net::ERR_FAILED;
-  fetcher_->FetchComplete(url, std::string(),
-                          net::URLRequestStatus::FromError(error), 500);
-}
-
-void GaiaAuthFetcherIOSBridge::FetchPendingRequest() {
-  if (!request_.pending)
-    return;
-  if (!request_.body.empty() && request_.shouldUseXmlHTTPRequest) {
-    DoPostRequest(GetWKWebView(), request_.body, request_.headers,
-                  request_.url);
-  } else {
-    [GetWKWebView()
-        loadRequest:GetRequest(request_.body, request_.headers, request_.url)];
-  }
-}
-
-GURL GaiaAuthFetcherIOSBridge::FinishPendingRequest() {
-  GURL url = request_.url;
-  request_ = Request();
-  return url;
-}
-
-WKWebView* GaiaAuthFetcherIOSBridge::GetWKWebView() {
-  if (!ActiveStateManager::FromBrowserState(browser_state_)->IsActive()) {
-    // |browser_state_| is not active, WKWebView linked to this browser state
-    // should not exist or be created.
-    return nil;
-  }
-  if (!web_view_) {
-    web_view_ = BuildWKWebView();
-    navigation_delegate_ =
-        [[GaiaAuthFetcherNavigationDelegate alloc] initWithBridge:this];
-    [web_view_ setNavigationDelegate:navigation_delegate_];
-  }
-  return web_view_;
-}
-
-void GaiaAuthFetcherIOSBridge::ResetWKWebView() {
-  [web_view_ setNavigationDelegate:nil];
-  [web_view_ stopLoading];
-  web_view_ = nil;
-  navigation_delegate_ = nil;
-}
-
-WKWebView* GaiaAuthFetcherIOSBridge::BuildWKWebView() {
-  return web::BuildWKWebView(CGRectZero, browser_state_);
-}
-
-void GaiaAuthFetcherIOSBridge::OnActive() {
-  // |browser_state_| is now active. If there is a pending request, restart it.
-  FetchPendingRequest();
-}
-
-void GaiaAuthFetcherIOSBridge::OnInactive() {
-  // |browser_state_| is now inactive. Stop using |web_view_| and don't create
-  // a new one until it is active.
-  ResetWKWebView();
-}
-
-#pragma mark - GaiaAuthFetcherIOS definition
-
 GaiaAuthFetcherIOS::GaiaAuthFetcherIOS(
     GaiaAuthConsumer* consumer,
     gaia::GaiaSource source,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     web::BrowserState* browser_state)
     : GaiaAuthFetcher(consumer, source, url_loader_factory),
-      bridge_(new GaiaAuthFetcherIOSBridge(this, browser_state)),
+      bridge_(new GaiaAuthFetcherIOSWKWebViewBridge(this, browser_state)),
       browser_state_(browser_state) {}
 
-GaiaAuthFetcherIOS::~GaiaAuthFetcherIOS() {
-}
+GaiaAuthFetcherIOS::~GaiaAuthFetcherIOS() {}
 
 void GaiaAuthFetcherIOS::CreateAndStartGaiaFetcher(
     const std::string& body,
@@ -361,8 +59,8 @@
   // a network request with cookies sent and saved is by making it through a
   // WKWebView.
   SetPendingFetch(true);
-  bool shouldUseXmlHTTPRequest = IsMultiloginUrl(gaia_gurl);
-  bridge_->Fetch(gaia_gurl, headers, body, shouldUseXmlHTTPRequest);
+  bool should_use_xml_http_request = IsMultiloginUrl(gaia_gurl);
+  bridge_->Fetch(gaia_gurl, headers, body, should_use_xml_http_request);
 }
 
 void GaiaAuthFetcherIOS::CancelRequest() {
@@ -373,10 +71,10 @@
   GaiaAuthFetcher::CancelRequest();
 }
 
-void GaiaAuthFetcherIOS::FetchComplete(const GURL& url,
-                                       const std::string& data,
-                                       const net::URLRequestStatus& status,
-                                       int response_code) {
+void GaiaAuthFetcherIOS::OnFetchComplete(const GURL& url,
+                                         const std::string& data,
+                                         const net::URLRequestStatus& status,
+                                         int response_code) {
   DVLOG(2) << "Response " << url.spec() << ", code = " << response_code << "\n";
   DVLOG(2) << "data: " << data << "\n";
   SetPendingFetch(false);
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h
new file mode 100644
index 0000000..f3a55e4
--- /dev/null
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h
@@ -0,0 +1,131 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_BRIDGE_H_
+#define IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_BRIDGE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request_status.h"
+
+class GURL;
+@class NSURLRequest;
+
+namespace web {
+class BrowserState;
+}
+
+// Specialization of GaiaAuthFetcher on iOS.
+//
+// Authenticate a user against the Google Accounts ClientLogin API
+// with various capabilities and return results to a GaiaAuthConsumer.
+// This class is an interface, and FetchPendingRequest() and Cancel() have to
+// be implemented using native APIs in a subclass.
+class GaiaAuthFetcherIOSBridge {
+ public:
+  // Delegate class receive notification whent the request is done.
+  class GaiaAuthFetcherIOSBridgeDelegate {
+   public:
+    GaiaAuthFetcherIOSBridgeDelegate();
+    virtual ~GaiaAuthFetcherIOSBridgeDelegate();
+
+    // Called when the request is done.
+    virtual void OnFetchComplete(const GURL& url,
+                                 const std::string& data,
+                                 const net::URLRequestStatus& status,
+                                 int response_code) = 0;
+
+    DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcherIOSBridgeDelegate);
+  };
+
+  // Initializes the instance.
+  GaiaAuthFetcherIOSBridge(GaiaAuthFetcherIOSBridgeDelegate* delegate,
+                           web::BrowserState* browser_state);
+  virtual ~GaiaAuthFetcherIOSBridge();
+
+  // Starts a network fetch.
+  // * |url| is the URL to fetch.
+  // * |headers| are the HTTP headers to add to the request.
+  // * |body| is the HTTP body to add to the request. If not empty, the fetch
+  //   will be a POST request.
+  void Fetch(const GURL& url,
+             const std::string& headers,
+             const std::string& body,
+             bool should_use_xml_http_request);
+
+  // Cancels the current fetch.
+  virtual void Cancel() = 0;
+
+  // Informs the bridge of the success of the URL fetch.
+  // * |data| is the body of the HTTP response.
+  // * |response_code| is the response code.
+  // URLFetchSuccess and URLFetchFailure are no-op if one of them was already
+  // called.
+  void OnURLFetchSuccess(const std::string& data, int response_code);
+
+  // Informs the bridge of the failure of the URL fetch.
+  // * |is_cancelled| whether the fetch failed because it was cancelled.
+  // URLFetchSuccess and URLFetchFailure are no-op if one of them was already
+  // called.
+  void OnURLFetchFailure(int error, int response_code);
+
+  // Returns the current browser state.
+  web::BrowserState* GetBrowserState() const;
+
+ protected:
+  // Fetches the pending request if it exists. The subclass needs to update the
+  // cookie store for each redirect and call either URLFetchSuccess() or
+  // URLFetchFailure().
+  virtual void FetchPendingRequest() = 0;
+
+  // A network request that needs to be fetched.
+  struct Request {
+    Request();
+    Request(const GURL& url,
+            const std::string& headers,
+            const std::string& body,
+            bool should_use_xml_http_request);
+    // Whether the request is pending (i.e. awaiting to be processed or
+    // currently being processed).
+    bool pending;
+    // URL to fetch.
+    GURL url;
+    // HTTP headers to add to the request.
+    std::string headers;
+    // HTTP body to add to the request.
+    std::string body;
+    // Whether XmlHTTPRequest should be injected in JS instead of using
+    // WKWebView directly.
+    bool should_use_xml_http_request;
+  };
+
+  // Returns a |request_| that contains the url, the headers and the body
+  // received in the constructor of this instance.
+  const Request& GetRequest() const;
+
+  // Creates a NSURLRequest with the url, the headers and the body received in
+  // the constructor of this instance. The request is a GET if |body| is empty
+  // and a POST otherwise.
+  NSURLRequest* GetNSURLRequest() const;
+
+ private:
+  // Finishes the pending request and cleans up its associated state. Returns
+  // the URL of the request.
+  GURL FinishPendingRequest();
+
+  // Delegate.
+  GaiaAuthFetcherIOSBridgeDelegate* delegate_;
+  // Browser state associated with the bridge.
+  web::BrowserState* browser_state_;
+  // Request currently processed by the bridge.
+  Request request_;
+
+  DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcherIOSBridge);
+};
+
+#endif  // IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_BRIDGE_H_
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.mm
new file mode 100644
index 0000000..ebee7bd
--- /dev/null
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.mm
@@ -0,0 +1,110 @@
+// Copyright 2018 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 "ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/strings/sys_string_conversions.h"
+#import "net/base/mac/url_conversions.h"
+#include "net/http/http_request_headers.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#pragma mark - GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate
+
+GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate::
+    GaiaAuthFetcherIOSBridgeDelegate() {}
+
+GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate::
+    ~GaiaAuthFetcherIOSBridgeDelegate() {}
+
+#pragma mark - GaiaAuthFetcherIOSBridge::Request
+
+GaiaAuthFetcherIOSBridge::Request::Request()
+    : pending(false), should_use_xml_http_request(false) {}
+
+GaiaAuthFetcherIOSBridge::Request::Request(const GURL& request_url,
+                                           const std::string& request_headers,
+                                           const std::string& request_body,
+                                           bool should_use_xml_http_request)
+    : pending(true),
+      url(request_url),
+      headers(request_headers),
+      body(request_body),
+      should_use_xml_http_request(should_use_xml_http_request) {}
+
+#pragma mark - GaiaAuthFetcherIOSBridge
+
+GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridge(
+    GaiaAuthFetcherIOSBridgeDelegate* delegate,
+    web::BrowserState* browser_state)
+    : delegate_(delegate), browser_state_(browser_state) {}
+
+GaiaAuthFetcherIOSBridge::~GaiaAuthFetcherIOSBridge() {}
+
+void GaiaAuthFetcherIOSBridge::Fetch(const GURL& url,
+                                     const std::string& headers,
+                                     const std::string& body,
+                                     bool should_use_xml_http_request) {
+  request_ = Request(url, headers, body, should_use_xml_http_request);
+  FetchPendingRequest();
+}
+
+void GaiaAuthFetcherIOSBridge::OnURLFetchSuccess(const std::string& data,
+                                                 int response_code) {
+  if (!request_.pending) {
+    return;
+  }
+  GURL url = FinishPendingRequest();
+  delegate_->OnFetchComplete(url, data, net::URLRequestStatus(), response_code);
+}
+
+void GaiaAuthFetcherIOSBridge::OnURLFetchFailure(int error, int response_code) {
+  if (!request_.pending) {
+    return;
+  }
+  GURL url = FinishPendingRequest();
+  delegate_->OnFetchComplete(url, std::string(),
+                             net::URLRequestStatus::FromError(error),
+                             response_code);
+}
+
+web::BrowserState* GaiaAuthFetcherIOSBridge::GetBrowserState() const {
+  return browser_state_;
+}
+
+const GaiaAuthFetcherIOSBridge::Request& GaiaAuthFetcherIOSBridge::GetRequest()
+    const {
+  return request_;
+}
+
+NSURLRequest* GaiaAuthFetcherIOSBridge::GetNSURLRequest() const {
+  NSMutableURLRequest* request = [[NSMutableURLRequest alloc]
+      initWithURL:net::NSURLWithGURL(request_.url)];
+  net::HttpRequestHeaders request_headers;
+  request_headers.AddHeadersFromString(request_.headers);
+  for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) {
+    [request setValue:base::SysUTF8ToNSString(it.value())
+        forHTTPHeaderField:base::SysUTF8ToNSString(it.name())];
+  }
+  if (!request_.body.empty()) {
+    NSData* post_data = [base::SysUTF8ToNSString(request_.body)
+        dataUsingEncoding:NSUTF8StringEncoding];
+    [request setHTTPBody:post_data];
+    [request setHTTPMethod:@"POST"];
+    DCHECK(![[request allHTTPHeaderFields] objectForKey:@"Content-Type"]);
+    [request setValue:@"application/x-www-form-urlencoded"
+        forHTTPHeaderField:@"Content-Type"];
+  }
+  return request;
+}
+
+GURL GaiaAuthFetcherIOSBridge::FinishPendingRequest() {
+  GURL url = request_.url;
+  request_ = Request();
+  return url;
+}
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h
deleted file mode 100644
index 40e8459e..0000000
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_PRIVATE_H_
-#define IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_PRIVATE_H_
-
-#import <WebKit/WebKit.h>
-
-#include "base/macros.h"
-#include "components/signin/ios/browser/active_state_manager.h"
-
-class GaiaAuthFetcherIOS;
-class GURL;
-
-namespace web {
-class BrowserState;
-}
-
-// Navigation delegate attached to a WKWebView used for URL fetches.
-@interface GaiaAuthFetcherNavigationDelegate : NSObject<WKNavigationDelegate>
-@end
-
-// Bridge between the GaiaAuthFetcherIOS and the webview (and its navigation
-// delegate) used to actually do the network fetch.
-class GaiaAuthFetcherIOSBridge : ActiveStateManager::Observer {
- public:
-  GaiaAuthFetcherIOSBridge(GaiaAuthFetcherIOS* fetcher,
-                           web::BrowserState* browser_state);
-  virtual ~GaiaAuthFetcherIOSBridge();
-
-  // Starts a network fetch.
-  // * |url| is the URL to fetch.
-  // * |headers| are the HTTP headers to add to the request.
-  // * |body| is the HTTP body to add to the request. If not empty, the fetch
-  //   will be a POST request.
-  void Fetch(const GURL& url,
-             const std::string& headers,
-             const std::string& body,
-             bool shouldUseXmlHTTPRequest);
-
-  // Cancels the current fetch.
-  void Cancel();
-
-  // Informs the bridge of the success of the URL fetch.
-  // * |data| is the body of the HTTP response.
-  // URLFetchSuccess and URLFetchFailure are no-op if one of them was already
-  // called.
-  void URLFetchSuccess(const std::string& data);
-
-  // Informs the bridge of the failure of the URL fetch.
-  // * |is_cancelled| whether the fetch failed because it was cancelled.
-  // URLFetchSuccess and URLFetchFailure are no-op if one of them was already
-  // called.
-  void URLFetchFailure(bool is_cancelled);
-
- private:
-  friend class GaiaAuthFetcherIOSTest;
-
-  // A network request that needs to be fetched.
-  struct Request {
-    Request();
-    Request(const GURL& url,
-            const std::string& headers,
-            const std::string& body,
-            bool shouldUseXmlHTTPRequest);
-    // Whether the request is pending (i.e. awaiting to be processed or
-    // currently being processed).
-    bool pending;
-    // URL to fetch.
-    GURL url;
-    // HTTP headers to add to the request.
-    std::string headers;
-    // HTTP body to add to the request.
-    std::string body;
-    // Whether XmlHTTPRequest should be injected in JS instead of using
-    // WKWebView directly.
-    bool shouldUseXmlHTTPRequest;
-  };
-
-  // Fetches the pending request if it exists.
-  void FetchPendingRequest();
-  // Finishes the pending request and cleans up its associated state. Returns
-  // the URL of the request.
-  GURL FinishPendingRequest();
-
-  // Returns the cached WKWebView if it exists, or creates one if necessary.
-  // Can return nil if the browser state is not active.
-  WKWebView* GetWKWebView();
-  // Actually creates a WKWebView. Virtual for testing.
-  virtual WKWebView* BuildWKWebView();
-  // Stops any page loading in the WKWebView currently in use and releases it.
-  void ResetWKWebView();
-
-  // ActiveStateManager::Observer implementation.
-  void OnActive() override;
-  void OnInactive() override;
-
-  // Browser state associated with the bridge, used to create WKWebViews.
-  web::BrowserState* browser_state_;
-  // Fetcher owning this bridge.
-  GaiaAuthFetcherIOS* fetcher_;
-  // Request currently processed by the bridge.
-  Request request_;
-  // Navigation delegate of |web_view_| that informs the bridge of relevant
-  // navigation events.
-  GaiaAuthFetcherNavigationDelegate* navigation_delegate_;
-  // Web view used to do the network requests.
-  WKWebView* web_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcherIOSBridge);
-};
-
-#endif  // IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_PRIVATE_H_
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
index affe9af..75d692d 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
@@ -4,6 +4,7 @@
 
 #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios.h"
 
+#import <WebKit/WebKit.h>
 #include <memory>
 
 #include "base/ios/ios_util.h"
@@ -12,7 +13,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h"
+#import "ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -31,11 +32,14 @@
 
 namespace {
 
-class FakeGaiaAuthFetcherIOSBridge : public GaiaAuthFetcherIOSBridge {
+class FakeGaiaAuthFetcherIOSWKWebViewBridge
+    : public GaiaAuthFetcherIOSWKWebViewBridge {
  public:
-  FakeGaiaAuthFetcherIOSBridge(GaiaAuthFetcherIOS* fetcher,
-                               web::BrowserState* browser_state)
-      : GaiaAuthFetcherIOSBridge(fetcher, browser_state), mock_web_view_(nil) {}
+  FakeGaiaAuthFetcherIOSWKWebViewBridge(
+      GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate,
+      web::BrowserState* browser_state)
+      : GaiaAuthFetcherIOSWKWebViewBridge(delegate, browser_state),
+        mock_web_view_(nil) {}
 
  private:
   WKWebView* BuildWKWebView() override {
@@ -72,7 +76,7 @@
     gaia_auth_fetcher_.reset(
         new GaiaAuthFetcherIOS(&consumer_, gaia::GaiaSource::kChrome,
                                test_shared_loader_factory_, browser_state()));
-    gaia_auth_fetcher_->bridge_.reset(new FakeGaiaAuthFetcherIOSBridge(
+    gaia_auth_fetcher_->bridge_.reset(new FakeGaiaAuthFetcherIOSWKWebViewBridge(
         gaia_auth_fetcher_.get(), browser_state()));
   }
 
@@ -88,7 +92,12 @@
 
   ios::ChromeBrowserState* browser_state() { return browser_state_.get(); }
 
-  id GetMockWKWebView() { return gaia_auth_fetcher_->bridge_->GetWKWebView(); }
+  id GetMockWKWebView() {
+    GaiaAuthFetcherIOSWKWebViewBridge* wkWebviewBridge =
+        reinterpret_cast<GaiaAuthFetcherIOSWKWebViewBridge*>(
+            gaia_auth_fetcher_->bridge_.get());
+    return wkWebviewBridge->GetWKWebView();
+  }
 
   web::TestWebThreadBundle thread_bundle_;
   // BrowserState, required for WKWebView creation.
@@ -123,7 +132,7 @@
   EXPECT_CALL(consumer_, OnMergeSessionSuccess("data")).Times(1);
 
   [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) {
-    GetBridge()->URLFetchSuccess("data");
+    GetBridge()->OnURLFetchSuccess("data", 200);
   }]) loadRequest:[OCMArg any]];
 
   gaia_auth_fetcher_->StartMergeSession("uber_token", "");
@@ -138,7 +147,7 @@
   EXPECT_CALL(consumer_, OnLogOutFailure(expected_error)).Times(1);
 
   [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) {
-    GetBridge()->URLFetchFailure(false);
+    GetBridge()->OnURLFetchFailure(net::ERR_FAILED, 500);
   }]) loadRequest:[OCMArg any]];
 
   gaia_auth_fetcher_->StartLogOut();
@@ -180,7 +189,7 @@
   // its navigation delegate are created, and the request is processed.
   [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNotNil]];
   [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) {
-    GetBridge()->URLFetchSuccess("data");
+    GetBridge()->OnURLFetchSuccess("data", 200);
   }]) loadRequest:[OCMArg any]];
 
   ActiveStateManager::FromBrowserState(browser_state())->SetActive(false);
@@ -199,7 +208,7 @@
   [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNil]];
   [[GetMockWKWebView() expect] setNavigationDelegate:[OCMArg isNotNil]];
   [static_cast<WKWebView*>([[GetMockWKWebView() expect] andDo:^(NSInvocation*) {
-    GetBridge()->URLFetchSuccess("data");
+    GetBridge()->OnURLFetchSuccess("data", 200);
   }]) loadRequest:[OCMArg any]];
 
   gaia_auth_fetcher_->StartMergeSession("uber_token", "");
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h
new file mode 100644
index 0000000..635e108
--- /dev/null
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h
@@ -0,0 +1,57 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_WK_WEBVIEW_BRIDGE_H_
+#define IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_WK_WEBVIEW_BRIDGE_H_
+
+#import <Foundation/Foundation.h>
+
+#include "components/signin/ios/browser/active_state_manager.h"
+#include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_bridge.h"
+
+@class GaiaAuthFetcherNavigationDelegate;
+@class NSHTTPCookie;
+@class WKWebView;
+
+// Specialization of GaiaAuthFetcher on iOS, using WKWebView to send requests.
+class GaiaAuthFetcherIOSWKWebViewBridge : public GaiaAuthFetcherIOSBridge,
+                                          ActiveStateManager::Observer {
+ public:
+  GaiaAuthFetcherIOSWKWebViewBridge(
+      GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate,
+      web::BrowserState* browser_state);
+  ~GaiaAuthFetcherIOSWKWebViewBridge() override;
+
+  // GaiaAuthFetcherIOSBridge.
+  void Cancel() override;
+
+ protected:
+  friend class GaiaAuthFetcherIOSTest;
+
+  // GaiaAuthFetcherIOSBridge.
+  void FetchPendingRequest() override;
+
+  // Returns the cached WKWebView if it exists, or creates one if necessary.
+  // Can return nil if the browser state is not active.
+  WKWebView* GetWKWebView();
+  // Actually creates a WKWebView. Virtual for testing.
+  virtual WKWebView* BuildWKWebView();
+  // Stops any page loading in the WKWebView currently in use and releases it.
+  void ResetWKWebView();
+
+  // ActiveStateManager::Observer implementation.
+  void OnActive() override;
+  void OnInactive() override;
+
+ private:
+  // Navigation delegate of |web_view_| that informs the bridge of relevant
+  // navigation events.
+  GaiaAuthFetcherNavigationDelegate* navigation_delegate_;
+  // Web view used to do the network requests.
+  WKWebView* web_view_;
+
+  DISALLOW_COPY_AND_ASSIGN(GaiaAuthFetcherIOSWKWebViewBridge);
+};
+
+#endif  // IOS_CHROME_BROWSER_SIGNIN_GAIA_AUTH_FETCHER_IOS_WK_WEBVIEW_BRIDGE_H_
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.mm
new file mode 100644
index 0000000..5934bf9
--- /dev/null
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.mm
@@ -0,0 +1,246 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/signin/gaia_auth_fetcher_ios_wk_webview_bridge.h"
+
+#import <Foundation/Foundation.h>
+#import <WebKit/WebKit.h>
+
+#include "base/json/string_escape.h"
+#include "base/strings/sys_string_conversions.h"
+#import "ios/web/public/web_view_creation_util.h"
+#import "net/base/mac/url_conversions.h"
+#include "net/http/http_request_headers.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// JavaScript template to do a POST request using an XMLHttpRequest.
+// The request is retried once on failure, as it can be marked as failing to
+// load the resource because of 302s on POST request (the cookies of the first
+// response are correctly set).
+//
+// The template takes three arguments (in order):
+// * The quoted and escaped URL to send a POST request to.
+// * The HTTP headers of the request. They should be written as valid JavaScript
+//   statements, adding headers to the XMLHttpRequest variable named 'req'
+//   (e.g. 'req.setRequestHeader("Foo", "Bar");').
+// * The quoted and escaped body of the POST request.
+NSString* const kPostRequestTemplate =
+    @"<html><script>"
+     "function __gCrWebDoPostRequest() {"
+     "  function createAndSendPostRequest() {"
+     "    var req = new XMLHttpRequest();"
+     "    req.open(\"POST\", %@, false);"
+     "    req.setRequestHeader(\"Content-Type\","
+     "\"application/x-www-form-urlencoded\");"
+     "%@"
+     "    req.send(%@);"
+     "    if (req.status != 200) {"
+     "      throw req.status;"
+     "    }"
+     "    return req.responseText;"
+     "  }"
+     "  try {"
+     "    return createAndSendPostRequest();"
+     "  } catch(err) {"
+     "    return createAndSendPostRequest();"
+     "  }"
+     "}"
+     "</script></html>";
+
+// JavaScript template to read the response to a GET or POST request. There is
+// two different cases:
+// * GET request, which was made by simply loading a request to the correct
+//   URL. The response is the inner text (to avoid formatting in case of JSON
+//   answers) of the body.
+// * POST request, in case the "__gCrWebDoPostRequest" function is defined.
+//   Running the function will do a POST request via a XMLHttpRequest and
+//   return the response. See DoPostRequest below to know why this is necessary.
+NSString* const kReadResponseTemplate =
+    @"if (typeof __gCrWebDoPostRequest === 'function') {"
+     "  __gCrWebDoPostRequest();"
+     "} else {"
+     "  document.body.innerText;"
+     "}";
+
+// Escapes and quotes |value| and converts the result to an NSString.
+NSString* EscapeAndQuoteToNSString(const std::string& value) {
+  return base::SysUTF8ToNSString(base::GetQuotedJSONString(value));
+}
+
+// Simulates a POST request on |web_view| using a XMLHttpRequest in
+// JavaScript.
+// This is needed because WKWebView ignores the HTTPBody in a POST request
+// before iOS11 and because WKWebView cannot read response body if
+// content-disposition header is set. See
+// https://bugs.webkit.org/show_bug.cgi?id=145410
+// TODO(crbug.com/889471) Remove this once requests are done using
+// NSUrlSession in iOS.
+void DoPostRequest(WKWebView* web_view,
+                   const std::string& body,
+                   const std::string& headers,
+                   const GURL& url) {
+  NSMutableString* header_data = [NSMutableString string];
+  net::HttpRequestHeaders request_headers;
+  request_headers.AddHeadersFromString(headers);
+  for (net::HttpRequestHeaders::Iterator it(request_headers); it.GetNext();) {
+    if (it.name() == "Origin") {
+      // The Origin request header cannot be set on an XMLHttpRequest.
+      continue;
+    }
+    // net::HttpRequestHeaders escapes the name and value for a header. Some
+    // escaping might still be necessary for the JavaScript layer.
+    [header_data appendFormat:@"req.setRequestHeader(%@, %@);",
+                              EscapeAndQuoteToNSString(it.name()),
+                              EscapeAndQuoteToNSString(it.value())];
+  }
+  NSString* html_string =
+      [NSString stringWithFormat:kPostRequestTemplate,
+                                 EscapeAndQuoteToNSString(url.spec()),
+                                 header_data, EscapeAndQuoteToNSString(body)];
+  // |url| is used as the baseURL to avoid CORS issues.
+  [web_view loadHTMLString:html_string baseURL:net::NSURLWithGURL(url)];
+}
+}  // namespace
+
+#pragma mark - GaiaAuthFetcherNavigationDelegate
+
+// Navigation delegate attached to a WKWebView used for URL fetches.
+@interface GaiaAuthFetcherNavigationDelegate : NSObject <WKNavigationDelegate>
+
+@property(nonatomic, assign) GaiaAuthFetcherIOSWKWebViewBridge* bridge;
+
+@end
+
+@implementation GaiaAuthFetcherNavigationDelegate
+
+- (instancetype)initWithBridge:(GaiaAuthFetcherIOSWKWebViewBridge*)bridge {
+  self = [super init];
+  if (self) {
+    _bridge = bridge;
+  }
+  return self;
+}
+
+- (void)javascriptCompletionWithResult:(NSString*)result error:(NSError*)error {
+  if (error || !result) {
+    DVLOG(1) << "Gaia fetcher extract body failed:"
+             << base::SysNSStringToUTF8(error.localizedDescription);
+    // WKWebViewNavigationDelegate API doesn't give any way to get the HTTP
+    // response code of a navigation. Default to 500 for error.
+    self.bridge->OnURLFetchFailure(net::ERR_FAILED, 500);
+  } else {
+    DCHECK([result isKindOfClass:[NSString class]]);
+    // WKWebViewNavigationDelegate API doesn't give any way to get
+    // the HTTP response code of a navigation. Default to 200 for
+    // success.
+    self.bridge->OnURLFetchSuccess(base::SysNSStringToUTF8(result), 200);
+  }
+}
+
+#pragma mark WKNavigationDelegate
+
+- (void)webView:(WKWebView*)webView
+    didFailNavigation:(WKNavigation*)navigation
+            withError:(NSError*)error {
+  DVLOG(1) << "Gaia fetcher navigation failed: "
+           << base::SysNSStringToUTF8(error.localizedDescription);
+  self.bridge->OnURLFetchFailure(net::ERR_FAILED, 500);
+}
+
+- (void)webView:(WKWebView*)webView
+    didFailProvisionalNavigation:(WKNavigation*)navigation
+                       withError:(NSError*)error {
+  DVLOG(1) << "Gaia fetcher provisional navigation failed: "
+           << base::SysNSStringToUTF8(error.localizedDescription);
+  self.bridge->OnURLFetchFailure(net::ERR_FAILED, 500);
+}
+
+- (void)webView:(WKWebView*)webView
+    didFinishNavigation:(WKNavigation*)navigation {
+  // A WKNavigation is an opaque object. The only way to access the body of the
+  // response is via Javascript.
+  DVLOG(2) << "WKWebView loaded:" << net::GURLWithNSURL(webView.URL);
+  __weak __typeof(self) weakSelf = self;
+  [webView evaluateJavaScript:kReadResponseTemplate
+            completionHandler:^(NSString* result, NSError* error) {
+              [weakSelf javascriptCompletionWithResult:result error:error];
+            }];
+}
+
+@end
+
+#pragma mark - GaiaAuthFetcherIOSWKWebViewBridge
+
+GaiaAuthFetcherIOSWKWebViewBridge::GaiaAuthFetcherIOSWKWebViewBridge(
+    GaiaAuthFetcherIOSBridge::GaiaAuthFetcherIOSBridgeDelegate* delegate,
+    web::BrowserState* browser_state)
+    : GaiaAuthFetcherIOSBridge(delegate, browser_state) {
+  ActiveStateManager::FromBrowserState(GetBrowserState())->AddObserver(this);
+}
+
+GaiaAuthFetcherIOSWKWebViewBridge::~GaiaAuthFetcherIOSWKWebViewBridge() {
+  ActiveStateManager::FromBrowserState(GetBrowserState())->RemoveObserver(this);
+  ResetWKWebView();
+}
+
+void GaiaAuthFetcherIOSWKWebViewBridge::Cancel() {
+  if (!GetRequest().pending)
+    return;
+  [GetWKWebView() stopLoading];
+  OnURLFetchFailure(net::ERR_ABORTED, 500);
+}
+
+void GaiaAuthFetcherIOSWKWebViewBridge::FetchPendingRequest() {
+  if (!GetRequest().pending)
+    return;
+  if (!GetRequest().body.empty() && GetRequest().should_use_xml_http_request) {
+    DoPostRequest(GetWKWebView(), GetRequest().body, GetRequest().headers,
+                  GetRequest().url);
+  } else {
+    [GetWKWebView() loadRequest:GetNSURLRequest()];
+  }
+}
+
+WKWebView* GaiaAuthFetcherIOSWKWebViewBridge::GetWKWebView() {
+  if (!ActiveStateManager::FromBrowserState(GetBrowserState())->IsActive()) {
+    // |GetBrowserState()| is not active, WKWebView linked to this browser state
+    // should not exist or be created.
+    return nil;
+  }
+  if (!web_view_) {
+    web_view_ = BuildWKWebView();
+    navigation_delegate_ =
+        [[GaiaAuthFetcherNavigationDelegate alloc] initWithBridge:this];
+    [web_view_ setNavigationDelegate:navigation_delegate_];
+  }
+  return web_view_;
+}
+
+void GaiaAuthFetcherIOSWKWebViewBridge::ResetWKWebView() {
+  [web_view_ setNavigationDelegate:nil];
+  [web_view_ stopLoading];
+  web_view_ = nil;
+  navigation_delegate_ = nil;
+}
+
+WKWebView* GaiaAuthFetcherIOSWKWebViewBridge::BuildWKWebView() {
+  return web::BuildWKWebView(CGRectZero, GetBrowserState());
+}
+
+void GaiaAuthFetcherIOSWKWebViewBridge::OnActive() {
+  // |GetBrowserState()| is now active. If there is a pending request, restart
+  // it.
+  FetchPendingRequest();
+}
+
+void GaiaAuthFetcherIOSWKWebViewBridge::OnInactive() {
+  // |GetBrowserState()| is now inactive. Stop using |web_view_| and don't
+  // create a new one until it is active.
+  ResetWKWebView();
+}
diff --git a/ios/chrome/browser/sync/BUILD.gn b/ios/chrome/browser/sync/BUILD.gn
index 1f9e4e0..ed8779f 100644
--- a/ios/chrome/browser/sync/BUILD.gn
+++ b/ios/chrome/browser/sync/BUILD.gn
@@ -108,6 +108,7 @@
     "//ios/chrome/browser/signin",
     "//ios/chrome/common",
     "//ios/web",
+    "//ui/base",
   ]
   public_deps = [
     "//testing/gmock",
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
index 860b43ae..c6acf36 100644
--- a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
@@ -11,12 +11,14 @@
 #include "base/bind_helpers.h"
 #include "components/browser_sync/profile_sync_service_mock.h"
 #include "components/browser_sync/profile_sync_test_util.h"
+#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/signin/identity_manager_factory.h"
 #include "ios/chrome/browser/sync/ios_chrome_sync_client.h"
 #include "ios/chrome/common/channel_info.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/device_form_factor.h"
 
 browser_sync::ProfileSyncService::InitParams
 CreateProfileSyncServiceParamsForTest(
@@ -35,7 +37,10 @@
   init_params.network_time_update_callback = base::DoNothing();
   init_params.url_loader_factory = browser_state->GetSharedURLLoaderFactory();
   init_params.debug_identifier = browser_state->GetDebugName();
-  init_params.channel = ::GetChannel();
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          ::GetChannel(), ::GetVersionString(),
+          ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
 
   return init_params;
 }
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 3d4fc3c..b2967c7 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -70,7 +70,6 @@
 #include "ios/chrome/common/channel_info.h"
 #include "ios/web/public/web_task_traits.h"
 #include "ios/web/public/web_thread.h"
-#include "ui/base/device_form_factor.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -114,9 +113,7 @@
   // Component factory may already be set in tests.
   if (!GetSyncApiComponentFactory()) {
     component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl(
-        this, ::GetChannel(), ::GetVersionString(),
-        ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET,
-        prefs::kSavingBrowserHistoryDisabled,
+        this, ::GetChannel(), prefs::kSavingBrowserHistoryDisabled,
         base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}),
         db_thread_, profile_web_data_service_, account_web_data_service_,
         password_store_,
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory.cc b/ios/chrome/browser/sync/profile_sync_service_factory.cc
index 882b9d5..42c06cf 100644
--- a/ios/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/ios/chrome/browser/sync/profile_sync_service_factory.cc
@@ -15,6 +15,7 @@
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/network_time/network_time_tracker.h"
 #include "components/signin/core/browser/device_id_helper.h"
+#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/driver/startup_controller.h"
 #include "components/sync/driver/sync_util.h"
 #include "ios/chrome/browser/application_context.h"
@@ -43,6 +44,7 @@
 #include "ios/web/public/web_task_traits.h"
 #include "ios/web/public/web_thread.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/device_form_factor.h"
 #include "url/gurl.h"
 
 using browser_sync::ProfileSyncService;
@@ -151,7 +153,10 @@
   init_params.network_connection_tracker =
       GetApplicationContext()->GetNetworkConnectionTracker();
   init_params.debug_identifier = browser_state->GetDebugName();
-  init_params.channel = ::GetChannel();
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          ::GetChannel(), ::GetVersionString(),
+          ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
 
   bool use_fcm_invalidations =
       base::FeatureList::IsEnabled(invalidation::switches::kFCMInvalidations);
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
index eb557276..f0cbd93 100644
--- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
+++ b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
@@ -13,10 +13,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-const CGFloat kAccessoryWidth = 40;
-}  // namespace
-
 @implementation ImportDataMultilineDetailItem
 
 @synthesize accessoryType = _accessoryType;
@@ -103,10 +99,10 @@
   // is set.
   self.detailTextLabel.preferredMaxLayoutWidth =
       self.bounds.size.width -
-      (kAccessoryWidth + 2 * kTableViewHorizontalSpacing);
+      (kTableViewAccessoryWidth + 2 * kTableViewHorizontalSpacing);
   self.textLabel.preferredMaxLayoutWidth =
       self.bounds.size.width -
-      (kAccessoryWidth + 2 * kTableViewHorizontalSpacing);
+      (kTableViewAccessoryWidth + 2 * kTableViewHorizontalSpacing);
   [super layoutSubviews];
 }
 
diff --git a/ios/chrome/browser/ui/settings/settings_root_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_collection_view_controller.mm
index 4dd6741..fe1c263 100644
--- a/ios/chrome/browser/ui/settings/settings_root_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_root_collection_view_controller.mm
@@ -71,6 +71,14 @@
   }
 }
 
+- (UIViewController*)childViewControllerForStatusBarHidden {
+  return nil;
+}
+
+- (UIViewController*)childViewControllerForStatusBarStyle {
+  return nil;
+}
+
 - (UIBarButtonItem*)doneButtonIfNeeded {
   if (self.shouldHideDoneButton) {
     return nil;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h
index 3241ab1..5e138dea0 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h
@@ -32,6 +32,9 @@
 // Spacing between text label and cell contentView.
 extern const CGFloat kTableViewLabelVerticalTopSpacing;
 
+// The width taken by the accessory view when it is displayed.
+extern const CGFloat kTableViewAccessoryWidth;
+
 // Hex Value for blue label text color.
 extern const int kTableViewTextLabelColorBlue;
 
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm
index 930d190..6d1976c 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm
@@ -16,6 +16,7 @@
 const CGFloat kTableViewCellSelectionAnimationDuration = 0.15;
 const CGFloat kUseDefaultFontSize = 0.0;
 const CGFloat kTableViewLabelVerticalTopSpacing = 13.0;
+const CGFloat kTableViewAccessoryWidth = 40;
 
 const int kTableViewTextLabelColorBlue = 0x1A73E8;
 const int kTableViewTextLabelColorLightGrey = 0x6D6D72;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm
index 3191a8d..4c18f23 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.mm
@@ -167,4 +167,19 @@
   }
 }
 
+- (void)layoutSubviews {
+  if (UIContentSizeCategoryIsAccessibilityCategory(
+          self.traitCollection.preferredContentSizeCategory)) {
+    // Make sure that the multiline labels width isn't changed when the
+    // accessory is set.
+    self.detailTextLabel.preferredMaxLayoutWidth =
+        self.bounds.size.width -
+        (kTableViewAccessoryWidth + 2 * kTableViewHorizontalSpacing);
+    self.textLabel.preferredMaxLayoutWidth =
+        self.bounds.size.width -
+        (kTableViewAccessoryWidth + 2 * kTableViewHorizontalSpacing);
+  }
+  [super layoutSubviews];
+}
+
 @end
diff --git a/ios/web_view/internal/sync/OWNERS b/ios/web_view/internal/sync/OWNERS
index ed365631..51a1f08 100644
--- a/ios/web_view/internal/sync/OWNERS
+++ b/ios/web_view/internal/sync/OWNERS
@@ -1,6 +1,8 @@
 ichikawa@chromium.org
 jzw@chromium.org
 
+file://components/sync/OWNERS
+
 # These are for the common case of adding or renaming files. If you're doing
 # structural changes, please get a review from an OWNER.
 per-file BUILD.gn=*
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
index 90676901..2ebf2164 100644
--- a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
+++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -20,6 +20,7 @@
 #include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h"
 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h"
+#include "components/sync/device_info/local_device_info_provider_mock.h"
 #include "components/sync/driver/fake_sync_client.h"
 #include "components/sync/driver/sync_service_observer.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -74,6 +75,8 @@
     init_params.network_time_update_callback = base::DoNothing();
     init_params.signin_scoped_device_id_callback = base::BindRepeating(
         &signin::GetSigninScopedDeviceId, browser_state_.GetPrefs());
+    init_params.local_device_info_provider =
+        std::make_unique<syncer::LocalDeviceInfoProviderMock>();
     profile_sync_service_ =
         std::make_unique<browser_sync::ProfileSyncServiceMock>(
             std::move(init_params));
diff --git a/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm b/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
index a6fded4..5867b39 100644
--- a/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
+++ b/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
@@ -14,8 +14,10 @@
 #include "components/signin/core/browser/device_id_helper.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/driver/startup_controller.h"
 #include "components/sync/driver/sync_util.h"
+#include "components/version_info/version_info.h"
 #include "ios/web/public/web_thread.h"
 #include "ios/web_view/internal/app/application_context.h"
 #include "ios/web_view/internal/autofill/web_view_personal_data_manager_factory.h"
@@ -30,6 +32,7 @@
 #include "ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.h"
 #include "services/identity/public/cpp/identity_manager.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/device_form_factor.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -97,6 +100,10 @@
       WebViewProfileInvalidationProviderFactory::GetForBrowserState(
           browser_state)
           ->GetIdentityProvider());
+  init_params.local_device_info_provider =
+      std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          version_info::Channel::UNKNOWN, version_info::GetVersionNumber(),
+          ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET);
 
   auto profile_sync_service =
       std::make_unique<ProfileSyncService>(std::move(init_params));
diff --git a/ios/web_view/internal/sync/web_view_sync_client.mm b/ios/web_view/internal/sync/web_view_sync_client.mm
index 4c014d2..6913efb 100644
--- a/ios/web_view/internal/sync/web_view_sync_client.mm
+++ b/ios/web_view/internal/sync/web_view_sync_client.mm
@@ -40,7 +40,6 @@
 #import "ios/web_view/internal/sync/web_view_profile_invalidation_provider_factory.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
 #include "ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.h"
-#include "ui/base/device_form_factor.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -80,8 +79,7 @@
       browser_state_, ServiceAccessType::IMPLICIT_ACCESS);
 
   component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl(
-      this, version_info::Channel::UNKNOWN, version_info::GetVersionNumber(),
-      ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET,
+      this, version_info::Channel::UNKNOWN,
       prefs::kSavingBrowserHistoryDisabled,
       base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}),
       db_thread_, profile_web_data_service_, account_web_data_service_,
diff --git a/ios/web_view/tools/build.py b/ios/web_view/tools/build.py
index 40fb124..ecffe84 100755
--- a/ios/web_view/tools/build.py
+++ b/ios/web_view/tools/build.py
@@ -226,6 +226,9 @@
     extra_gn_options += 'ios_web_view_include_cronet=false '
   if options.enable_sync:
     extra_gn_options += 'ios_web_view_enable_sync=true '
+    # Used to differentiate //ios/web_view from //ios/chrome in the user agent
+    # product string passed to sync servers.
+    extra_gn_options += 'sync_user_agent_product="ChromeWebView" '
   else:
     extra_gn_options += 'ios_web_view_enable_sync=false '
   if options.enable_autofill:
diff --git a/media/audio/mac/audio_device_listener_mac.cc b/media/audio/mac/audio_device_listener_mac.cc
index f36c3eb..bccd5e6 100644
--- a/media/audio/mac/audio_device_listener_mac.cc
+++ b/media/audio/mac/audio_device_listener_mac.cc
@@ -133,6 +133,8 @@
     RemovePropertyListener(default_input_listener_.get());
   if (addition_removal_listener_)
     RemovePropertyListener(addition_removal_listener_.get());
+  for (const auto& entry : source_listeners_)
+    RemovePropertyListener(entry.second.get());
 }
 
 bool AudioDeviceListenerMac::AddPropertyListener(
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
index c0d849a..7032a2d 100644
--- a/media/gpu/v4l2/v4l2_device.cc
+++ b/media/gpu/v4l2/v4l2_device.cc
@@ -1216,6 +1216,43 @@
 }
 
 // static
+std::string V4L2Device::V4L2BufferToString(const struct v4l2_buffer& buffer) {
+  std::ostringstream s;
+  s << "v4l2_buffer type: " << buffer.type << ", memory: " << buffer.memory
+    << ", index: " << buffer.index << " bytesused: " << buffer.bytesused
+    << ", length: " << buffer.length;
+  if (buffer.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+      buffer.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+    //  single-planar
+    if (buffer.memory == V4L2_MEMORY_MMAP) {
+      s << ", m.offset: " << buffer.m.offset;
+    } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
+      s << ", m.userptr: " << buffer.m.userptr;
+    } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
+      s << ", m.fd: " << buffer.m.fd;
+    }
+  } else if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) {
+    for (size_t i = 0; i < buffer.length; ++i) {
+      const struct v4l2_plane& plane = buffer.m.planes[i];
+      s << ", m.planes[" << i << "](bytesused: " << plane.bytesused
+        << ", length: " << plane.length
+        << ", data_offset: " << plane.data_offset;
+      if (buffer.memory == V4L2_MEMORY_MMAP) {
+        s << ", m.mem_offset: " << plane.m.mem_offset;
+      } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
+        s << ", m.userptr: " << plane.m.userptr;
+      } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
+        s << ", m.fd: " << plane.m.fd;
+      }
+      s << ")";
+    }
+  } else {
+    s << " unsupported yet.";
+  }
+  return s.str();
+}
+
+// static
 base::Optional<VideoFrameLayout> V4L2Device::V4L2FormatToVideoFrameLayout(
     const struct v4l2_format& format) {
   if (!V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h
index e7bda8d5..c37635ab 100644
--- a/media/gpu/v4l2/v4l2_device.h
+++ b/media/gpu/v4l2/v4l2_device.h
@@ -310,6 +310,9 @@
   // Composes human readable string of v4l2_format.
   static std::string V4L2FormatToString(const struct v4l2_format& format);
 
+  // Composes human readable string of v4l2_buffer.
+  static std::string V4L2BufferToString(const struct v4l2_buffer& buffer);
+
   // Composes VideoFrameLayout based on v4l2_format.
   // If error occurs, it returns base::nullopt.
   static base::Optional<VideoFrameLayout> V4L2FormatToVideoFrameLayout(
diff --git a/media/gpu/v4l2/v4l2_image_processor.cc b/media/gpu/v4l2/v4l2_image_processor.cc
index c0a5835..77ffa63 100644
--- a/media/gpu/v4l2/v4l2_image_processor.cc
+++ b/media/gpu/v4l2/v4l2_image_processor.cc
@@ -860,6 +860,7 @@
         return false;
     }
   }
+  DVLOGF(4) << "Calling VIDIOC_QBUF: " << V4L2Device::V4L2BufferToString(qbuf);
   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
   input_record.at_device = true;
 
@@ -900,6 +901,8 @@
   }
   qbuf.m.planes = qbuf_planes;
   qbuf.length = output_layout_.num_buffers();
+
+  DVLOGF(4) << "Calling VIDIOC_QBUF: " << V4L2Device::V4L2BufferToString(qbuf);
   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
   output_record.at_device = true;
   output_buffer_queued_count_++;
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 43771ad..cba9a95 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -895,6 +895,7 @@
   qbuf.memory = input_memory_type_;
   qbuf.length = input_planes_count_;
 
+  DVLOGF(4) << "Calling VIDIOC_QBUF: " << V4L2Device::V4L2BufferToString(qbuf);
   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
   input_record.at_device = true;
   input_record.frame = frame;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index d2844a9..8f0a9ab 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -3143,6 +3143,12 @@
     "quic/mock_encrypter.h",
     "quic/test_task_runner.cc",
     "quic/test_task_runner.h",
+    "third_party/quic/core/qpack/qpack_decoder_test_utils.cc",
+    "third_party/quic/core/qpack/qpack_decoder_test_utils.h",
+    "third_party/quic/core/qpack/qpack_encoder_test_utils.cc",
+    "third_party/quic/core/qpack/qpack_encoder_test_utils.h",
+    "third_party/quic/core/qpack/qpack_test_utils.cc",
+    "third_party/quic/core/qpack/qpack_test_utils.h",
     "third_party/quic/core/quic_trace_visitor.cc",
     "third_party/quic/core/quic_trace_visitor.h",
     "third_party/quic/platform/api/quic_expect_bug.h",
@@ -5084,20 +5090,14 @@
     "third_party/quic/core/legacy_quic_stream_id_manager_test.cc",
     "third_party/quic/core/packet_number_indexed_queue_test.cc",
     "third_party/quic/core/qpack/qpack_decoder_test.cc",
-    "third_party/quic/core/qpack/qpack_decoder_test_utils.cc",
-    "third_party/quic/core/qpack/qpack_decoder_test_utils.h",
     "third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc",
     "third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc",
     "third_party/quic/core/qpack/qpack_encoder_test.cc",
-    "third_party/quic/core/qpack/qpack_encoder_test_utils.cc",
-    "third_party/quic/core/qpack/qpack_encoder_test_utils.h",
     "third_party/quic/core/qpack/qpack_header_table_test.cc",
     "third_party/quic/core/qpack/qpack_instruction_decoder_test.cc",
     "third_party/quic/core/qpack/qpack_instruction_encoder_test.cc",
     "third_party/quic/core/qpack/qpack_round_trip_test.cc",
     "third_party/quic/core/qpack/qpack_static_table_test.cc",
-    "third_party/quic/core/qpack/qpack_test_utils.cc",
-    "third_party/quic/core/qpack/qpack_test_utils.h",
     "third_party/quic/core/quic_alarm_test.cc",
     "third_party/quic/core/quic_arena_scoped_ptr_test.cc",
     "third_party/quic/core/quic_bandwidth_test.cc",
@@ -6322,3 +6322,55 @@
   ]
   dict = "data/fuzzer_dictionaries/net_uri_template_fuzzer.dict"
 }
+
+fuzzer_test("net_qpack_decoder_fuzzer") {
+  sources = [
+    "third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    ":quic_test_tools",
+    "//base",
+    "//net",
+  ]
+  seed_corpus =
+      "third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer_corpus/"
+}
+
+fuzzer_test("net_qpack_encoder_stream_receiver_fuzzer") {
+  sources = [
+    "third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    "//base",
+    "//net",
+  ]
+  seed_corpus = "third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer_corpus/"
+}
+
+fuzzer_test("net_qpack_encoder_stream_sender_fuzzer") {
+  sources = [
+    "third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    "//base",
+    "//net",
+  ]
+  seed_corpus = "third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer_corpus/"
+}
+
+fuzzer_test("net_qpack_round_trip_fuzzer") {
+  sources = [
+    "third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc",
+  ]
+  deps = [
+    ":net_fuzzer_test_support",
+    ":quic_test_tools",
+    "//base",
+    "//net",
+  ]
+  seed_corpus =
+      "third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer_corpus/"
+}
diff --git a/net/third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer.cc b/net/third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer.cc
index 2485805..4ddea875 100644
--- a/net/third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer.cc
+++ b/net/third_party/quic/core/qpack/fuzzer/qpack_decoder_fuzzer.cc
@@ -39,12 +39,11 @@
   // Process up to 64 kB fragments at a time.  Too small upper bound might not
   // provide enough coverage, too large would make fuzzing less efficient.
   auto fragment_size_generator =
-      std::bind(&QuicFuzzedDataProvider::ConsumeIntegralInRange<uint32_t>,
-                &provider, 1, 64 * 1024);
+      std::bind(&QuicFuzzedDataProvider::ConsumeIntegralInRange<uint16_t>,
+                &provider, 1, std::numeric_limits<uint16_t>::max());
 
-  QpackDecode(
-      &handler, fragment_size_generator,
-      provider.ConsumeRandomLengthString(std::numeric_limits<size_t>::max()));
+  QpackDecode(&handler, fragment_size_generator,
+              provider.ConsumeRemainingBytesAsString());
 
   return 0;
 }
diff --git a/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc b/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
index 766cb549..5869e6e 100644
--- a/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
+++ b/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
@@ -55,7 +55,8 @@
   while (!delegate.error_detected() && provider.remaining_bytes() != 0) {
     // Process up to 64 kB fragments at a time.  Too small upper bound might not
     // provide enough coverage, too large might make fuzzing too inefficient.
-    size_t fragment_size = provider.ConsumeUint32InRange(1, 64 * 1024);
+    size_t fragment_size = provider.ConsumeIntegralInRange<uint16_t>(
+        1, std::numeric_limits<uint16_t>::max());
     receiver.Decode(provider.ConsumeRandomLengthString(fragment_size));
   }
 
diff --git a/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc b/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
index 1f099cc..24f339bf 100644
--- a/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
+++ b/net/third_party/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
@@ -35,40 +35,37 @@
 
   QuicFuzzedDataProvider provider(data, size);
   // Limit string literal length to 2 kB for efficiency.
-  const uint32_t kMaxStringLength = 2048;
+  const uint16_t kMaxStringLength = 2048;
 
   while (provider.remaining_bytes() != 0) {
-    switch (provider.ConsumeUint8() % 4) {
+    switch (provider.ConsumeIntegral<uint8_t>() % 4) {
       case 0: {
         bool is_static = provider.ConsumeBool();
-        uint64_t name_index = provider.ConsumeUint32InRange(
-            0, std::numeric_limits<uint32_t>::max());
-        uint32_t value_length =
-            provider.ConsumeUint32InRange(0, kMaxStringLength);
+        uint64_t name_index = provider.ConsumeIntegral<uint64_t>();
+        uint16_t value_length =
+            provider.ConsumeIntegralInRange<uint16_t>(0, kMaxStringLength);
         QuicString value = provider.ConsumeRandomLengthString(value_length);
 
         sender.SendInsertWithNameReference(is_static, name_index, value);
         break;
       }
       case 1: {
-        uint32_t name_length =
-            provider.ConsumeUint32InRange(0, kMaxStringLength);
+        uint16_t name_length =
+            provider.ConsumeIntegralInRange<uint16_t>(0, kMaxStringLength);
         QuicString name = provider.ConsumeRandomLengthString(name_length);
-        uint32_t value_length =
-            provider.ConsumeUint32InRange(0, kMaxStringLength);
+        uint16_t value_length =
+            provider.ConsumeIntegralInRange<uint16_t>(0, kMaxStringLength);
         QuicString value = provider.ConsumeRandomLengthString(value_length);
         sender.SendInsertWithoutNameReference(name, value);
         break;
       }
       case 2: {
-        uint64_t index = provider.ConsumeUint32InRange(
-            0, std::numeric_limits<uint32_t>::max());
+        uint64_t index = provider.ConsumeIntegral<uint64_t>();
         sender.SendDuplicate(index);
         break;
       }
       case 3: {
-        uint64_t max_size = provider.ConsumeUint32InRange(
-            0, std::numeric_limits<uint32_t>::max());
+        uint64_t max_size = provider.ConsumeIntegral<uint64_t>();
         sender.SendDynamicTableSizeUpdate(max_size);
         break;
       }
diff --git a/net/third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc b/net/third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc
index 8891fc4a..f29d230 100644
--- a/net/third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc
+++ b/net/third_party/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc
@@ -120,8 +120,8 @@
   // Process up to 64 kB fragments at a time.  Too small upper bound might not
   // provide enough coverage, too large would make fuzzing less efficient.
   auto fragment_size_generator =
-      std::bind(&QuicFuzzedDataProvider::ConsumeIntegralInRange<uint32_t>,
-                &provider, 1, 64 * 1024);
+      std::bind(&QuicFuzzedDataProvider::ConsumeIntegralInRange<uint16_t>,
+                &provider, 1, std::numeric_limits<uint16_t>::max());
 
   // Encode header list.
   QuicString encoded_header_block =
diff --git a/net/third_party/quic/platform/impl/quic_fuzzed_data_provider_impl.h b/net/third_party/quic/platform/impl/quic_fuzzed_data_provider_impl.h
new file mode 100644
index 0000000..ddbd832
--- /dev/null
+++ b/net/third_party/quic/platform/impl/quic_fuzzed_data_provider_impl.h
@@ -0,0 +1,16 @@
+// Copyright 2018 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 NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_FUZZED_DATA_PROVIDER_IMPL_H_
+#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_FUZZED_DATA_PROVIDER_IMPL_H_
+
+#include "base/test/fuzzed_data_provider.h"
+
+namespace quic {
+
+using QuicFuzzedDataProviderImpl = base::FuzzedDataProvider;
+
+}  // namespace quic
+
+#endif  // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_FUZZED_DATA_PROVIDER_IMPL_H_
diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h
index 3044118fd..e670d36c 100644
--- a/ppapi/shared_impl/resource.h
+++ b/ppapi/shared_impl/resource.h
@@ -116,7 +116,8 @@
 // cases.
 enum ResourceObjectType { OBJECT_IS_IMPL, OBJECT_IS_PROXY };
 
-class PPAPI_SHARED_EXPORT Resource : public base::RefCounted<Resource> {
+class PPAPI_SHARED_EXPORT Resource
+    : public base::RefCountedThreadSafe<Resource> {
  public:
   // Constructor for impl and non-proxied, instance-only objects.
   //
diff --git a/services/identity/public/cpp/primary_account_mutator.h b/services/identity/public/cpp/primary_account_mutator.h
index fe890d8..c4a5f12 100644
--- a/services/identity/public/cpp/primary_account_mutator.h
+++ b/services/identity/public/cpp/primary_account_mutator.h
@@ -64,11 +64,6 @@
   virtual bool IsSettingPrimaryAccountAllowed() const = 0;
   virtual void SetSettingPrimaryAccountAllowed(bool allowed) = 0;
 
-  // Getter and setter that allow enabling or disabling the ability to clear
-  // the primary account.
-  virtual bool IsClearingPrimaryAccountAllowed() const = 0;
-  virtual void SetClearingPrimaryAccountAllowed(bool allowed) = 0;
-
   // Sets the pattern controlling which user names are allowed when setting
   // the primary account.
   virtual void SetAllowedPrimaryAccountPattern(const std::string& pattern) = 0;
diff --git a/services/identity/public/cpp/primary_account_mutator_impl.cc b/services/identity/public/cpp/primary_account_mutator_impl.cc
index 84380cf..3b544c3 100644
--- a/services/identity/public/cpp/primary_account_mutator_impl.cc
+++ b/services/identity/public/cpp/primary_account_mutator_impl.cc
@@ -47,8 +47,6 @@
       !LegacyIsPrimaryAccountAuthInProgress())
     return false;
 
-  // TODO: report failure if SignOut is not allowed.
-
   switch (action) {
     case PrimaryAccountMutator::ClearAccountsAction::kDefault:
       signin_manager_->SignOut(source_metric, delete_metric);
@@ -73,15 +71,6 @@
   signin_manager_->SetSigninAllowed(allowed);
 }
 
-bool PrimaryAccountMutatorImpl::IsClearingPrimaryAccountAllowed() const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-void PrimaryAccountMutatorImpl::SetClearingPrimaryAccountAllowed(bool allowed) {
-  NOTIMPLEMENTED();
-}
-
 void PrimaryAccountMutatorImpl::SetAllowedPrimaryAccountPattern(
     const std::string& pattern) {
   NOTIMPLEMENTED();
diff --git a/services/identity/public/cpp/primary_account_mutator_impl.h b/services/identity/public/cpp/primary_account_mutator_impl.h
index 912e700..8df5aea 100644
--- a/services/identity/public/cpp/primary_account_mutator_impl.h
+++ b/services/identity/public/cpp/primary_account_mutator_impl.h
@@ -28,8 +28,6 @@
       signin_metrics::SignoutDelete delete_metric) override;
   bool IsSettingPrimaryAccountAllowed() const override;
   void SetSettingPrimaryAccountAllowed(bool allowed) override;
-  bool IsClearingPrimaryAccountAllowed() const override;
-  void SetClearingPrimaryAccountAllowed(bool allowed) override;
   void SetAllowedPrimaryAccountPattern(const std::string& pattern) override;
   void LegacyStartSigninWithRefreshTokenForPrimaryAccount(
       const std::string& refresh_token,
diff --git a/services/network/public/cpp/url_request.typemap b/services/network/public/cpp/url_request.typemap
index 00e3bc1..07b5a99d 100644
--- a/services/network/public/cpp/url_request.typemap
+++ b/services/network/public/cpp/url_request.typemap
@@ -13,5 +13,6 @@
 ]
 type_mappings = [
   "network.mojom.URLRequest=network::ResourceRequest",
+  "network.mojom.URLRequestBody=scoped_refptr<network::ResourceRequestBody>",
   "network.mojom.RequestPriority=net::RequestPriority",
 ]
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index f4ee750..e55427a 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -12,6 +12,9 @@
 struct URLRequest;
 
 [Native]
+struct URLRequestBody;
+
+[Native]
 struct URLResponseHead;
 
 [Native]
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d8065d4..7270010 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4357,7 +4357,8 @@
                 {
                     "name": "Enabled",
                     "enable_features": [
-                        "BlinkMainThreadUsesSequenceManager"
+                        "BlinkMainThreadUsesSequenceManager",
+                        "MessageLoopUsesSequenceManager"
                     ]
                 }
             ]
diff --git a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
index c589f80..5e6fd9f 100644
--- a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
+++ b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -4,8 +4,10 @@
 
 module blink.mojom;
 
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/fetch_api.mojom";
 import "services/network/public/mojom/request_context_frame_type.mojom";
+import "services/network/public/mojom/url_loader.mojom";
 import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
 import "third_party/blink/public/mojom/referrer.mojom";
 import "url/mojom/url.mojom";
@@ -106,6 +108,15 @@
   map<string, string> headers;
 };
 
+// Struct representing a Request:
+// https://fetch.spec.whatwg.org/#request-class
+// Compared to network.mojom.URLRequest which is kind of internal data in the
+// loading stack, FetchAPIRequest acts as a direct representation of the JS
+// Request object in all API implementations like Background Fetch, Cache
+// Storage and Service Worker, with no need to care how the loading logic
+// happens.
+// Note: When updating this struct, also update
+// content/common/fetch/fetch_request_type_converters.cc.
 struct FetchAPIRequest {
   network.mojom.FetchRequestMode mode = network.mojom.FetchRequestMode.kNoCors;
   bool is_main_resource_load = false;
@@ -115,7 +126,17 @@
   url.mojom.Url url;
   string method;
   FetchAPIRequestHeaders headers;
+
+  // Note: |blob| and |body| are mutually exclusive.
+  // |blob| is used in implementing Background Fetch APIs, also used to
+  // represent the FetchEvent#request#body dispatched to service workers for
+  // non-S13nServiceWorker case.
+  // |body| is used only to represent the FetchEvent#request#body dispatched to
+  // service workers for S13nServiceWorker case.
+  // TODO(crbug.com/911930): Remove |blob| and use |body| instead everywhere.
   SerializedBlob? blob;
+  network.mojom.URLRequestBody? body;
+
   Referrer? referrer;
   network.mojom.FetchCredentialsMode credentials_mode =
     network.mojom.FetchCredentialsMode.kOmit;
@@ -123,6 +144,12 @@
   network.mojom.FetchRedirectMode redirect_mode =
     network.mojom.FetchRedirectMode.kFollow;
   string? integrity;
+  network.mojom.RequestPriority priority = network.mojom.RequestPriority.kIdle;
+
+  // Id of the original requestor window.
+  // See network::ResourceRequest::fetch_window_id.
+  mojo_base.mojom.UnguessableToken? fetch_window_id;
+
   bool keepalive = false;
   string? client_id;
   bool is_reload = false;
diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
index 21cc715..1fc679a 100644
--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
@@ -6,6 +6,7 @@
 
 import "services/network/public/mojom/url_loader.mojom";
 import "third_party/blink/public/mojom/blob/blob.mojom";
+import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
 
 // Used for service worker navigation preload, to create
 // FetchEvent#preloadResponse.
@@ -17,28 +18,25 @@
 // Parameters used for dispatching a FetchEvent.
 struct DispatchFetchEventParams {
   // FetchEvent#request.
-  network.mojom.URLRequest request;
+  FetchAPIRequest request;
 
   // The following fields are used to create FetchEvent#request#body, depending
   // on whether S13nServiceWorker/NetworkService are enabled.
 
   // (A) S13nServiceWorker with NetworkService on:
-  // All information about the request body is provided in
-  // |request.request_body|.
+  // All information about the request body is provided in |request.body|, and
+  // |request.blob| is null.
 
   // (B) S13nServiceWorker with NetworkService off:
   // All information about the request body except for BlobPtrs is provided in
-  // |request.request_body|. These BlobPtrs need to be passed separately.
+  // |request.body|. These BlobPtrs need to be passed separately.
   // Once the NetworkService is enabled, this will be no longer used since all
-  // Blobs are passed as data pipes which can live in |request.request_body|.
+  // Blobs are passed as data pipes which can live in |request.body|.
   array<Blob> request_body_blob_ptrs;
 
   // (C) non-S13nServiceWorker:
-  // All information to create the request body are packed into a blob. These
-  // params are for passing the blob.
-  string request_body_blob_uuid;
-  uint64 request_body_blob_size;
-  Blob? request_body_blob;
+  // All information to create the request body is packed into |request.blob|,
+  // and |request.body| is null.
 
   // FetchEvent#clientId.
   string client_id;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index da9b3be..470086f 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -705,12 +705,6 @@
       Platform::Current()->IsTakingV8ContextSnapshot()
           ? V8PerIsolateData::V8ContextSnapshotMode::kTakeSnapshot
           : V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot;
-  if (v8_context_snapshot_mode ==
-          V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot &&
-      !RuntimeEnabledFeatures::V8ContextSnapshotEnabled()) {
-    v8_context_snapshot_mode =
-        V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot;
-  }
 #else
   V8PerIsolateData::V8ContextSnapshotMode v8_context_snapshot_mode =
       V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot;
diff --git a/third_party/blink/renderer/core/html/forms/form_data.cc b/third_party/blink/renderer/core/html/forms/form_data.cc
index f302173..b2b9745 100644
--- a/third_party/blink/renderer/core/html/forms/form_data.cc
+++ b/third_party/blink/renderer/core/html/forms/form_data.cc
@@ -107,7 +107,10 @@
                                       "The form is constructing entry list.");
     return nullptr;
   }
-  return form_data;
+  // Return a shallow copy of |form_data| because |form_data| is visible in
+  // "formdata" event, and the specification says it should be different from
+  // the FormData object to be returned.
+  return MakeGarbageCollected<FormData>(*form_data);
 }
 
 void FormData::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index e2fbc16..08d49cd6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -886,6 +886,14 @@
                                                    style.PaddingBefore());
   padding.block_end = ResolveMarginPaddingLength(percentage_resolution_size,
                                                  style.PaddingAfter());
+
+  if (style.Display() == EDisplay::kTableCell) {
+    // Compatibility hack to mach legacy layout. Legacy layout floors padding on
+    // the block sides, but not on the inline sides. o.O
+    padding.block_start = LayoutUnit(padding.block_start.Floor());
+    padding.block_end = LayoutUnit(padding.block_end.Floor());
+  }
+
   return padding;
 }
 
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
index 580b87f2..1e85daf 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
@@ -131,7 +131,10 @@
 
 mojom::blink::BackgroundFetchService* BackgroundFetchBridge::GetService() {
   if (!background_fetch_service_) {
-    auto request = mojo::MakeRequest(&background_fetch_service_);
+    auto request = mojo::MakeRequest(
+        &background_fetch_service_,
+        GetSupplementable()->GetExecutionContext()->GetTaskRunner(
+            TaskType::kBackgroundFetch));
     if (auto* interface_provider = GetSupplementable()
                                        ->GetExecutionContext()
                                        ->GetInterfaceProvider()) {
diff --git a/third_party/blink/renderer/modules/battery/battery_dispatcher.cc b/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
index 59d0336..aa084b6 100644
--- a/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
+++ b/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
@@ -7,6 +7,7 @@
 #include "services/device/public/mojom/constants.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 
@@ -45,8 +46,9 @@
 
 void BatteryDispatcher::StartListening(LocalFrame* frame) {
   DCHECK(!monitor_.is_bound());
-  Platform::Current()->GetInterfaceProvider()->GetInterface(
-      mojo::MakeRequest(&monitor_));
+  // See https://bit.ly/2S0zRAS for task types.
+  Platform::Current()->GetInterfaceProvider()->GetInterface(mojo::MakeRequest(
+      &monitor_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
   QueryNextStatus();
 }
 
diff --git a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
index 0a5fb57..9e1fa49cc 100644
--- a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
+++ b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
@@ -240,21 +240,33 @@
 
     responses_ = Vector<RequestResponse>(requestSize);
     num_responses_left_ = requestSize;
-    for (const auto& request : requests) {
-      cache_ptr_->Match(
-          request.Clone(), mojom::blink::QueryParams::New(),
-          WTF::Bind(
-              [](scoped_refptr<ResponsesAccumulator> accumulator,
-                 mojom::blink::FetchAPIRequestPtr request,
-                 mojom::blink::MatchResultPtr result) {
-                if (result->is_status()) {
-                  accumulator->SendFailure(result->get_status());
-                } else {
-                  accumulator->AddRequestResponsePair(request,
-                                                      result->get_response());
-                }
-              },
-              scoped_refptr<ResponsesAccumulator>(this), request.Clone()));
+    for (auto& request : requests) {
+      // All FetchAPIRequests in cache_storage code are supposed to not contain
+      // a body.
+      DCHECK(!request->blob && !request->body);
+      auto request_clone_without_body = mojom::blink::FetchAPIRequest::New(
+          request->mode, request->is_main_resource_load,
+          request->request_context_type, request->frame_type, request->url,
+          request->method, request->headers, nullptr /* blob */,
+          nullptr /* body */, request->referrer.Clone(),
+          request->credentials_mode, request->cache_mode,
+          request->redirect_mode, request->integrity, request->priority,
+          request->fetch_window_id, request->keepalive, request->client_id,
+          request->is_reload, request->is_history_navigation);
+      cache_ptr_->Match(std::move(request), mojom::blink::QueryParams::New(),
+                        WTF::Bind(
+                            [](scoped_refptr<ResponsesAccumulator> accumulator,
+                               mojom::blink::FetchAPIRequestPtr request,
+                               mojom::blink::MatchResultPtr result) {
+                              if (result->is_status()) {
+                                accumulator->SendFailure(result->get_status());
+                              } else {
+                                accumulator->AddRequestResponsePair(
+                                    request, result->get_response());
+                              }
+                            },
+                            scoped_refptr<ResponsesAccumulator>(this),
+                            std::move(request_clone_without_body)));
     }
   }
 
diff --git a/third_party/blink/renderer/modules/cookie_store/cookie_store.cc b/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
index ddedfa7..81930536 100644
--- a/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
+++ b/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
@@ -592,8 +592,7 @@
   if (change_listener_binding_ || !backend_)
     return;
 
-  // A specific task source should be defined but not.
-  // See https://wicg.github.io/cookie-store/
+  // See https://bit.ly/2S0zRAS for task types.
   auto task_runner =
       GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
   network::mojom::blink::CookieChangeListenerPtr change_listener;
diff --git a/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc b/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc
index eb378d47..2e80e9b 100644
--- a/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc
+++ b/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc
@@ -20,8 +20,10 @@
     ExecutionContext* execution_context,
     service_manager::InterfaceProvider* interface_provider) {
   network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr;
-  interface_provider->GetInterface(mojo::MakeRequest(&cookie_manager_ptr));
-
+  // See https://bit.ly/2S0zRAS for task types.
+  interface_provider->GetInterface(mojo::MakeRequest(
+      &cookie_manager_ptr,
+      execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
   return CookieStore::Create(execution_context, std::move(cookie_manager_ptr),
                              blink::mojom::blink::CookieStorePtr());
 }
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
index 0245d2c..774efbc 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
@@ -15,9 +15,10 @@
 CredentialManagerProxy::CredentialManagerProxy(Document& document) {
   LocalFrame* frame = document.GetFrame();
   DCHECK(frame);
-  frame->GetInterfaceProvider().GetInterface(&credential_manager_);
   frame->GetInterfaceProvider().GetInterface(
-      mojo::MakeRequest(&authenticator_));
+      &credential_manager_, frame->GetTaskRunner(TaskType::kUserInteraction));
+  frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(
+      &authenticator_, frame->GetTaskRunner(TaskType::kUserInteraction)));
 }
 
 CredentialManagerProxy::~CredentialManagerProxy() {}
diff --git a/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc b/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
index 8524dc4..2c50eae 100644
--- a/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
+++ b/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc
@@ -103,8 +103,10 @@
   }
 
   if (!provider_) {
+    // See https://bit.ly/2S0zRAS for task types.
     GetSupplementable()->GetInterfaceProvider().GetInterface(
-        mojo::MakeRequest(&provider_));
+        mojo::MakeRequest(&provider_, GetExecutionContext()->GetTaskRunner(
+                                          blink::TaskType::kMiscPlatformAPI)));
     // TODO(mgiuca): Set a connection error handler. This requires a refactor to
     // work like NavigatorShare.cpp (retain a persistent list of clients to
     // reject all of their promises).
diff --git a/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc b/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
index 274e38e..b61ce67 100644
--- a/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
+++ b/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
@@ -94,7 +94,9 @@
     if (!frame) {
       return false;
     }
-    frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+    // See https://bit.ly/2S0zRAS for task types.
+    frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(
+        &service_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
     DCHECK(service_);
   }
 
diff --git a/third_party/blink/renderer/modules/locks/lock_manager.cc b/third_party/blink/renderer/modules/locks/lock_manager.cc
index 41191f4..5f0f04b 100644
--- a/third_party/blink/renderer/modules/locks/lock_manager.cc
+++ b/third_party/blink/renderer/modules/locks/lock_manager.cc
@@ -68,8 +68,7 @@
         resolver_(resolver),
         name_(name),
         mode_(mode),
-        // A specific task source should be defined but not.
-        // See https://wicg.github.io/web-locks/.
+        // See https://bit.ly/2S0zRAS for task types.
         binding_(this,
                  std::move(request),
                  manager->GetExecutionContext()->GetTaskRunner(
diff --git a/third_party/blink/renderer/modules/mediasession/media_session.cc b/third_party/blink/renderer/modules/mediasession/media_session.cc
index 11e1099..6173ecf 100644
--- a/third_party/blink/renderer/modules/mediasession/media_session.cc
+++ b/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -199,16 +199,16 @@
   if (!frame)
     return nullptr;
 
-  frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+  // See https://bit.ly/2S0zRAS for task types.
+  auto task_runner =
+      GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
+  frame->GetInterfaceProvider().GetInterface(
+      mojo::MakeRequest(&service_, task_runner));
   if (service_.get()) {
     // Record the eTLD+1 of the frame using the API.
     Platform::Current()->RecordRapporURL("Media.Session.APIUsage.Origin",
                                          document->Url());
     blink::mojom::blink::MediaSessionClientPtr client;
-    // A specific task source should be defined but not.
-    // See https://wicg.github.io/mediasession/.
-    auto task_runner =
-        GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
     client_binding_.Bind(mojo::MakeRequest(&client, task_runner), task_runner);
     service_->SetClient(std::move(client));
   }
diff --git a/third_party/blink/renderer/modules/nfc/nfc.cc b/third_party/blink/renderer/modules/nfc/nfc.cc
index 74ad6c0..f778384 100644
--- a/third_party/blink/renderer/modules/nfc/nfc.cc
+++ b/third_party/blink/renderer/modules/nfc/nfc.cc
@@ -645,8 +645,7 @@
   if (!IsSupportedInContext(GetExecutionContext(), error_message))
     return;
 
-  // A specific task source should be defined but not.
-  // See https://w3c.github.io/web-nfc/.
+  // See https://bit.ly/2S0zRAS for task types.
   auto task_runner = frame->GetTaskRunner(TaskType::kMiscPlatformAPI);
   frame->GetInterfaceProvider().GetInterface(
       mojo::MakeRequest(&nfc_, task_runner));
diff --git a/third_party/blink/renderer/modules/payments/payment_manager.cc b/third_party/blink/renderer/modules/payments/payment_manager.cc
index f9db07d..8d92b02 100644
--- a/third_party/blink/renderer/modules/payments/payment_manager.cc
+++ b/third_party/blink/renderer/modules/payments/payment_manager.cc
@@ -44,8 +44,9 @@
     : registration_(registration), instruments_(nullptr) {
   DCHECK(registration);
 
-  auto request = mojo::MakeRequest(&manager_);
   if (ExecutionContext* context = registration->GetExecutionContext()) {
+    auto request = mojo::MakeRequest(
+        &manager_, context->GetTaskRunner(TaskType::kUserInteraction));
     if (auto* interface_provider = context->GetInterfaceProvider()) {
       interface_provider->GetInterface(std::move(request));
     }
diff --git a/third_party/blink/renderer/modules/permissions/permissions.cc b/third_party/blink/renderer/modules/permissions/permissions.cc
index 137ae641..515613f4 100644
--- a/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -282,7 +282,10 @@
 PermissionService& Permissions::GetService(
     ExecutionContext* execution_context) {
   if (!service_) {
-    ConnectToPermissionService(execution_context, mojo::MakeRequest(&service_));
+    ConnectToPermissionService(
+        execution_context,
+        mojo::MakeRequest(&service_, execution_context->GetTaskRunner(
+                                         TaskType::kPermission)));
     service_.set_connection_error_handler(WTF::Bind(
         &Permissions::ServiceConnectionError, WrapWeakPersistent(this)));
   }
diff --git a/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc b/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
index 13ea6831..2060b0a7 100644
--- a/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
+++ b/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
@@ -22,12 +22,14 @@
 
 BarcodeDetector::BarcodeDetector(ExecutionContext* context) : ShapeDetector() {
   shape_detection::mojom::blink::BarcodeDetectionProviderPtr provider;
-  auto request = mojo::MakeRequest(&provider);
+  // See https://bit.ly/2S0zRAS for task types.
+  auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
+  auto request = mojo::MakeRequest(&provider, task_runner);
   if (auto* interface_provider = context->GetInterfaceProvider()) {
     interface_provider->GetInterface(std::move(request));
   }
   provider->CreateBarcodeDetection(
-      mojo::MakeRequest(&barcode_service_),
+      mojo::MakeRequest(&barcode_service_, task_runner),
       shape_detection::mojom::blink::BarcodeDetectorOptions::New());
 
   barcode_service_.set_connection_error_handler(
diff --git a/third_party/blink/renderer/modules/shapedetection/face_detector.cc b/third_party/blink/renderer/modules/shapedetection/face_detector.cc
index fa7a072..83eef1e 100644
--- a/third_party/blink/renderer/modules/shapedetection/face_detector.cc
+++ b/third_party/blink/renderer/modules/shapedetection/face_detector.cc
@@ -35,11 +35,13 @@
   face_detector_options->fast_mode = options->fastMode();
 
   shape_detection::mojom::blink::FaceDetectionProviderPtr provider;
-  auto request = mojo::MakeRequest(&provider);
+  // See https://bit.ly/2S0zRAS for task types.
+  auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
+  auto request = mojo::MakeRequest(&provider, task_runner);
   if (auto* interface_provider = context->GetInterfaceProvider()) {
     interface_provider->GetInterface(std::move(request));
   }
-  provider->CreateFaceDetection(mojo::MakeRequest(&face_service_),
+  provider->CreateFaceDetection(mojo::MakeRequest(&face_service_, task_runner),
                                 std::move(face_detector_options));
 
   face_service_.set_connection_error_handler(WTF::Bind(
diff --git a/third_party/blink/renderer/modules/shapedetection/text_detector.cc b/third_party/blink/renderer/modules/shapedetection/text_detector.cc
index 3e0e6ae..4e3fb73 100644
--- a/third_party/blink/renderer/modules/shapedetection/text_detector.cc
+++ b/third_party/blink/renderer/modules/shapedetection/text_detector.cc
@@ -20,7 +20,9 @@
 }
 
 TextDetector::TextDetector(ExecutionContext* context) : ShapeDetector() {
-  auto request = mojo::MakeRequest(&text_service_);
+  // See https://bit.ly/2S0zRAS for task types.
+  auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
+  auto request = mojo::MakeRequest(&text_service_, task_runner);
   if (auto* interface_provider = context->GetInterfaceProvider()) {
     interface_provider->GetInterface(std::move(request));
   }
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition.cc b/third_party/blink/renderer/modules/speech/speech_recognition.cc
index 681ecf0..a8180d7 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition.cc
+++ b/third_party/blink/renderer/modules/speech/speech_recognition.cc
@@ -53,9 +53,12 @@
 
   final_results_.clear();
 
+  // See https://bit.ly/2S0zRAS for task types.
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+      GetExecutionContext()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI);
   mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client;
   binding_.Bind(mojo::MakeRequest(&session_client),
-                GetExecutionContext()->GetInterfaceInvalidator());
+                GetExecutionContext()->GetInterfaceInvalidator(), task_runner);
   binding_.set_connection_error_handler(WTF::Bind(
       &SpeechRecognition::OnConnectionError, WrapWeakPersistent(this)));
 
diff --git a/third_party/blink/renderer/modules/vr/vr_controller.cc b/third_party/blink/renderer/modules/vr/vr_controller.cc
index 27cf491..45bcb147b 100644
--- a/third_party/blink/renderer/modules/vr/vr_controller.cc
+++ b/third_party/blink/renderer/modules/vr/vr_controller.cc
@@ -21,13 +21,16 @@
       navigator_vr_(navigator_vr),
       display_synced_(false),
       binding_(this) {
+  // See https://bit.ly/2S0zRAS for task types.
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+      navigator_vr->GetDocument()->GetTaskRunner(TaskType::kMiscPlatformAPI);
   navigator_vr->GetDocument()->GetFrame()->GetInterfaceProvider().GetInterface(
-      mojo::MakeRequest(&service_));
+      mojo::MakeRequest(&service_, task_runner));
   service_.set_connection_error_handler(
       WTF::Bind(&VRController::Dispose, WrapWeakPersistent(this)));
 
   device::mojom::blink::VRServiceClientPtr client;
-  binding_.Bind(mojo::MakeRequest(&client));
+  binding_.Bind(mojo::MakeRequest(&client, task_runner), task_runner);
   service_->SetClient(std::move(client));
 
   service_->RequestDevice(
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc
index f691f3d..b31ddbee 100644
--- a/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -856,8 +856,7 @@
 device::mojom::blink::VRDisplayClientPtr VRDisplay::GetDisplayClient() {
   display_client_binding_.Close();
   device::mojom::blink::VRDisplayClientPtr client;
-  // A specific task source should be defined but not.
-  // See https://immersive-web.github.io/webvr/spec/1.1/.
+  // See https://bit.ly/2S0zRAS for task types.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
   display_client_binding_.Bind(mojo::MakeRequest(&client, task_runner),
diff --git a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
index f6be881d..e47baa4 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
+++ b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
@@ -40,8 +40,12 @@
   ScriptPromise promise = this->Promise();
   accessor_ = MIDIAccessor::Create(this);
 
-  ConnectToPermissionService(GetExecutionContext(),
-                             mojo::MakeRequest(&permission_service_));
+  // See https://bit.ly/2S0zRAS for task types.
+  ConnectToPermissionService(
+      GetExecutionContext(),
+      mojo::MakeRequest(
+          &permission_service_,
+          GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
 
   Document& doc = To<Document>(*GetExecutionContext());
   permission_service_->RequestPermission(
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share.cc b/third_party/blink/renderer/modules/webshare/navigator_share.cc
index 261658c..bd96d50 100644
--- a/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -137,7 +137,9 @@
       return ScriptPromise::RejectWithDOMException(script_state, error);
     }
 
-    frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+    // See https://bit.ly/2S0zRAS for task types.
+    frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(
+        &service_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
     service_.set_connection_error_handler(WTF::Bind(
         &NavigatorShare::OnConnectionError, WrapWeakPersistent(this)));
     DCHECK(service_);
diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
index 0ad8294..b834a2d 100644
--- a/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/third_party/blink/renderer/modules/webusb/usb.cc
@@ -292,10 +292,9 @@
 
   DCHECK(IsContextSupported());
   DCHECK(GetFeatureEnabledState() != FeatureEnabledState::kDisabled);
-  // A specific task source should be defined but not.
-  // See https://wicg.github.io/webusb/.
+  // See https://bit.ly/2S0zRAS for task types.
   auto task_runner =
-      GetExecutionContext()->GetTaskRunner(TaskType::kInternalDefault);
+      GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
   GetExecutionContext()->GetInterfaceProvider()->GetInterface(
       mojo::MakeRequest(&service_, task_runner));
   service_.set_connection_error_handler(
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index 595c15e..9f568dd 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -36,7 +36,9 @@
       FocusChangedObserver(frame.GetPage()),
       ukm_source_id_(ukm_source_id),
       binding_(this) {
-  frame.GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+  // See https://bit.ly/2S0zRAS for task types.
+  frame.GetInterfaceProvider().GetInterface(mojo::MakeRequest(
+      &service_, frame.GetTaskRunner(TaskType::kMiscPlatformAPI)));
   service_.set_connection_error_handler(
       WTF::Bind(&XR::Dispose, WrapWeakPersistent(this)));
 }
@@ -192,9 +194,13 @@
 
   if (event_type == event_type_names::kDevicechange) {
     // Register for notifications if we haven't already.
+    //
+    // See https://bit.ly/2S0zRAS for task types.
+    auto task_runner =
+        GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
     if (!binding_.is_bound()) {
       device::mojom::blink::VRServiceClientPtr client;
-      binding_.Bind(mojo::MakeRequest(&client));
+      binding_.Bind(mojo::MakeRequest(&client, task_runner));
       service_->SetClient(std::move(client));
     }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_device.cc b/third_party/blink/renderer/modules/xr/xr_device.cc
index d48f157e..9a84310 100644
--- a/third_party/blink/renderer/modules/xr/xr_device.cc
+++ b/third_party/blink/renderer/modules/xr/xr_device.cc
@@ -225,8 +225,11 @@
   } else {
     magic_window_provider_.Bind(std::move(session_ptr->data_provider));
     if (environment_integration) {
+      // See https://bit.ly/2S0zRAS for task types.
       magic_window_provider_->GetEnvironmentIntegrationProvider(
-          mojo::MakeRequest(&environment_provider_));
+          mojo::MakeRequest(&environment_provider_,
+                            xr_->GetExecutionContext()->GetTaskRunner(
+                                TaskType::kMiscPlatformAPI)));
     }
   }
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index e6dce18..e5a88f6 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1312,10 +1312,6 @@
       name: "UserActivationV2",
     },
     {
-      name: "V8ContextSnapshot",
-      status: "test",
-    },
-    {
       name: "V8IdleTasks",
     },
     {
diff --git a/third_party/blink/renderer/platform/wtf/text/collator.cc b/third_party/blink/renderer/platform/wtf/text/collator.cc
index ee57a10..0225cac 100644
--- a/third_party/blink/renderer/platform/wtf/text/collator.cc
+++ b/third_party/blink/renderer/platform/wtf/text/collator.cc
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <unicode/ucol.h>
 #include <memory>
+#include "base/thread_annotations.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
@@ -39,13 +40,16 @@
 
 namespace WTF {
 
-static UCollator* g_cached_collator;
-static char g_cached_equivalent_locale[Collator::kUlocFullnameCapacity];
 static Mutex& CachedCollatorMutex() {
   DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
   return mutex;
 }
 
+static UCollator* g_cached_collator GUARDED_BY(CachedCollatorMutex());
+static char
+    g_cached_equivalent_locale[Collator::kUlocFullnameCapacity] GUARDED_BY(
+        CachedCollatorMutex());
+
 Collator::Collator(const char* locale)
     : collator_(nullptr),
       locale_(locale ? strdup(locale) : nullptr),
@@ -82,7 +86,7 @@
   UErrorCode status = U_ZERO_ERROR;
 
   {
-    Locker<Mutex> lock(CachedCollatorMutex());
+    MutexLocker lock(CachedCollatorMutex());
     if (g_cached_collator) {
       UColAttributeValue cached_collator_lower_first =
           ucol_getAttribute(g_cached_collator, UCOL_CASE_FIRST, &status);
@@ -119,7 +123,7 @@
 
 void Collator::ReleaseCollator() {
   {
-    Locker<Mutex> lock(CachedCollatorMutex());
+    MutexLocker lock(CachedCollatorMutex());
     if (g_cached_collator)
       ucol_close(g_cached_collator);
     g_cached_collator = collator_;
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 16e9fbb..130e8e6f 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -100,7 +100,7 @@
 crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Pass ]
 crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ]
-crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Pass ]
+crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ]
 crbug.com/893550 external/wpt/css/css-ui/text-overflow-015.html [ Failure ]
@@ -250,7 +250,7 @@
 crbug.com/591099 fast/inline/inline-box-background-repeat-y.html [ Failure ]
 crbug.com/889721 fast/inline/outline-continuations.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
-crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure ]
+crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure Pass ]
 crbug.com/591099 fast/scroll-snap/snaps-after-keyboard-scrolling-rtl.html [ Failure ]
 crbug.com/591099 fast/table/backgr_border-table-cell-collapsed-border.html [ Failure ]
 crbug.com/591099 fast/table/backgr_border-table-cell.html [ Failure ]
@@ -333,17 +333,11 @@
 crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ]
 crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
-crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ]
-crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ]
-crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ Failure ]
-crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug101674.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug23235.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug2973.html [ Pass ]
-crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ]
 crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ]
 crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ]
@@ -359,8 +353,7 @@
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ]
-crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Pass ]
-crbug.com/591099 virtual/omt-worker-fetch/http/tests/workers/worker-invalid-context.html [ Failure Pass ]
+crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Timeout ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.html [ Pass ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ]
 crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index db9e43d1..217eb61 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -188,6 +188,8 @@
 crbug.com/759632 http/tests/devtools/network/network-datasaver-warning.js [ Failure ]
 # ====== Browserside navigation until here ======
 
+crbug.com/915472 inspector-protocol/worker/worker-autoattach-order.js [ Failure Pass ]
+
 # ====== Paint team owned tests from here ======
 # The paint team tracks and triages its test failures, and keeping them colocated
 # makes tracking much easier.
@@ -281,6 +283,8 @@
 crbug.com/774873 [ Linux ] virtual/exotic-color-space/images/color-profile-border-fade.html [ Pass Failure ]
 crbug.com/774873 [ Win ] virtual/exotic-color-space/images/color-profile-border-fade.html [ Pass Failure ]
 
+crbug.com/915417 http/tests/webmidi/midi-default-feature-policy.https.sub.html [ Pass Timeout Failure ]
+
 # Flakily timing out or failing.
 # TODO(ccameron): Investigate this.
 crbug.com/730267 virtual/gpu-rasterization/images/color-profile-group.html [ Pass Timeout Failure ]
@@ -2144,9 +2148,7 @@
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-008.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-009.xht [ Skip ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-003.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-004.xht [ Skip ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-text/word-break/word-break-normal-bo-000.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-normal-km-000.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-my-000.html [ Failure ]
@@ -4694,6 +4696,11 @@
 # Antialiasing error
 crbug.com/845973 virtual/display-compositor-pixel-dump/fast/canvas/display-compositor-pixel-dump/OffscreenCanvas-opaque-background-compositing.html  [ Pass Failure ]
 
+# Some Windows 7 vm images have a timezone-related registry not populated
+# leading this test to fail.
+# https://chromium-review.googlesource.com/c/chromium/src/+/1379250/6
+crbug.com/856119 [ Win7 ] fast/js/regress/resolved-timezone-defined.html  [ Pass Failure ]
+
 # Tests occasionaly timing out (flaky) on WebKit Win7 dbg builder
 crbug.com/757955 [ Win7 Debug ] http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ]
 crbug.com/757955 [ Win7 Debug ] storage/indexeddb/mozilla/cursors.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index a781708d..9c2c7af 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -1687,18 +1687,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/word-break-break-all-009.xht": [
-    [
-     "/css/css-text/word-break/word-break-break-all-009.xht",
-     {}
-    ]
-   ],
-   "css/css-text/word-break/word-break-keep-all-004.xht": [
-    [
-     "/css/css-text/word-break/word-break-keep-all-004.xht",
-     {}
-    ]
-   ],
    "css/css-transitions/transition-delay-000.html": [
     [
      "/css/css-transitions/transition-delay-000.html",
@@ -61267,18 +61255,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/overflow-wrap-003.html": [
-    [
-     "/css/css-text/overflow-wrap/overflow-wrap-003.html",
-     [
-      [
-       "/css/css-text/overflow-wrap/overflow-wrap-003-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/overflow-wrap/overflow-wrap-004.html": [
     [
      "/css/css-text/overflow-wrap/overflow-wrap-004.html",
@@ -61291,18 +61267,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/overflow-wrap-005.html": [
-    [
-     "/css/css-text/overflow-wrap/overflow-wrap-005.html",
-     [
-      [
-       "/css/css-text/overflow-wrap/overflow-wrap-003-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/overflow-wrap/overflow-wrap-break-word-001.html": [
     [
      "/css/css-text/overflow-wrap/overflow-wrap-break-word-001.html",
@@ -61447,18 +61411,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/word-wrap-003.html": [
-    [
-     "/css/css-text/overflow-wrap/word-wrap-003.html",
-     [
-      [
-       "/css/css-text/overflow-wrap/overflow-wrap-003-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/overflow-wrap/word-wrap-004.html": [
     [
      "/css/css-text/overflow-wrap/word-wrap-004.html",
@@ -61471,18 +61423,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/word-wrap-005.html": [
-    [
-     "/css/css-text/overflow-wrap/word-wrap-005.html",
-     [
-      [
-       "/css/css-text/overflow-wrap/overflow-wrap-003-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/tab-size/tab-min-rendered-width-1.html": [
     [
      "/css/css-text/tab-size/tab-min-rendered-width-1.html",
@@ -140287,11 +140227,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/overflow-wrap-003-ref.html": [
-    [
-     {}
-    ]
-   ],
    "css/css-text/overflow-wrap/overflow-wrap-004-ref.html": [
     [
      {}
@@ -141302,11 +141237,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/reference/word-break-break-all-009-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-text/word-break/reference/word-break-break-all-010-ref.html": [
     [
      {}
@@ -141367,11 +141297,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/reference/word-break-keep-all-004-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-text/word-break/reference/word-break-keep-all-005-ref.html": [
     [
      {}
@@ -166807,11 +166732,6 @@
      {}
     ]
    ],
-   "html/semantics/forms/the-button-element/button-validation-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt": [
     [
      {}
@@ -291147,30 +291067,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/word-break-001.html": [
-    [
-     "/css/css-text/word-break/word-break-001.html",
-     {}
-    ]
-   ],
-   "css/css-text/word-break/word-break-002.html": [
-    [
-     "/css/css-text/word-break/word-break-002.html",
-     {}
-    ]
-   ],
-   "css/css-text/word-break/word-break-003.html": [
-    [
-     "/css/css-text/word-break/word-break-003.html",
-     {}
-    ]
-   ],
-   "css/css-text/word-break/word-break-004.html": [
-    [
-     "/css/css-text/word-break/word-break-004.html",
-     {}
-    ]
-   ],
    "css/css-transforms/css-transform-inherit-rotate.html": [
     [
      "/css/css-transforms/css-transform-inherit-rotate.html",
@@ -353038,14 +352934,6 @@
    "2c6d34d01da680939df27850b64cd0091751a21a",
    "reftest"
   ],
-  "css/css-text/overflow-wrap/overflow-wrap-003-ref.html": [
-   "fa4ca42b587efba8d7ccb353309caab9a26bc5bc",
-   "support"
-  ],
-  "css/css-text/overflow-wrap/overflow-wrap-003.html": [
-   "99ead18f2811b2762b34ddbd918a66f0af52b7f0",
-   "reftest"
-  ],
   "css/css-text/overflow-wrap/overflow-wrap-004-ref.html": [
    "c0abde9885851583c7274e18f432430d159291d5",
    "support"
@@ -353054,10 +352942,6 @@
    "92ad750207dbd573df83e235be4cee52d92d4add",
    "reftest"
   ],
-  "css/css-text/overflow-wrap/overflow-wrap-005.html": [
-   "181137450d58d9fa072ba40e8d4d5f75b23e7f4e",
-   "reftest"
-  ],
   "css/css-text/overflow-wrap/overflow-wrap-break-word-001.html": [
    "7eaa8f31df1e474bae4c669bd6622b9f1cb2542c",
    "reftest"
@@ -353142,18 +353026,10 @@
    "380fb8ec4fde4decb82e52961ce5ef71a0a6c965",
    "reftest"
   ],
-  "css/css-text/overflow-wrap/word-wrap-003.html": [
-   "282d184b06927311f575d1022ecf1b21b6fd677f",
-   "reftest"
-  ],
   "css/css-text/overflow-wrap/word-wrap-004.html": [
    "ce7a2fe504747e6c6ffc35a019021bdedbec6d21",
    "reftest"
   ],
-  "css/css-text/overflow-wrap/word-wrap-005.html": [
-   "4b9973a19de2e7b3182d29134102843a2c6b4eb6",
-   "reftest"
-  ],
   "css/css-text/overflow-wrap/word-wrap-alias.html": [
    "74e8aa2312416f165550b08ab7351ec18ca956f1",
    "testharness"
@@ -355042,16 +354918,12 @@
    "6b21df62c5cbdfa2cce9e52d91c7a792d94354e8",
    "reftest"
   ],
-  "css/css-text/word-break/reference/word-break-break-all-009-ref.xht": [
-   "0768b857d96624a63129f002d317019674d1ef0d",
-   "support"
-  ],
   "css/css-text/word-break/reference/word-break-break-all-010-ref.html": [
    "0e0300a72dc920a5ffb54cda6fbe84a2f517d010",
    "support"
   ],
   "css/css-text/word-break/reference/word-break-break-all-014-ref.html": [
-   "a8720a101c3b2d2616b661e51c60b55b85d2d667",
+   "044ea40dd2c737f61a05751d1a778f13d93ad33a",
    "support"
   ],
   "css/css-text/word-break/reference/word-break-break-all-020-ref.html": [
@@ -355094,10 +354966,6 @@
    "0499f82e799e76f757eb17f81733447d2186481f",
    "support"
   ],
-  "css/css-text/word-break/reference/word-break-keep-all-004-ref.xht": [
-   "65ede653fcc21183c8353137873113ee3a05aa2b",
-   "support"
-  ],
   "css/css-text/word-break/reference/word-break-keep-all-005-ref.html": [
    "2a33ce75e23f6c65ec98a2a808633349b1ae465e",
    "support"
@@ -355115,7 +354983,7 @@
    "support"
   ],
   "css/css-text/word-break/reference/word-break-keep-all-ref-003.html": [
-   "a6adfdc8340d53184d7182e944e5991108f3188b",
+   "5aba6783f4ed6a2ef19a5a3f59c862ce4584faeb",
    "support"
   ],
   "css/css-text/word-break/reference/word-break-normal-ar-ref-000.html": [
@@ -355182,22 +355050,6 @@
    "afdd82454c059b487cb1329751f3e1ca9f1cf750",
    "support"
   ],
-  "css/css-text/word-break/word-break-001.html": [
-   "f0b6aee34467d077dec49de5d54f497bb0877b97",
-   "visual"
-  ],
-  "css/css-text/word-break/word-break-002.html": [
-   "652e40de2664ea4ae079e48f03c3a74449b28c22",
-   "visual"
-  ],
-  "css/css-text/word-break/word-break-003.html": [
-   "34546ad61f5c85fbeed9bb40f120069355327f53",
-   "visual"
-  ],
-  "css/css-text/word-break/word-break-004.html": [
-   "9f4ccd0331d69b82ac13de439d59d8cc64be897c",
-   "visual"
-  ],
   "css/css-text/word-break/word-break-break-all-000.html": [
    "af21bedf4bdc3219b3c3b1225f76b55e127d3f13",
    "reftest"
@@ -355234,10 +355086,6 @@
    "83a74c46a39590ebc7d25d4d665e104ba38fbc18",
    "reftest"
   ],
-  "css/css-text/word-break/word-break-break-all-009.xht": [
-   "9a7a591dafd4352f7df11dc9396608027ef80cd6",
-   "manual"
-  ],
   "css/css-text/word-break/word-break-break-all-010.html": [
    "7d3bc056d822ca15b523f332c6c23ed22a85b340",
    "reftest"
@@ -355247,7 +355095,7 @@
    "reftest"
   ],
   "css/css-text/word-break/word-break-break-all-014.html": [
-   "6885553ad685700e89d4d83ded7bc65269aa1123",
+   "674b0545e05a5d25f056ac9850abd11791de6a58",
    "reftest"
   ],
   "css/css-text/word-break/word-break-break-all-020.html": [
@@ -355267,13 +355115,9 @@
    "reftest"
   ],
   "css/css-text/word-break/word-break-keep-all-003.html": [
-   "1395e354465c5018bd761305933bdcd601fff639",
+   "776d56d828084e95d260b936b3a8c9f282966728",
    "reftest"
   ],
-  "css/css-text/word-break/word-break-keep-all-004.xht": [
-   "c66bfe4bae042170581ab087fb90e41f8a1fc122",
-   "manual"
-  ],
   "css/css-text/word-break/word-break-keep-all-005.html": [
    "4bb523ab7ca395b36204148755ee5e6d9243761a",
    "reftest"
@@ -404170,12 +404014,8 @@
    "6cfd6687c707479600534de03156afa698daa314",
    "testharness"
   ],
-  "html/semantics/forms/the-button-element/button-validation-expected.txt": [
-   "de5aadc0390746b41df1bfb9070a3ed1228d93bc",
-   "support"
-  ],
   "html/semantics/forms/the-button-element/button-validation.html": [
-   "a153907d77a2c38cc8fbfe39d5c21b065fa96eed",
+   "f3b57fd296a251bc3075215cf93a91942b4d281f",
    "testharness"
   ],
   "html/semantics/forms/the-button-element/button-validationmessage.html": [
@@ -411279,7 +411119,7 @@
    "support"
   ],
   "interfaces/webxr.idl": [
-   "27ee27493aaa98869c9fe3adc0f4f19ec99e85e2",
+   "ea45aef97715ec7d4e098e357af69575eb432ebd",
    "support"
   ],
   "interfaces/worklets.idl": [
@@ -434071,7 +433911,7 @@
    "testharness"
   ],
   "resource-timing/resource-timing.js": [
-   "c0d072d6cf57f921a188f9e331fa1e4a2af7a51b",
+   "8d97b2f26871e3a492cc6d3d253808e0cf18b0f2",
    "support"
   ],
   "resource-timing/resource_TAO_cross_origin_redirect_chain.html": [
@@ -451303,7 +451143,7 @@
    "support"
   ],
   "webxr/idlharness.https.window-expected.txt": [
-   "70f7fa67447af7b96878d02f4d7b4dd388dc7e3c",
+   "51e4af40edabe2c90c4527552ec8c51965f82b19",
    "support"
   ],
   "webxr/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003-ref.html
deleted file mode 100644
index fa4ca42b..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003-ref.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test Reference File</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<style>
-  #test {
-    border: 5px solid orange;
-    font: 20px/1 Ahem;
-    width: 20em;
-  }
-</style>
-<body>
-  <p class="instructions">Test passes if the black box displayed in two rows within the orange box.</p>
-  <p id="test">FillerTextFillerText<br>FillerTextFillerText</p>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003.html
deleted file mode 100644
index 99ead18..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-003.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: overflow-wrap - break-word (white space)</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" title="6.2. Overflow Wrapping: the 'word-wrap'/'overflow-wrap' property" href="http://www.w3.org/TR/css-text-3/#overflow-wrap">
-<link rel="match" href="overflow-wrap-003-ref.html">
-<meta name="flags" content="ahem">
-<meta name="assert" content="The 'overflow-wrap' property set 'break-word' breaks line at white space">
-<style>
-  #test {
-    border: 5px solid orange;
-    font: 20px/1 Ahem;
-    overflow-wrap: break-word;
-    width: 20em;
-  }
-</style>
-<body>
-  <p class="instructions">Test passes if the black box displayed in two rows within the orange box.</p>
-  <p id="test">FillerTextFillerText FillerTextFillerText</p>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-005.html b/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-005.html
deleted file mode 100644
index 18113745..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-005.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: overflow-wrap - normal (white space)</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" title="6.2. Overflow Wrapping: the 'word-wrap'/'overflow-wrap' property" href="http://www.w3.org/TR/css-text-3/#overflow-wrap">
-<link rel="match" href="overflow-wrap-003-ref.html">
-<meta name="flags" content="ahem">
-<meta name="assert" content="The 'overflow-wrap' property set 'normal' will break line at white space">
-<style>
-  #test {
-    border: 5px solid orange;
-    font: 20px/1 Ahem;
-    overflow-wrap: normal;
-    width: 20em;
-  }
-</style>
-<body>
-  <p class="instructions">Test passes if the black box displayed in two rows within the orange box.</p>
-  <p id="test">FillerTextFillerText FillerTextFillerText</p>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-003.html
deleted file mode 100644
index 282d184..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-003.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-wrap - break-word (white space)</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" title="6.2. Overflow Wrapping: the 'word-wrap'/'overflow-wrap' property" href="http://www.w3.org/TR/css-text-3/#overflow-wrap">
-<link rel="match" href="overflow-wrap-003-ref.html">
-<meta name="flags" content="ahem">
-<meta name="assert" content="The 'word-wrap' property set 'break-word' breaks line at white space">
-<style>
-  #test {
-    border: 5px solid orange;
-    font: 20px/1 Ahem;
-    word-wrap: break-word;
-    width: 20em;
-  }
-</style>
-<body>
-  <p class="instructions">Test passes if the black box displayed in two rows within the orange box.</p>
-  <p id="test">FillerTextFillerText FillerTextFillerText</p>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-005.html b/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-005.html
deleted file mode 100644
index 4b9973a..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/overflow-wrap/word-wrap-005.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-wrap - normal (white space)</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" title="6.2. Overflow Wrapping: the 'word-wrap'/'overflow-wrap' property" href="http://www.w3.org/TR/css-text-3/#overflow-wrap">
-<link rel="match" href="overflow-wrap-003-ref.html">
-<meta name="flags" content="ahem">
-<meta name="assert" content="The 'word-wrap' property set 'normal' will break line at white space">
-<style>
-  #test {
-    border: 5px solid orange;
-    font: 20px/1 Ahem;
-    word-wrap: normal;
-    width: 20em;
-  }
-</style>
-<body>
-  <p class="instructions">Test passes if the black box displayed in two rows within the orange box.</p>
-  <p id="test">FillerTextFillerText FillerTextFillerText</p>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-009-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-009-ref.xht
deleted file mode 100644
index 0768b85..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-009-ref.xht
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
-	<head>
-		<title>CSS Test: word-break - break-all - basic cases</title>
-		<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
-		<style type="text/css">
-			<![CDATA[
-				.test span {
-					word-break: break-all;
-				}
-				/* the CSS below is not part of the test */
-				p.test, p.control {
-					border: 1px solid gray;
-					color: blue;
-					font-family: "IPAMincho", "IPAGothic", "IPA明朝", "IPAゴシック";
-					width: 10em;
-				}
-				div.wrapper {
-					display: inline-block;
-					border: 1px solid;
-					margin: 10px;
-					padding: 10px;
-				}
-				span.attention {
-					color: red;
-				}
-			]]>
-		</style>
-	</head>
-	<body>
-		<p>
-			Test passes if each pair of upper and lower text in the square box is identical.
-		</p>
-		<div class="wrapper">
-			<p class="test">
-				<span>Filler Text Filler Text Filler Text</span>
-			</p>
-			<p class="control">
-				<span>Filler Text Filler T<br />ext Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字 Filler Text</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字 Fil<br />ler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字満たすための文字</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字満た<br />すための文字</span>
-			</p>
-		</div>
-		<p>
-			<span class="attention">* You will need a Japanese font.</span><br />
-			If you are unable to see font glyphs for certain characters using the browsers default font, install the <a href="http://ossipedia.ipa.go.jp/ipafont/">IPA Font(http://ossipedia.ipa.go.jp/ipafont/)</a> and reload this page.
-		</p>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-014-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-014-ref.html
index a8720a1..044ea40 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-014-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-break-all-014-ref.html
@@ -2,5 +2,5 @@
 <meta charset="utf-8">
 <title>CSS Text Test: overflow-wrap: break-all</title>
 <link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
-<p>Test passes if 2 icons are rendered in a row, matching the reference file.</p>
+<p>Test passes if 2 (different) heart emojis are rendered below each other.</p>
 <div>💖<br>💔</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-004-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-004-ref.xht
deleted file mode 100644
index 65ede65..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-004-ref.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
-	<head>
-		<title>CSS Test: word-break - keep-all - basic cases Reftest Reference</title>
-		<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
-		<style type="text/css">
-			<![CDATA[
-				p.control {
-					border: 1px solid gray;
-					color: blue;
-					font-family: "IPAMincho", "IPAGothic", "IPA明朝", "IPAゴシック";
-					width: 10em;
-				}
-				div.wrapper {
-					display: inline-block;
-					border: 1px solid;
-					margin: 10px;
-					padding: 10px;
-				}
-				span.attention {
-					color: red;
-				}
-				span.no_wrap {
-					white-space: nowrap;
-				}
-			]]>
-		</style>
-	</head>
-	<body>
-		<p>
-			Test passes if each pair of upper and lower text in the square box is identical.
-		</p>
-		<div class="wrapper">
-			<p class="control">
-				<span>Filler Text Filler<br />Text Filler Text</span>
-			</p>
-			<p class="control">
-				<span>Filler Text Filler<br />Text Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="control">
-				<span>満たすための文字<br />Filler Text</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字<br />Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="control">
-				<span class="no_wrap">満たすための文字満たすための文字</span>
-			</p>
-			<p class="control">
-				<span class="no_wrap">満たすための文字満たすための文字</span>
-			</p>
-		</div>
-		<p>
-			<span class="attention">* You will need a Japanese font.</span><br />
-			If you are unable to see font glyphs for certain characters using the browsers default font, install the <a href="http://ossipedia.ipa.go.jp/ipafont/">IPA Font(http://ossipedia.ipa.go.jp/ipafont/)</a> and reload this page.
-		</p>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-ref-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-ref-003.html
index a6adfdc..5aba6783 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-ref-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/reference/word-break-keep-all-ref-003.html
@@ -12,7 +12,7 @@
 </head>
 <body>
 <div id='instructions'>Test passes if the two orange boxes are the same.</div>
-<div class="ref" lang="th"><span>แและ แและ<br/>แและ</span></div>
-<div class="ref" lang="th"><span>แและ แและ<br/>แและ</span></div>
+<div class="ref" lang="th"><span>และ และ<br/>และ</span></div>
+<div class="ref" lang="th"><span>และ และ<br/>และ</span></div>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-001.html
deleted file mode 100644
index f0b6aee3..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-001.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-break - break-all keyword value</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" href="http://www.w3.org/TR/css-text-3/#word-break">
-<meta name="flags" content="">
-<meta name="assert" content="Check that 'word-break' with 'break-all' keyword value implies to words break between any two letters without hyphenate.">
-<style>
-  div {
-    border: 2px black solid;
-    color: blue;
-    width: 100px;
-    word-break: break-all;
-  }
-</style>
-<body>
-  <p>Test passes if all the words below are inside the box and break between any two letters without hyphenate.</p>
-  <div>Words in these lines should break between any two letters and be inside the box.</div>
-</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-002.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-002.html
deleted file mode 100644
index 652e40d..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-002.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-break - normal keyword value</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" href="http://www.w3.org/TR/css-text-3/#word-break">
-<meta name="flags" content="">
-<meta name="assert" content="Check that 'word-break' with 'normal' keyword value implies to words break after word.">
-<style>
-  div {
-    border: 2px black solid;
-    color: blue;
-    width: 100px;
-    word-break: normal;
-  }
-</style>
-<body>
-  <p>Test passes if all the words below are within the box and break only after a word.</p>
-  <div>Words in these lines should break after word and be inside the box.</div>
-</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-003.html
deleted file mode 100644
index 34546ad..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-003.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-break - normal keyword value - single word not break</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" href="http://www.w3.org/TR/css-text-3/#word-break">
-<meta name="flags" content="">
-<meta name="assert" content="Check that 'word-break' with 'normal' keyword value implies to words break after word, so that a single word won't break.">
-<style>
-  div {
-    border: 2px black solid;
-    color: blue;
-    width: 100px;
-    word-break: normal;
-  }
-</style>
-<body>
-  <p>Test passes if there is <strong>no</strong> word break below.</p>
-  <div>ThisWordShouldNotBeBreakedAndMayBeOutOfTheBox</div>
-</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-004.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-004.html
deleted file mode 100644
index 9f4ccd0..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-004.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: word-break - normal keyword value - Chinese words break</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
-<link rel="help" href="http://www.w3.org/TR/css-text-3/#word-break">
-<meta name="flags" content="">
-<meta name="assert" content="Check that 'word-break' with 'normal' keyword value implies to words break after word, including Chinese words.">
-<style>
-  div {
-    border: 2px black solid;
-    color: blue;
-    width: 100px;
-    word-break: normal;
-  }
-</style>
-<body>
-  <p>Test passes if all the Chinese words below are inside the box and break normally.</p>
-  <div>这些文字会自动换行,但不会超出黑色框。</div>
-</body>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-009.xht b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-009.xht
deleted file mode 100644
index 9a7a591d..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-009.xht
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
-	<head>
-		<title>CSS Test: word-break - break-all - basic cases</title>
-		<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
-		<link rel="help" title="CSS Text Level 3: 5.2. Word Breaking Rules: the ‘word-break’ property" href="http://www.w3.org/TR/css-text-3/#word-break" />
-		<link rel="match" href="reference/word-break-break-all-009-ref.xht"/>
-		<meta name="flags" content="font" />
-		<meta name="assert" content="Lines may break between any two grapheme clusters within words." />
-		<style type="text/css">
-			<![CDATA[
-				.test span {
-					word-break: break-all;
-				}
-				/* the CSS below is not part of the test */
-				p.test, p.control {
-					border: 1px solid gray;
-					color: blue;
-					font-family: "IPAMincho", "IPAGothic", "IPA明朝", "IPAゴシック";
-					width: 10em;
-				}
-				div.wrapper {
-					display: inline-block;
-					border: 1px solid;
-					margin: 10px;
-					padding: 10px;
-				}
-				span.attention {
-					color: red;
-				}
-			]]>
-		</style>
-	</head>
-	<body>
-		<p>
-			Test passes if each pair of upper and lower text in the square box is identical.
-		</p>
-		<div class="wrapper">
-			<p class="test">
-				<span>Filler Text Filler Text Filler Text</span>
-			</p>
-			<p class="control">
-				<span>Filler Text Filler T<br />ext Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字 Filler Text</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字 Fil<br />ler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字満たすための文字</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字満た<br />すための文字</span>
-			</p>
-		</div>
-		<p>
-			<span class="attention">* You will need a Japanese font.</span><br />
-			If you are unable to see font glyphs for certain characters using the browsers default font, install the <a href="http://ossipedia.ipa.go.jp/ipafont/">IPA Font(http://ossipedia.ipa.go.jp/ipafont/)</a> and reload this page.
-		</p>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-014.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-014.html
index 6885553..674b0545 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-014.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-break-all-014.html
@@ -3,7 +3,7 @@
 <title>CSS Text Test: overflow-wrap: break-all</title>
 <link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
-<meta name="flags" content="ahem">
+<meta name="flags" content="">
 <link rel="match" href="reference/word-break-break-all-014-ref.html">
 <meta name="assert" content="The text is wrapped after the first character and no unicode unit is broken.">
 <style>
@@ -12,5 +12,5 @@
   word-break: break-all;
 }
 </style>
-<p>Test passes if 2 icons are rendered in a row, matching the reference file.</p>
+<p>Test passes if 2 (different) heart emojis are rendered below each other.</p>
 <div>💖💔</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-003.html
index 1395e354..776d56d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-003.html
@@ -15,11 +15,11 @@
 </head>
 <body>
 <div id='instructions'>Test passes if the two orange boxes are the same.</div>
-<div class="test" lang="th"><div id="testdiv"><span id="testspan">แและ แและแและ</span></div></div>
-<div class="ref" lang="th"><span>แและ แและ<br/>แและ</span></div>
+<div class="test" lang="th"><div id="testdiv"><span id="testspan">และ และและ</span></div></div>
+<div class="ref" lang="th"><span>และ และ<br/>และ</span></div>
 <script>
 var sentenceWidth = document.getElementById('testspan').offsetWidth
 document.getElementById('testdiv').style.width = String(sentenceWidth - 5)+'px'
 </script>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-004.xht b/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-004.xht
deleted file mode 100644
index c66bfe4..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/word-break/word-break-keep-all-004.xht
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
-	<head>
-		<title>CSS Test: word-break - keep-all - basic cases</title>
-		<link rel="author" title="Satoshi Umehara" href="mailto:umehara@est.co.jp" />
-		<link rel="help" title="CSS Text Level 3: 5.2. Word Breaking Rules: the ‘word-break’ property" href="http://www.w3.org/TR/css-text-3/#word-break" />
-		<link rel="match" href="reference/word-break-keep-all-004-ref.xht"/>
-		<meta name="flags" content="font" />
-		<meta name="assert" content="Block characters can no longer create implied break points." />
-		<style type="text/css">
-			<![CDATA[
-				.test span {
-					word-break: keep-all;
-				}
-				/* the CSS below is not part of the test */
-				p.test, p.control {
-					border: 1px solid gray;
-					color: blue;
-					font-family: "IPAMincho", "IPAGothic", "IPA明朝", "IPAゴシック";
-					width: 10em;
-				}
-				div.wrapper {
-					display: inline-block;
-					border: 1px solid;
-					margin: 10px;
-					padding: 10px;
-				}
-				span.attention {
-					color: red;
-				}
-				span.no_wrap {
-					white-space: nowrap;
-				}
-			]]>
-		</style>
-	</head>
-	<body>
-		<p>
-			Test passes if each pair of upper and lower text in the square box is identical.
-		</p>
-		<div class="wrapper">
-			<p class="test">
-				<span>Filler Text Filler Text Filler Text</span>
-			</p>
-			<p class="control">
-				<span>Filler Text Filler<br />Text Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字 Filler Text</span>
-			</p>
-			<p class="control">
-				<span>満たすための文字<br />Filler Text</span>
-			</p>
-		</div>
-		<div class="wrapper">
-			<p class="test">
-				<span>満たすための文字満たすための文字</span>
-			</p>
-			<p class="control">
-				<span class="no_wrap">満たすための文字満たすための文字</span>
-			</p>
-		</div>
-		<p>
-			<span class="attention">* You will need a Japanese font.</span><br />
-			If you are unable to see font glyphs for certain characters using the browsers default font, install the <a href="http://ossipedia.ipa.go.jp/ipafont/">IPA Font(http://ossipedia.ipa.go.jp/ipafont/)</a> and reload this page.
-		</p>
-	</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation-expected.txt
deleted file mode 100644
index de5aadc..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-PASS missing type attribute
-PASS submit type attribute
-PASS reset type attribute
-PASS button type attribute
-FAIL menu type attribute assert_equals: expected "menu" but got "submit"
-PASS invalid type attribute
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation.html
index a153907..f3b57fd2 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/button-validation.html
@@ -24,6 +24,6 @@
   willValid(document.getElementById('btn2'), "submit", true, "submit type attribute");
   willValid(document.getElementById('btn3'), "reset", false, "reset type attribute");
   willValid(document.getElementById('btn4'), "button", false, "button type attribute");
-  willValid(document.getElementById('btn5'), "menu", false, "menu type attribute");
+  willValid(document.getElementById('btn5'), "submit", true, "historical menu type attribute");
   willValid(document.getElementById('btn6'), "submit", true, "invalid type attribute");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
index 27ee274..ea45aef9 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
@@ -74,7 +74,7 @@
 };
 
 [SecureContext, Exposed=Window] interface XRSpace : EventTarget {
-  Float32Array? getTransformTo(XRSpace other);
+  XRRigidTransform? getTransformTo(XRSpace other);
 };
 
 enum XRReferenceSpaceType {
@@ -125,6 +125,7 @@
   readonly attribute XREye eye;
   readonly attribute Float32Array projectionMatrix;
   readonly attribute Float32Array viewMatrix;
+  readonly attribute XRRigidTransform transform;
 };
 
 [SecureContext, Exposed=Window] interface XRViewport {
@@ -134,8 +135,25 @@
   readonly attribute long height;
 };
 
+[SecureContext, Exposed=Window,
+ Constructor(optional DOMPointInit position, optional DOMPointInit orientation)]
+interface XRRigidTransform {
+  readonly attribute DOMPointReadOnly position;
+  readonly attribute DOMPointReadOnly orientation;
+  readonly attribute Float32Array matrix;
+};
+
+[SecureContext, Exposed=Window,
+ Constructor(optional DOMPointInit origin, optional DOMPointInit direction),
+ Constructor(XRRigidTransform transform)]
+interface XRRay {
+  readonly attribute DOMPointReadOnly origin;
+  readonly attribute DOMPointReadOnly direction;
+  readonly attribute Float32Array matrix;
+};
+
 [SecureContext, Exposed=Window] interface XRViewerPose {
-  readonly attribute Float32Array poseMatrix;
+  readonly attribute XRRigidTransform transform;
   readonly attribute FrozenArray<XRView> views;
 };
 
@@ -158,17 +176,10 @@
 };
 
 [SecureContext, Exposed=Window]
-interface XRRay {
-  readonly attribute DOMPointReadOnly origin;
-  readonly attribute DOMPointReadOnly direction;
-  readonly attribute Float32Array transformMatrix;
-};
-
-[SecureContext, Exposed=Window]
 interface XRInputPose {
   readonly attribute boolean emulatedPosition;
   readonly attribute XRRay targetRay;
-  readonly attribute Float32Array? gripMatrix;
+  readonly attribute XRRigidTransform? gripTransform;
 };
 
 [SecureContext, Exposed=Window] interface XRLayer {};
@@ -243,10 +254,10 @@
 [SecureContext, Exposed=Window, Constructor(DOMString type, XRReferenceSpaceEventInit eventInitDict)]
 interface XRReferenceSpaceEvent : Event {
   readonly attribute XRReferenceSpace referenceSpace;
-  readonly attribute Float32Array? transformMatrix;
+  readonly attribute XRRigidTransform? transform;
 };
 
 dictionary XRReferenceSpaceEventInit : EventInit {
   required XRReferenceSpace referenceSpace;
-  Float32Array transformMatrix;
+  XRRigidTransform transform;
 };
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource-timing.js b/third_party/blink/web_tests/external/wpt/resource-timing/resource-timing.js
index c0d072d..8d97b2f 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resource-timing.js
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource-timing.js
@@ -227,7 +227,7 @@
         // Ensure that responseStart only measures the time up to the first few
         // bytes of the header response. This is tested by writing an HTTP 1.1
         // status line, followed by a flush, then a pause before the end of the
-        // headers. The tests makes sure that responseStart is not delayed by
+        // headers. The test makes sure that responseStart is not delayed by
         // this pause.
         [
             { initiator: "iframe",         response: "(done)",    mime: mimeHtml },
@@ -248,12 +248,13 @@
                                         + "&mime:" + template.mime
                                         + "&send:" + encodeURIComponent(template.response)),
                         function (initiator, entry) {
-                            // Test that the delay between 'requestStart' and
-                            // 'responseStart' does not include the added delay
-                            // post-statusline.
-                            assert_less_than(
-                                entry.responseStart - entry.requestStart,
-                                serverStepDelay,
+                            // Test that the delay between 'responseStart' and
+                            // 'responseEnd' includes the delay, which implies
+                            // that 'responseStart' was measured at the time of
+                            // status line receipt.
+                            assert_greater_than_equal(
+                                entry.responseEnd,
+                                entry.responseStart + serverStepDelay,
                                 "Delay after HTTP/1.1 status should not affect 'responseStart'.");
 
                             test.done();
@@ -264,9 +265,9 @@
 
         // Test that responseStart uses the timing of 1XX responses by
         // synthesizing a delay between a 100 and 200 status, and verifying that
-        // responseStart does not include this delay. If the delay is included,
-        // this implies that the 200 status line was (incorrectly) used for
-        // responseStart timing, despite the 100 response arriving earlier.
+        // this delay is included before responseEnd. If the delay is not
+        // included, this implies that the 200 status line was (incorrectly) used
+        // for responseStart timing, despite the 100 response arriving earlier.
         //
         // Source: "In the case where more than one response is available for a
         // request, due to an Informational 1xx response, the reported
@@ -292,9 +293,9 @@
                                         + "&mime:" + template.mime
                                         + "&send:" + encodeURIComponent(template.response)),
                         function (initiator, entry) {
-                            assert_less_than(
-                                entry.responseStart - entry.requestStart,
-                                serverStepDelay,
+                            assert_greater_than_equal(
+                                entry.responseEnd,
+                                entry.responseStart + serverStepDelay,
                                 "HTTP/1.1 1XX (first) response should determine 'responseStart' timing.");
 
                             test.done();
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
index 70f7fa6..51e4af4 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -95,6 +95,7 @@
 PASS XRView interface: attribute eye
 PASS XRView interface: attribute projectionMatrix
 FAIL XRView interface: attribute viewMatrix assert_true: The prototype object must have a property "viewMatrix" expected true got false
+FAIL XRView interface: attribute transform assert_true: The prototype object must have a property "transform" expected true got false
 PASS XRViewport interface: existence and properties of interface object
 PASS XRViewport interface object length
 PASS XRViewport interface object name
@@ -105,13 +106,31 @@
 PASS XRViewport interface: attribute y
 PASS XRViewport interface: attribute width
 PASS XRViewport interface: attribute height
+FAIL XRRigidTransform interface: existence and properties of interface object assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface object length assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface object name assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: attribute position assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: attribute orientation assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+FAIL XRRigidTransform interface: attribute matrix assert_own_property: self does not have own property "XRRigidTransform" expected property "XRRigidTransform" missing
+PASS XRRay interface: existence and properties of interface object
+PASS XRRay interface object length
+PASS XRRay interface object name
+PASS XRRay interface: existence and properties of interface prototype object
+PASS XRRay interface: existence and properties of interface prototype object's "constructor" property
+PASS XRRay interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRRay interface: attribute origin
+PASS XRRay interface: attribute direction
+FAIL XRRay interface: attribute matrix assert_true: The prototype object must have a property "matrix" expected true got false
 FAIL XRViewerPose interface: existence and properties of interface object assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface object length assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface object name assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
-FAIL XRViewerPose interface: attribute poseMatrix assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
+FAIL XRViewerPose interface: attribute transform assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 FAIL XRViewerPose interface: attribute views assert_own_property: self does not have own property "XRViewerPose" expected property "XRViewerPose" missing
 PASS XRInputSource interface: existence and properties of interface object
 PASS XRInputSource interface object length
@@ -121,15 +140,6 @@
 PASS XRInputSource interface: existence and properties of interface prototype object's @@unscopables property
 PASS XRInputSource interface: attribute handedness
 PASS XRInputSource interface: attribute targetRayMode
-PASS XRRay interface: existence and properties of interface object
-PASS XRRay interface object length
-PASS XRRay interface object name
-PASS XRRay interface: existence and properties of interface prototype object
-PASS XRRay interface: existence and properties of interface prototype object's "constructor" property
-PASS XRRay interface: existence and properties of interface prototype object's @@unscopables property
-PASS XRRay interface: attribute origin
-PASS XRRay interface: attribute direction
-PASS XRRay interface: attribute transformMatrix
 PASS XRInputPose interface: existence and properties of interface object
 PASS XRInputPose interface object length
 PASS XRInputPose interface object name
@@ -138,7 +148,7 @@
 PASS XRInputPose interface: existence and properties of interface prototype object's @@unscopables property
 PASS XRInputPose interface: attribute emulatedPosition
 PASS XRInputPose interface: attribute targetRay
-PASS XRInputPose interface: attribute gripMatrix
+FAIL XRInputPose interface: attribute gripTransform assert_true: The prototype object must have a property "gripTransform" expected true got false
 PASS XRLayer interface: existence and properties of interface object
 PASS XRLayer interface object length
 PASS XRLayer interface object name
@@ -191,7 +201,7 @@
 FAIL XRReferenceSpaceEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
 FAIL XRReferenceSpaceEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
 FAIL XRReferenceSpaceEvent interface: attribute referenceSpace assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
-FAIL XRReferenceSpaceEvent interface: attribute transformMatrix assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
+FAIL XRReferenceSpaceEvent interface: attribute transform assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
 FAIL WebGLRenderingContext interface: operation makeXRCompatible() assert_own_property: interface prototype object missing non-static operation expected property "makeXRCompatible" missing
 PASS Navigator interface: attribute xr
 PASS Navigator interface: navigator must inherit property "xr" with the proper type
diff --git a/third_party/blink/web_tests/fast/forms/formdata-event/formdata-event.html b/third_party/blink/web_tests/fast/forms/formdata-event/formdata-event.html
index 4080523..94ff430 100644
--- a/third_party/blink/web_tests/fast/forms/formdata-event/formdata-event.html
+++ b/third_party/blink/web_tests/fast/forms/formdata-event/formdata-event.html
@@ -91,12 +91,15 @@
 
 test(() => {
   let form = populateForm('<input name=n1 value=v1>');
+  let formDataInEvent = null;
   form.addEventListener('formdata', (e) => {
     e.formData.append('h1', 'vh1');
+    formDataInEvent = e.formData;
   });
   let formData = new FormData(form);
   assert_equals(formData.get('h1'), 'vh1');
   assert_equals(formData.get('n1'), 'v1');
+  assert_not_equals(formData, formDataInEvent, '"formData" attribute should be different from the FromData object created by "new"');
 }, 'Newly created FormData contains entries added to "formData" IDL attribute of FormDataEvent.');
 
 test(() => {
diff --git a/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined-expected.txt b/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined-expected.txt
new file mode 100644
index 0000000..68bc3bdd
--- /dev/null
+++ b/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined-expected.txt
@@ -0,0 +1,5 @@
+PASS new Intl.DateTimeFormat('en').resolvedOptions().timeZone is defined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined.html b/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined.html
new file mode 100644
index 0000000..7c6eebe
--- /dev/null
+++ b/third_party/blink/web_tests/fast/js/regress/resolved-timezone-defined.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+</head>
+<body>
+<script src="script-tests/resolved-timezone-defined.js"></script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/fast/js/regress/script-tests/resolved-timezone-defined.js b/third_party/blink/web_tests/fast/js/regress/script-tests/resolved-timezone-defined.js
new file mode 100644
index 0000000..48c7407
--- /dev/null
+++ b/third_party/blink/web_tests/fast/js/regress/script-tests/resolved-timezone-defined.js
@@ -0,0 +1,5 @@
+// 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.
+
+shouldBeDefined("new Intl.DateTimeFormat('en').resolvedOptions().timeZone");
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/4402375-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/4402375-expected.png
index 1ce76b5..b4f8160 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/4402375-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/4402375-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/transformed-selection-rects-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/transformed-selection-rects-expected.png
index 1af763e4..ddf66e8 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/transformed-selection-rects-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/editing/selection/transformed-selection-rects-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/text/foreignObject-text-clipping-bug-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/text/foreignObject-text-clipping-bug-expected.png
index c5ce752..4a9abd2 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/text/foreignObject-text-clipping-bug-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/text/foreignObject-text-clipping-bug-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug50695-2-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug50695-2-expected.png
new file mode 100644
index 0000000..dfd6c5e
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug50695-2-expected.png
Binary files differ
diff --git a/third_party/minizip/BUILD.gn b/third_party/minizip/BUILD.gn
index f84bcd2..ff5bc469 100644
--- a/third_party/minizip/BUILD.gn
+++ b/third_party/minizip/BUILD.gn
@@ -29,10 +29,10 @@
   ]
 
   defines = [
-    "MZ_VERSION_MADEBY_HOST_SYSTEM=MZ_HOST_SYSTEM_UNIX",
     "HAVE_ZLIB",
     "HAVE_PKCRYPT",
-    "HAVE_AES",
+    "HAVE_WZAES",
+    "HAVE_STDINT_H",
 
     # This isn't actually low entropy. It just allows for an OS-specific
     # random number generator.
diff --git a/third_party/minizip/README.chromium b/third_party/minizip/README.chromium
index 85a56c2..cc7f42b 100644
--- a/third_party/minizip/README.chromium
+++ b/third_party/minizip/README.chromium
@@ -1,8 +1,8 @@
 Name: nmoinvaz/minizip
 Short name: minizip
 URL: https://github.com/nmoinvaz/minizip
-Version: 0
-Revision: 4d4c9db5b019e71b4a40fb41ab21fb47de12ae69
+Version: 2.8.1
+Revision: 1ff40343b55e738d941abb51c70eddb803db16e2
 Security critical: yes
 License: Custom license
 License File: src/LICENSE
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b943b1f..60b9cd6a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -32564,6 +32564,31 @@
   <int value="22" label="MacBookPro5,X"/>
 </enum>
 
+<enum name="MachineLearningServiceCreateGraphExecutorResultEvent">
+  <int value="0" label="OK"/>
+  <int value="1" label="MODEL_INTERPRETATION_ERROR"/>
+  <int value="2" label="MEMORY_ALLOCATION_ERROR"/>
+</enum>
+
+<enum name="MachineLearningServiceExecuteResultEvent">
+  <int value="0" label="OK"/>
+  <int value="1" label="MEMORY_ALLOCATION_ERROR"/>
+  <int value="2" label="UNKNOWN_INPUT_ERROR"/>
+  <int value="3" label="INPUT_TYPE_ERROR"/>
+  <int value="4" label="INPUT_SHAPE_ERROR"/>
+  <int value="5" label="INPUT_FORMAT_ERROR"/>
+  <int value="6" label="OUTPUT_MISSING_ERROR"/>
+  <int value="7" label="UNKNOWN_OUTPUT_ERROR"/>
+  <int value="8" label="DUPLICATE_OUTPUT_ERROR"/>
+  <int value="9" label="EXECUTION_ERROR"/>
+</enum>
+
+<enum name="MachineLearningServiceLoadModelResultEvent">
+  <int value="0" label="OK"/>
+  <int value="1" label="MODEL_SPEC_ERROR"/>
+  <int value="2" label="LOAD_MODEL_ERROR"/>
+</enum>
+
 <enum name="MachineLearningServiceMojoConnectionEvent">
   <int value="0" label="Mojo bootstrap requested over D-Bus"/>
   <int value="1" label="Mojo bootstrap succeeded"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 188441b..dac32d7 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -44347,6 +44347,18 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="MachineLearningService.CpuTimeMicrosec"
+    units="microseconds">
+<!-- Name completed by histogram_suffixes
+     name="MachineLearningServiceRequests" -->
+
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>
+    CPU time (for one CPU core) of one Chrome OS ML Service request.
+  </summary>
+</histogram>
+
 <histogram name="MachineLearningService.CpuUsageMilliPercent"
     units="1/1000ths of %" expires_after="2019-03-01">
   <owner>amoylan@chromium.org</owner>
@@ -44356,6 +44368,43 @@
   </summary>
 </histogram>
 
+<histogram name="MachineLearningService.CreateGraphExecutorResult.Event"
+    enum="MachineLearningServiceCreateGraphExecutorResultEvent">
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>
+    The result of CreateGraphExecutor, which can be OK or some specific error.
+  </summary>
+</histogram>
+
+<histogram base="true" name="MachineLearningService.ElapsedTimeMicrosec"
+    units="microseconds">
+<!-- Name completed by histogram_suffixes
+     name="MachineLearningServiceRequests" -->
+
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>Elapsed time of one Chrome OS ML Service request.</summary>
+</histogram>
+
+<histogram name="MachineLearningService.ExecuteResult.Event"
+    enum="MachineLearningServiceExecuteResultEvent">
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>
+    The result of Execute, which can be OK or some specific error.
+  </summary>
+</histogram>
+
+<histogram name="MachineLearningService.LoadModelResult.Event"
+    enum="MachineLearningServiceLoadModelResultEvent">
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>
+    The result of LoadModel, which can be OK or some specific error.
+  </summary>
+</histogram>
+
 <histogram name="MachineLearningService.MojoConnectionEvent"
     enum="MachineLearningServiceMojoConnectionEvent" expires_after="2019-03-01">
   <owner>amoylan@chromium.org</owner>
@@ -44374,6 +44423,18 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="MachineLearningService.PrivateMemoryDeltaKb"
+    units="KB">
+<!-- Name completed by histogram_suffixes
+     name="MachineLearningServiceRequests" -->
+
+  <owner>amoylan@chromium.com</owner>
+  <owner>alanlxl@chromium.com</owner>
+  <summary>
+    Memory usage increase caused by one Chrome OS ML Service request.
+  </summary>
+</histogram>
+
 <histogram name="MachineLearningService.PrivateMemoryKb" units="KB"
     expires_after="2019-03-01">
   <owner>amoylan@chromium.org</owner>
@@ -132957,6 +133018,16 @@
   <affected-histogram name="Media.Audio.InputStartupSuccessMac"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="MachineLearningServiceRequests" separator="."
+    ordering="prefix">
+  <suffix name="CreateGraphExecutorResult"/>
+  <suffix name="ExecuteResult"/>
+  <suffix name="LoadModelResult"/>
+  <affected-histogram name="MachineLearningService.CpuTimeMicrosec"/>
+  <affected-histogram name="MachineLearningService.ElapsedTimeMicrosec"/>
+  <affected-histogram name="MachineLearningService.PrivateMemoryDeltaKb"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="MainFrameNavigation" separator="_">
   <suffix name="MainFrame" label="Main frame navigation."/>
   <affected-histogram name="ServiceWorker.NavPreload.ConcurrentTime"/>
diff --git a/tools/traffic_annotation/OWNERS b/tools/traffic_annotation/OWNERS
index 84cd08c..b57a96b1 100644
--- a/tools/traffic_annotation/OWNERS
+++ b/tools/traffic_annotation/OWNERS
@@ -1,5 +1,4 @@
 battre@chromium.org
 georgesak@chromium.org
 msramek@chromium.org
-privard@chromium.org
 rhalavati@chromium.org
diff --git a/tools/traffic_annotation/summary/OWNERS b/tools/traffic_annotation/summary/OWNERS
index 6bbb64de..35033cb 100644
--- a/tools/traffic_annotation/summary/OWNERS
+++ b/tools/traffic_annotation/summary/OWNERS
@@ -4,6 +4,6 @@
 georgesak@chromium.org
 mkwst@chromium.org
 msramek@chromium.org
-privard@chromium.org
+nicolaso@chromium.org
 rhalavati@chromium.org
 tnagel@chromium.org
diff --git a/ui/accessibility/ax_language_info_unittest.cc b/ui/accessibility/ax_language_info_unittest.cc
index c15e9b7..464aa59 100644
--- a/ui/accessibility/ax_language_info_unittest.cc
+++ b/ui/accessibility/ax_language_info_unittest.cc
@@ -17,12 +17,11 @@
 
 // Tests that AXNode::GetLanguage() terminates when there is no lang attribute.
 TEST(AXLanguageInfoTest, TestGetLanguageNoLangAttr) {
-  /* build tree including parenting, this is to exercise the code paths within
-   * AXNode::GetLanguage() which scan up the tree to handle lang inheritance.
-   *      1
-   *    2   3
-   *  4
-   */
+  // build tree including parenting, this is to exercise the code paths within
+  // AXNode::GetLanguage() which scan up the tree to handle lang inheritance.
+  //      1
+  //    2   3
+  //  4
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
   initial_state.nodes.resize(4);
@@ -68,17 +67,16 @@
 }
 
 TEST(AXLanguageInfoTest, TestGetLanguageLangAttrInheritance) {
-  /* build tree including parenting, this is to exercise the code paths within
-   * AXNode::GetLanguage() which scan up the tree to handle lang inheritance.
-   *        1
-   *      2   3
-   *    4
-   *  5
-   *
-   *  1 - English
-   *  2 - French
-   *  all other nodes are unspecified
-   */
+  // build tree including parenting, this is to exercise the code paths within
+  // AXNode::GetLanguage() which scan up the tree to handle lang inheritance.
+  //        1
+  //      2   3
+  //    4
+  //  5
+  //
+  //  1 - English
+  //  2 - French
+  //  all other nodes are unspecified
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
   initial_state.nodes.resize(5);
@@ -121,4 +119,98 @@
   EXPECT_EQ(item5_lang, "fr");
 }
 
+TEST(AXLanguageInfoTest, TestGetLanguageLangDetection) {
+  // build tree including parenting, this is to exercise the code paths within
+  // AXNode::GetLanguage() which scan up the tree to handle lang inheritance.
+  //        1
+  //      2   3
+  //    4
+  //  5
+  //
+  //  1 - English lang attribute, no text
+  //  2 - French lang attribute,  no text
+  //  3 - no attribute,           French text
+  //  4 - no attribute,           English text
+  //  5 - no attribute,           German text
+  AXTreeUpdate initial_state;
+  initial_state.root_id = 1;
+  initial_state.nodes.resize(5);
+
+  {
+    AXNodeData& node1 = initial_state.nodes[0];
+    node1.id = 1;
+    node1.child_ids.resize(2);
+    node1.child_ids[0] = 2;
+    node1.child_ids[1] = 3;
+    node1.AddStringAttribute(ax::mojom::StringAttribute::kLanguage, "en");
+  }
+
+  {
+    AXNodeData& node2 = initial_state.nodes[1];
+    node2.id = 2;
+    node2.child_ids.resize(1);
+    node2.child_ids[0] = 4;
+    node2.AddStringAttribute(ax::mojom::StringAttribute::kLanguage, "fr");
+  }
+
+  {
+    AXNodeData& node3 = initial_state.nodes[2];
+    node3.id = 3;
+    node3.role = ax::mojom::Role::kStaticText;
+    std::string node3_text =
+        "Ce texte a été créé avec Google Translate, il est peu probable qu'il "
+        "soit idiomatique dans la langue cible indiquée Ce texte est "
+        "uniquement utilisé pour tester la détection de la langue.";
+    node3.AddStringAttribute(ax::mojom::StringAttribute::kName, node3_text);
+  }
+
+  {
+    AXNodeData& node4 = initial_state.nodes[3];
+    node4.id = 4;
+    node4.child_ids.resize(1);
+    node4.child_ids[0] = 5;
+    node4.role = ax::mojom::Role::kStaticText;
+    std::string node4_text =
+        "This is text created using Google Translate, it is unlikely to be "
+        "idomatic in the given target langauge. This text is only used to test "
+        "language detection";
+    node4.AddStringAttribute(ax::mojom::StringAttribute::kName, node4_text);
+  }
+
+  {
+    AXNodeData& node5 = initial_state.nodes[4];
+    node5.id = 5;
+    node5.role = ax::mojom::Role::kStaticText;
+    std::string node5_text =
+        "Dies ist ein mit Google Translate erstellter Text. Es ist "
+        "unwahrscheinlich, dass er in der angegebenen Zielsprache idiomatisch "
+        "ist. Dieser Text wird nur zum Testen der Spracherkennung verwendet.";
+    node5.AddStringAttribute(ax::mojom::StringAttribute::kName, node5_text);
+  }
+
+  AXTree tree(initial_state);
+
+  // TODO(crbug/889370): these expectations will be wrong once we detect
+  // language from the text.
+  AXNode* item1 = tree.GetFromId(1);
+  std::string item1_lang = item1->GetLanguage();
+  EXPECT_EQ(item1_lang, "en");
+
+  AXNode* item2 = tree.GetFromId(2);
+  std::string item2_lang = item2->GetLanguage();
+  EXPECT_EQ(item2_lang, "fr");
+
+  AXNode* item3 = tree.GetFromId(3);
+  std::string item3_lang = item3->GetLanguage();
+  EXPECT_EQ(item3_lang, "en");
+
+  AXNode* item4 = tree.GetFromId(4);
+  std::string item4_lang = item4->GetLanguage();
+  EXPECT_EQ(item4_lang, "fr");
+
+  AXNode* item5 = tree.GetFromId(5);
+  std::string item5_lang = item5->GetLanguage();
+  EXPECT_EQ(item5_lang, "fr");
+}
+
 }  // namespace ui
diff --git a/ui/file_manager/integration_tests/file_manager/zip_files.js b/ui/file_manager/integration_tests/file_manager/zip_files.js
index 24d67fd..febe6952 100644
--- a/ui/file_manager/integration_tests/file_manager/zip_files.js
+++ b/ui/file_manager/integration_tests/file_manager/zip_files.js
@@ -213,7 +213,7 @@
 function getZipSelectionFileListRowEntries() {
   return [
     ['photos', '--', 'Folder', 'Jan 1, 1980, 11:59 PM'],
-    ['photos.zip', '206 bytes', 'Zip archive', 'Oct 21, 1983, 11:55 AM']
+    ['photos.zip', '214 bytes', 'Zip archive', 'Oct 21, 1983, 11:55 AM']
   ];
 }