diff --git a/DEPS b/DEPS
index d9c1ae7..dbf21c3 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,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': '6d3af6faa23a931be1404cd3fcba02a3c271151c',
+  'skia_revision': '32fa5104148722dbd6aac1ce8d38dcf47737f669',
   # 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': '547d6a869d38e6c08a5d038abd1477530d01f9cc',
+  'v8_revision': 'f1317ecc526a2026e55c9bd6c532c3046defdeaa',
   # 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.
@@ -238,7 +238,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'c0b94eed5babc4ca5af32453a53d49e3ca155fcd', # commit position 19300
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '4a604c80cecce18aff6fc5e16296d04675312d83', # commit position 19324
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/base/android/scoped_java_ref.h b/base/android/scoped_java_ref.h
index 6d728e9..12d418d 100644
--- a/base/android/scoped_java_ref.h
+++ b/base/android/scoped_java_ref.h
@@ -286,7 +286,9 @@
  public:
   JavaRefOrBare(std::nullptr_t) : obj_(nullptr) {}
   JavaRefOrBare(const JavaRef<T>& ref) : obj_(ref.obj()) {}
-  JavaRefOrBare(T obj) : obj_(obj) {}
+  // TODO(torne): this is no longer permitted; remove the entire class and just
+  // use JavaRef once this removal sticks.
+  // JavaRefOrBare(T obj) : obj_(obj) {}
   T obj() const { return obj_; }
 
  private:
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index d153e23..a48f9df 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -74,8 +74,6 @@
     "perf_time_logger.h",
     "power_monitor_test_base.cc",
     "power_monitor_test_base.h",
-    "scoped_async_task_scheduler.cc",
-    "scoped_async_task_scheduler.h",
     "scoped_command_line.cc",
     "scoped_command_line.h",
     "scoped_environment_variable_override.cc",
diff --git a/base/test/scoped_async_task_scheduler.cc b/base/test/scoped_async_task_scheduler.cc
deleted file mode 100644
index adabed2..0000000
--- a/base/test/scoped_async_task_scheduler.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/test/scoped_async_task_scheduler.h"
-
-#include "base/logging.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
-#include "base/task_scheduler/task_scheduler.h"
-
-namespace base {
-namespace test {
-
-ScopedAsyncTaskScheduler::ScopedAsyncTaskScheduler() {
-  DCHECK(!TaskScheduler::GetInstance());
-
-  // Instantiate a TaskScheduler with 2 threads in each of its 4 pools. Threads
-  // stay alive even when they don't have work.
-  // Each pool uses two threads to prevent deadlocks in unit tests that have a
-  // sequence that uses WithBaseSyncPrimitives() to wait on the result of
-  // another sequence. This isn't perfect (doesn't solve wait chains) but solves
-  // the basic use case for now.
-  // TODO(fdoray/jeffreyhe): Make the TaskScheduler dynamically replace blocked
-  // threads and get rid of this limitation. http://crbug.com/738104
-  constexpr int kMaxThreads = 2;
-  const TimeDelta kSuggestedReclaimTime = TimeDelta::Max();
-  const SchedulerWorkerPoolParams worker_pool_params(kMaxThreads,
-                                                     kSuggestedReclaimTime);
-  TaskScheduler::Create("ScopedAsync");
-  task_scheduler_ = TaskScheduler::GetInstance();
-  TaskScheduler::GetInstance()->Start({worker_pool_params, worker_pool_params,
-                                       worker_pool_params, worker_pool_params});
-}
-
-ScopedAsyncTaskScheduler::~ScopedAsyncTaskScheduler() {
-  DCHECK_EQ(TaskScheduler::GetInstance(), task_scheduler_);
-  // Without FlushForTesting(), DeleteSoon() and ReleaseSoon() tasks could be
-  // skipped, resulting in memory leaks.
-  TaskScheduler::GetInstance()->FlushForTesting();
-  TaskScheduler::GetInstance()->Shutdown();
-  TaskScheduler::GetInstance()->JoinForTesting();
-  TaskScheduler::SetInstance(nullptr);
-}
-
-}  // namespace test
-}  // namespace base
diff --git a/base/test/scoped_async_task_scheduler.h b/base/test/scoped_async_task_scheduler.h
deleted file mode 100644
index 29a543f..0000000
--- a/base/test/scoped_async_task_scheduler.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TEST_SCOPED_ASYNC_TASK_SCHEDULER_H_
-#define BASE_TEST_SCOPED_ASYNC_TASK_SCHEDULER_H_
-
-#include "base/macros.h"
-#include "base/task_scheduler/lazy_task_runner.h"
-
-namespace base {
-
-class TaskScheduler;
-
-namespace test {
-
-// DEPRECATED. Use ScopedTaskEnvironment instead.
-//
-// TODO(fdoray): Replace ScopedAsyncTaskScheduler instances by
-// ScopedTaskEnvironment. https://crbug.com/708584
-//
-// Allows usage of the base/task_scheduler/post_task.h API within its scope.
-//
-// To wait until all tasks posted without a delay have run, use
-// TaskScheduler::GetInstance()->FlushForTesting().
-class ScopedAsyncTaskScheduler {
- public:
-  // Registers a single-threaded TaskScheduler.
-  ScopedAsyncTaskScheduler();
-
-  // Shuts down and unregisters the TaskScheduler.
-  //
-  // It is guaranteed that all BLOCK_SHUTDOWN tasks have run when this returns.
-  ~ScopedAsyncTaskScheduler();
-
- private:
-  const TaskScheduler* task_scheduler_ = nullptr;
-
-  // Ensures destruction of lazy TaskRunners when this is destroyed.
-  internal::ScopedLazyTaskRunnerListForTesting
-      scoped_lazy_task_runner_list_for_testing_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAsyncTaskScheduler);
-};
-
-}  // namespace test
-}  // namespace base
-
-#endif  // BASE_TEST_SCOPED_ASYNC_TASK_SCHEDULER_H_
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS
index 553994e..343a3db 100644
--- a/base/trace_event/OWNERS
+++ b/base/trace_event/OWNERS
@@ -5,5 +5,8 @@
 simonhatch@chromium.org
 per-file trace_event_android.cc=wangxianzhu@chromium.org
 
+# For memory-infra related changes
+ssid@chromium.org
+
 # TEAM: tracing@chromium.org
 # COMPONENT: Speed>Tracing
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
index e2e6d31..bd31c0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -240,6 +240,7 @@
     @Override
     public void setWebappIntentExtras(Intent intent) {
         // For launching a {@link WebApkActivity}.
+        intent.putExtra(ShortcutHelper.EXTRA_ID, id());
         intent.putExtra(ShortcutHelper.EXTRA_URL, uri().toString());
         intent.putExtra(ShortcutHelper.EXTRA_SOURCE, source());
         intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackageName());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 5dfa369..c9f6a4b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -49,6 +49,7 @@
 import org.chromium.ui.base.PageTransition;
 
 import java.io.File;
+import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -87,6 +88,14 @@
 
     private Runnable mSetImmersiveRunnable;
 
+    /** Initialization-on-demand holder. This exists for thread-safe lazy initialization. */
+    private static class Holder {
+        // This static map is used to cache WebappInfo objects between their initial creation in
+        // WebappLauncherActivity and final use in WebappActivity.
+        private static final HashMap<String, WebappInfo> sWebappInfoMap =
+                new HashMap<String, WebappInfo>();
+    }
+
     /**
      * Construct all the variables that shouldn't change.  We do it here both to clarify when the
      * objects are created and to ensure that they exist throughout the parallelized initialization
@@ -107,7 +116,9 @@
         if (intent == null) return;
         super.onNewIntent(intent);
 
-        WebappInfo newWebappInfo = createWebappInfo(intent);
+        WebappInfo newWebappInfo = popWebappInfo(WebappInfo.idFromIntent(intent));
+        if (newWebappInfo == null) newWebappInfo = createWebappInfo(intent);
+
         if (newWebappInfo == null) {
             Log.e(TAG, "Failed to parse new Intent: " + intent);
             ApiCompatibilityUtils.finishAndRemoveTask(this);
@@ -143,21 +154,21 @@
 
     @Override
     public void preInflationStartup() {
-        WebappInfo info = createWebappInfo(getIntent());
-
-        String id = "";
-        if (info != null) {
-            mWebappInfo = info;
-            id = info.id();
+        Intent intent = getIntent();
+        WebappInfo info = popWebappInfo(WebappInfo.idFromIntent(intent));
+        if (info == null) {
+            info = createWebappInfo(intent);
         }
 
+        mWebappInfo = info;
+
         // Initialize the WebappRegistry and warm up the shared preferences for this web app. No-ops
         // if the registry and this web app are already initialized. Must override Strict Mode to
         // avoid a violation.
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
         try {
             WebappRegistry.getInstance();
-            WebappRegistry.warmUpSharedPrefsForId(id);
+            WebappRegistry.warmUpSharedPrefsForId(info.id());
         } finally {
             StrictMode.setThreadPolicy(oldPolicy);
         }
@@ -252,7 +263,6 @@
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
 
         if (mSetImmersiveRunnable == null) {
-
             final View decor = getWindow().getDecorView();
 
             mSetImmersiveRunnable = new Runnable() {
@@ -363,6 +373,14 @@
         return mWebappInfo.scopeUri().toString();
     }
 
+    public static void addWebappInfo(String id, WebappInfo info) {
+        Holder.sWebappInfoMap.put(id, info);
+    }
+
+    public static WebappInfo popWebappInfo(String id) {
+        return Holder.sWebappInfoMap.remove(id);
+    }
+
     private void initializeWebappData() {
         if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) {
             enterImmersiveMode();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
index c7ea6f8..d66a37c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -108,9 +108,10 @@
      * @param intent Intent containing info about the app.
      */
     public static WebappInfo create(Intent intent) {
-        String id = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ID);
-        String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON);
+        String id = idFromIntent(intent);
         String url = urlFromIntent(intent);
+
+        String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON);
         String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE);
         int displayMode = IntentUtils.safeGetIntExtra(
                 intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.STANDALONE);
@@ -323,6 +324,9 @@
         intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, isIconGenerated());
     }
 
+    public static String idFromIntent(Intent intent) {
+        return IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ID);
+    }
     /**
      * Returns true if the WebappInfo was created for an Intent fired from a launcher shortcut (as
      * opposed to an intent from a push notification or other internal source).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
index d9a8642..8a47bc8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
@@ -89,6 +89,12 @@
                 source = getWebApkSource(webappInfo);
             }
             LaunchMetrics.recordHomeScreenLaunchIntoStandaloneActivity(webappUrl, source);
+
+            // Add all information needed to launch WebappActivity without {@link
+            // WebappActivity#sWebappInfoMap} to launch intent. When the Android OS has killed a
+            // WebappActivity and the user selects the WebappActivity from "Android Recents" the
+            // WebappActivity is launched without going through WebappLauncherActivity first.
+            WebappActivity.addWebappInfo(webappInfo.id(), webappInfo);
             Intent launchIntent = createWebappLaunchIntent(webappInfo, webappSource, validWebApk);
             startActivity(launchIntent);
             return;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
index e768942..dc4da25 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -28,6 +28,7 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.EnormousTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
@@ -596,7 +597,8 @@
      * Test to verify that the security icon is present when visiting http:// URLs.
      */
     @Test
-    @MediumTest
+    //@MediumTest
+    @DisabledTest(message = "crbug.com/754723")
     public void testSecurityIconOnHTTP() throws InterruptedException {
         EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer(
                 InstrumentationRegistry.getInstrumentation().getContext());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
index f9d4d81..5ec7b59 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -8,6 +8,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.view.View;
@@ -271,6 +272,38 @@
         });
     }
 
+    /**
+     * Test that a WebappActivity uses WebappInfo set via WebappActivity#putWebappInfo() if
+     * available instead of constructing the WebappInfo from the launch intent.
+     */
+    @Test
+    @MediumTest
+    @Feature({"Webapps"})
+    public void testWebappInfoReuse() throws Exception {
+        Intent intent = createIntent(
+                WebappActivityTestRule.WEBAPP_ID, WEBAPP_2_URL, WEBAPP_2_TITLE, WEBAPP_ICON, true);
+        Intent newIntent = createIntent(
+                WebappActivityTestRule.WEBAPP_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true);
+        WebappInfo webappInfo = WebappInfo.create(intent);
+        WebappActivity.addWebappInfo(WebappActivityTestRule.WEBAPP_ID, webappInfo);
+
+        WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
+        mActivityTestRule.startWebappActivity(newIntent);
+
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return isWebappActivityReady(ApplicationStatus.getLastTrackedFocusedActivity());
+            }
+        });
+
+        Activity lastActivity = ApplicationStatus.getLastTrackedFocusedActivity();
+        WebappActivity lastWebappActivity = (WebappActivity) lastActivity;
+
+        Assert.assertEquals(webappInfo, lastWebappActivity.getWebappInfo());
+        Assert.assertTrue(lastWebappActivity.getWebappInfo().uri().equals(Uri.parse(WEBAPP_2_URL)));
+    }
+
     /** Test that on first launch {@link WebappDataStorage#hasBeenLaunched()} is set. */
     // Flaky even with RetryOnFailure: http://crbug.com/749375
     @DisabledTest
diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
index a46c68e..12e0128 100644
--- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
@@ -186,7 +186,8 @@
          shell_integration::UNKNOWN_DEFAULT, false, true, false);
 }
 
-TEST_F(ExternalProtocolHandlerTest, TestLaunchSchemeUnknownChromeDefault) {
+TEST_F(ExternalProtocolHandlerTest,
+       DISABLED_TestLaunchSchemeUnknownChromeDefault) {
   DoTest(ExternalProtocolHandler::UNKNOWN, shell_integration::IS_DEFAULT, false,
          false, true);
 }
diff --git a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
index cf591000..646f65a 100644
--- a/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
@@ -358,8 +358,15 @@
 
 #if BUILDFLAG(RTC_USE_H264)
 
+// Flaky on mac: crbug.com/754684
+#if defined(OS_MACOSX)
+#define MAYBE_MANUAL_TestVideoQualityH264 DISABLED_MANUAL_TestVideoQualityH264
+#else
+#define MAYBE_MANUAL_TestVideoQualityH264 MANUAL_TestVideoQualityH264
+#endif
+
 IN_PROC_BROWSER_TEST_P(WebRtcVideoQualityBrowserTest,
-                       MANUAL_TestVideoQualityH264) {
+                       MAYBE_MANUAL_TestVideoQualityH264) {
   base::ThreadRestrictions::ScopedAllowIO allow_io;
   // Only run test if run-time feature corresponding to |rtc_use_h264| is on.
   if (!base::FeatureList::IsEnabled(content::kWebRtcH264WithOpenH264FFmpeg)) {
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc
index 67206d9..c364224 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -33,10 +33,6 @@
 #include "ui/display/display.h"
 #include "ui/events/event_utils.h"
 
-#if defined(USE_X11)
-#include "ui/events/devices/x11/touch_factory_x11.h"
-#endif  // defined(USE_X11)
-
 using metrics::ChromeUserMetricsExtension;
 using metrics::SampledProfile;
 using metrics::SystemProfileProto;
@@ -82,18 +78,8 @@
 }
 
 void WriteExternalTouchscreensProto(SystemProfileProto::Hardware* hardware) {
-#if defined(USE_X11)
-  std::set<std::pair<int, int> > touchscreen_ids =
-      ui::TouchFactory::GetInstance()->GetTouchscreenIds();
-  for (std::set<std::pair<int, int> >::iterator it = touchscreen_ids.begin();
-       it != touchscreen_ids.end();
-       ++it) {
-    SystemProfileProto::Hardware::TouchScreen* touchscreen =
-        hardware->add_external_touchscreen();
-    touchscreen->set_vendor_id(it->first);
-    touchscreen->set_product_id(it->second);
-  }
-#endif  // defined(USE_X11)
+  // TODO: this needs to be converted to Ozone, or remove the protos.
+  NOTIMPLEMENTED();
 }
 
 void IncrementPrefValue(const char* path) {
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
index d5e57cd..d9e5b69 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -28,10 +28,6 @@
 #include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(USE_X11)
-#include "ui/events/devices/x11/device_data_manager_x11.h"
-#endif
-
 using bluez::BluetoothAdapterClient;
 using bluez::BluetoothAgentManagerClient;
 using bluez::BluetoothDeviceClient;
@@ -59,9 +55,6 @@
 
  protected:
   void SetUp() override {
-#if defined(USE_X11)
-    ui::DeviceDataManagerX11::CreateInstance();
-#endif
 
     // Set up the fake Bluetooth environment,
     std::unique_ptr<BluezDBusManagerSetter> bluez_dbus_setter =
diff --git a/chrome/browser/metrics/tab_stats_tracker.cc b/chrome/browser/metrics/tab_stats_tracker.cc
index d97655e..4da222e 100644
--- a/chrome/browser/metrics/tab_stats_tracker.cc
+++ b/chrome/browser/metrics/tab_stats_tracker.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/metrics/tab_stats_tracker.h"
 
+#include "base/metrics/histogram_macros.h"
+#include "base/power_monitor/power_monitor.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -12,6 +14,10 @@
 namespace metrics {
 
 // static
+const char TabStatsTracker::UmaStatsReportingDelegate::
+    kNumberOfTabsOnResumeHistogramName[] = "Tabs.NumberOfTabsOnResume";
+
+// static
 void TabStatsTracker::Initialize() {
   // Calls GetInstance() to initialize the static instance.
   GetInstance();
@@ -23,7 +29,10 @@
   return instance;
 }
 
-TabStatsTracker::TabStatsTracker() : total_tabs_count_(0U), browser_count_(0U) {
+TabStatsTracker::TabStatsTracker()
+    : total_tabs_count_(0U),
+      browser_count_(0U),
+      reporting_delegate_(base::MakeUnique<UmaStatsReportingDelegate>()) {
   // Get the list of existing browsers/tabs. There shouldn't be any if this is
   // initialized at startup but this will ensure that the count stay accurate if
   // the initialization gets moved to after the creation of the first tab.
@@ -34,6 +43,9 @@
     total_tabs_count_ += browser->tab_strip_model()->count();
   }
   browser_list->AddObserver(this);
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  if (power_monitor != nullptr)
+    power_monitor->AddObserver(this);
 }
 
 TabStatsTracker::~TabStatsTracker() {
@@ -45,6 +57,10 @@
     total_tabs_count_ -= browser->tab_strip_model()->count();
   }
   browser_list->RemoveObserver(this);
+
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  if (power_monitor != nullptr)
+    power_monitor->RemoveObserver(this);
 }
 
 void TabStatsTracker::OnBrowserAdded(Browser* browser) {
@@ -74,4 +90,13 @@
   --total_tabs_count_;
 }
 
+void TabStatsTracker::OnResume() {
+  reporting_delegate_->ReportTabCountOnResume(total_tabs_count_);
+}
+
+void TabStatsTracker::UmaStatsReportingDelegate::ReportTabCountOnResume(
+    size_t tab_count) {
+  UMA_HISTOGRAM_COUNTS_10000(kNumberOfTabsOnResumeHistogramName, tab_count);
+}
+
 }  // namespace metrics
diff --git a/chrome/browser/metrics/tab_stats_tracker.h b/chrome/browser/metrics/tab_stats_tracker.h
index a0c0901..7f2c7f0 100644
--- a/chrome/browser/metrics/tab_stats_tracker.h
+++ b/chrome/browser/metrics/tab_stats_tracker.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_METRICS_TAB_STATS_TRACKER_H_
 
 #include "base/macros.h"
+#include "base/power_monitor/power_observer.h"
 #include "base/sequence_checker.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
@@ -17,7 +18,8 @@
 // TODO(sebmarchand): This is just a base class and doesn't do much for now,
 // finish this and document the architecture here.
 class TabStatsTracker : public TabStripModelObserver,
-                        public chrome::BrowserListObserver {
+                        public chrome::BrowserListObserver,
+                        public base::PowerObserver {
  public:
   // Creates the |TabStatsTracker| instance and initializes the
   // observers that notify it.
@@ -31,6 +33,10 @@
   size_t browser_count() const { return browser_count_; }
 
  protected:
+  // The UmaStatsReportingDelegate is responsible for delivering statistics
+  // reported by the TabStatsTracker via UMA.
+  class UmaStatsReportingDelegate;
+
   TabStatsTracker();
   ~TabStatsTracker() override;
 
@@ -47,18 +53,41 @@
                     content::WebContents* web_contents,
                     int index) override;
 
+  // base::PowerObserver:
+  void OnResume() override;
+
   // The total number of tabs opened across all the browsers.
   size_t total_tabs_count_;
 
   // The total number of browsers opened.
   size_t browser_count_;
 
+  // The delegate that reports the events.
+  std::unique_ptr<UmaStatsReportingDelegate> reporting_delegate_;
+
  private:
   SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(TabStatsTracker);
 };
 
+// The reporting delegate, which reports metrics via UMA.
+class TabStatsTracker::UmaStatsReportingDelegate {
+ public:
+  // The name of the histogram that records the number of tabs total at resume
+  // from sleep/hibernate.
+  static const char kNumberOfTabsOnResumeHistogramName[];
+
+  UmaStatsReportingDelegate() {}
+  ~UmaStatsReportingDelegate() {}
+
+  // Called at resume from sleep/hibernate.
+  void ReportTabCountOnResume(size_t tab_count);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(UmaStatsReportingDelegate);
+};
+
 }  // namespace metrics
 
 #endif  // CHROME_BROWSER_METRICS_TAB_STATS_TRACKER_H_
diff --git a/chrome/browser/metrics/tab_stats_tracker_unittests.cc b/chrome/browser/metrics/tab_stats_tracker_unittests.cc
index c16de91..e6bea5d 100644
--- a/chrome/browser/metrics/tab_stats_tracker_unittests.cc
+++ b/chrome/browser/metrics/tab_stats_tracker_unittests.cc
@@ -4,17 +4,22 @@
 
 #include "chrome/browser/metrics/tab_stats_tracker.h"
 
+#include "base/message_loop/message_loop.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/power_monitor_test_base.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace metrics {
+namespace {
 
-class TabStatsTrackerTest : public InProcessBrowserTest {
+using TabStatsTracker = metrics::TabStatsTracker;
+
+class TabStatsTrackerBrowserTest : public InProcessBrowserTest {
  public:
-  TabStatsTrackerTest() : tab_stats_tracker_(nullptr) {}
+  TabStatsTrackerBrowserTest() : tab_stats_tracker_(nullptr) {}
 
   void SetUpOnMainThread() override {
     tab_stats_tracker_ = TabStatsTracker::GetInstance();
@@ -23,10 +28,72 @@
  protected:
   TabStatsTracker* tab_stats_tracker_;
 
+  DISALLOW_COPY_AND_ASSIGN(TabStatsTrackerBrowserTest);
+};
+
+class TestTabStatsTracker : public TabStatsTracker {
+ public:
+  using UmaStatsReportingDelegate = TabStatsTracker::UmaStatsReportingDelegate;
+
+  TestTabStatsTracker() {}
+  ~TestTabStatsTracker() override {}
+
+  size_t AddTabs(size_t tab_count) {
+    total_tabs_count_ += tab_count;
+    return total_tabs_count_;
+  }
+
+  size_t RemoveTabs(size_t tab_count) {
+    EXPECT_LE(tab_count, total_tabs_count_);
+    total_tabs_count_ -= tab_count;
+    return total_tabs_count_;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestTabStatsTracker);
+};
+
+class TabStatsTrackerTest : public testing::Test {
+ public:
+  using UmaStatsReportingDelegate =
+      TestTabStatsTracker::UmaStatsReportingDelegate;
+
+  TabStatsTrackerTest() {
+    power_monitor_source_ = new base::PowerMonitorTestSource();
+    power_monitor_.reset(new base::PowerMonitor(
+        std::unique_ptr<base::PowerMonitorSource>(power_monitor_source_)));
+    // The tab stats tracker has to be created after the power monitor has it's
+    // using it.
+    tab_stats_tracker_.reset(new TestTabStatsTracker());
+  }
+
+  void TearDown() override { tab_stats_tracker_.reset(nullptr); }
+
+  // The tabs stat tracker instance, it should be created in the SetUp
+  std::unique_ptr<TestTabStatsTracker> tab_stats_tracker_;
+
+  // Used to simulate power events.
+  base::PowerMonitorTestSource* power_monitor_source_;
+  std::unique_ptr<base::PowerMonitor> power_monitor_;
+
+  // The Power Monitor requires a message loop.
+  base::MessageLoop message_loop_;
+
+  // Used to make sure that the metrics are reported properly.
+  base::HistogramTester histogram_tester_;
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(TabStatsTrackerTest);
 };
 
-IN_PROC_BROWSER_TEST_F(TabStatsTrackerTest,
+// Comparator for base::Bucket values.
+bool CompareHistogramBucket(const base::Bucket& l, const base::Bucket& r) {
+  return l.min < r.min;
+}
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(TabStatsTrackerBrowserTest,
                        TabsAndBrowsersAreCountedAccurately) {
   // Assert that the |TabStatsTracker| instance is initialized during the
   // creation of the main browser.
@@ -54,4 +121,44 @@
   EXPECT_EQ(1U, tab_stats_tracker_->total_tab_count());
 }
 
-}  // namespace metrics
+TEST_F(TabStatsTrackerTest, OnResume) {
+  // Makes sure that there's no sample initially.
+  histogram_tester_.ExpectTotalCount(
+      UmaStatsReportingDelegate::kNumberOfTabsOnResumeHistogramName, 0);
+
+  // Creates some tabs.
+  size_t expected_tab_count = tab_stats_tracker_->AddTabs(12);
+
+  std::vector<base::Bucket> count_buckets;
+  count_buckets.push_back(base::Bucket(expected_tab_count, 1));
+
+  // Generates a resume event that should end up calling the
+  // |ReportTabCountOnResume| method of the reporting delegate.
+  power_monitor_source_->GenerateSuspendEvent();
+  power_monitor_source_->GenerateResumeEvent();
+
+  // There should be only one sample for the |kNumberOfTabsOnResume| histogram.
+  histogram_tester_.ExpectTotalCount(
+      UmaStatsReportingDelegate::kNumberOfTabsOnResumeHistogramName,
+      count_buckets.size());
+  EXPECT_EQ(histogram_tester_.GetAllSamples(
+                UmaStatsReportingDelegate::kNumberOfTabsOnResumeHistogramName),
+            count_buckets);
+
+  // Removes some tabs and update the expectations.
+  expected_tab_count = tab_stats_tracker_->RemoveTabs(5);
+  count_buckets.push_back(base::Bucket(expected_tab_count, 1));
+  std::sort(count_buckets.begin(), count_buckets.end(), CompareHistogramBucket);
+
+  // Generates another resume event.
+  power_monitor_source_->GenerateSuspendEvent();
+  power_monitor_source_->GenerateResumeEvent();
+
+  // There should be 2 samples for this metric now.
+  histogram_tester_.ExpectTotalCount(
+      UmaStatsReportingDelegate::kNumberOfTabsOnResumeHistogramName,
+      count_buckets.size());
+  EXPECT_EQ(histogram_tester_.GetAllSamples(
+                UmaStatsReportingDelegate::kNumberOfTabsOnResumeHistogramName),
+            count_buckets);
+}
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index fa47486..dcac047 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -11,8 +11,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
-#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
 #include "base/time/default_clock.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
@@ -189,12 +187,8 @@
           base::Bind(&safe_json::SafeJsonParser::Parse));
   base::FilePath database_dir(
       profile->GetPath().Append("contextualSuggestionsDatabase"));
-  scoped_refptr<base::SequencedTaskRunner> task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BACKGROUND,
-           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
   auto contextual_suggestions_database =
-      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir, task_runner);
+      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir);
   auto cached_image_fetcher =
       base::MakeUnique<ntp_snippets::CachedImageFetcher>(
           base::MakeUnique<image_fetcher::ImageFetcherImpl>(
@@ -387,7 +381,8 @@
       std::move(subscription_manager),
       base::Bind(&safe_json::SafeJsonParser::Parse),
       base::MakeUnique<base::DefaultClock>(),
-      /*token_validation_timer=*/base::MakeUnique<base::OneShotTimer>());
+      /*token_validation_timer=*/base::MakeUnique<base::OneShotTimer>(),
+      /*forced_subscription_timer=*/base::MakeUnique<base::OneShotTimer>());
 }
 
 #endif  // OS_ANDROID
@@ -417,10 +412,6 @@
 
   base::FilePath database_dir(
       profile->GetPath().Append(ntp_snippets::kDatabaseFolder));
-  scoped_refptr<base::SequencedTaskRunner> task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BACKGROUND,
-           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
   std::string api_key;
   // The API is private. If we don't have the official API key, don't even try.
   if (google_apis::IsGoogleChromeAPIKeyUsed()) {
@@ -461,7 +452,7 @@
       std::move(suggestions_fetcher),
       base::MakeUnique<ImageFetcherImpl>(base::MakeUnique<ImageDecoderImpl>(),
                                          request_context.get()),
-      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir, task_runner),
+      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir),
       base::MakeUnique<RemoteSuggestionsStatusServiceImpl>(
           signin_manager, pref_service, additional_toggle_pref),
       std::move(prefetched_pages_tracker),
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index ffe8359..5f58357 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -222,18 +222,14 @@
 
 LocalNtpSource::LocalNtpSource(Profile* profile)
     : profile_(profile),
-      one_google_bar_service_(nullptr),
+      one_google_bar_service_(
+          OneGoogleBarServiceFactory::GetForProfile(profile_)),
       one_google_bar_service_observer_(this),
       default_search_provider_is_google_(false),
       default_search_provider_is_google_io_thread_(false),
       weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (base::FeatureList::IsEnabled(features::kOneGoogleBarOnLocalNtp)) {
-    one_google_bar_service_ =
-        OneGoogleBarServiceFactory::GetForProfile(profile_);
-  }
-
   // |one_google_bar_service_| is null in incognito, or when the feature is
   // disabled.
   if (one_google_bar_service_)
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
index d3810db..498e781 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.cc
@@ -10,12 +10,10 @@
 #include "base/callback.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chrome/browser/search/one_google_bar/one_google_bar_data.h"
 #include "chrome/common/chrome_content_client.h"
-#include "chrome/common/chrome_features.h"
 #include "components/google/core/browser/google_url_tracker.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/safe_json/safe_json_parser.h"
@@ -135,6 +133,7 @@
   AuthenticatedURLFetcher(net::URLRequestContextGetter* request_context,
                           const GURL& google_base_url,
                           const std::string& application_locale,
+                          const base::Optional<std::string>& api_url_override,
                           FetchDoneCallback callback);
   ~AuthenticatedURLFetcher() override = default;
 
@@ -150,6 +149,7 @@
   net::URLRequestContextGetter* const request_context_;
   const GURL google_base_url_;
   const std::string application_locale_;
+  const base::Optional<std::string> api_url_override_;
 
   FetchDoneCallback callback_;
 
@@ -161,20 +161,16 @@
     net::URLRequestContextGetter* request_context,
     const GURL& google_base_url,
     const std::string& application_locale,
+    const base::Optional<std::string>& api_url_override,
     FetchDoneCallback callback)
     : request_context_(request_context),
       google_base_url_(google_base_url),
       application_locale_(application_locale),
+      api_url_override_(api_url_override),
       callback_(std::move(callback)) {}
 
 GURL OneGoogleBarFetcherImpl::AuthenticatedURLFetcher::GetApiUrl() const {
-  GURL api_url = google_base_url_.Resolve(kApiPath);
-
-  std::string api_url_override = base::GetFieldTrialParamValueByFeature(
-      features::kOneGoogleBarOnLocalNtp, "one-google-api-url");
-  if (!api_url_override.empty()) {
-    api_url = GURL(api_url_override);
-  }
+  GURL api_url = google_base_url_.Resolve(api_url_override_.value_or(kApiPath));
 
   // Add the "hl=" parameter.
   return net::AppendQueryParameter(api_url, "hl", application_locale_);
@@ -236,10 +232,12 @@
 OneGoogleBarFetcherImpl::OneGoogleBarFetcherImpl(
     net::URLRequestContextGetter* request_context,
     GoogleURLTracker* google_url_tracker,
-    const std::string& application_locale)
+    const std::string& application_locale,
+    const base::Optional<std::string>& api_url_override)
     : request_context_(request_context),
       google_url_tracker_(google_url_tracker),
       application_locale_(application_locale),
+      api_url_override_(api_url_override),
       weak_ptr_factory_(this) {}
 
 OneGoogleBarFetcherImpl::~OneGoogleBarFetcherImpl() = default;
@@ -256,7 +254,7 @@
   // something has changed in the meantime (e.g. signin state) that would make
   // the result obsolete.
   pending_request_ = base::MakeUnique<AuthenticatedURLFetcher>(
-      request_context_, google_base_url, application_locale_,
+      request_context_, google_base_url, application_locale_, api_url_override_,
       base::BindOnce(&OneGoogleBarFetcherImpl::FetchDone,
                      base::Unretained(this)));
   pending_request_->Start();
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h
index ec71ddb..1c4eaf4 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h
+++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h
@@ -32,9 +32,12 @@
 // See crbug.com/751534.
 class OneGoogleBarFetcherImpl : public OneGoogleBarFetcher {
  public:
+  // |api_url_override| can be either absolute, or relative to the Google base
+  // URL.
   OneGoogleBarFetcherImpl(net::URLRequestContextGetter* request_context,
                           GoogleURLTracker* google_url_tracker,
-                          const std::string& application_locale);
+                          const std::string& application_locale,
+                          const base::Optional<std::string>& api_url_override);
   ~OneGoogleBarFetcherImpl() override;
 
   void Fetch(OneGoogleCallback callback) override;
@@ -52,6 +55,7 @@
   net::URLRequestContextGetter* request_context_;
   GoogleURLTracker* google_url_tracker_;
   const std::string application_locale_;
+  const base::Optional<std::string> api_url_override_;
 
   std::vector<OneGoogleCallback> callbacks_;
   std::unique_ptr<AuthenticatedURLFetcher> pending_request_;
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc
index b26b093..491a61b 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/mock_callback.h"
@@ -57,7 +58,10 @@
 
 class OneGoogleBarFetcherImplTest : public testing::Test {
  public:
-  OneGoogleBarFetcherImplTest()
+  OneGoogleBarFetcherImplTest() : OneGoogleBarFetcherImplTest(base::nullopt) {}
+
+  OneGoogleBarFetcherImplTest(
+      const base::Optional<std::string>& api_url_override)
       : task_runner_(new base::TestSimpleTaskRunner()),
         request_context_getter_(
             new net::TestURLRequestContextGetter(task_runner_)),
@@ -65,7 +69,8 @@
                             GoogleURLTracker::UNIT_TEST_MODE),
         one_google_bar_fetcher_(request_context_getter_.get(),
                                 &google_url_tracker_,
-                                kApplicationLocale) {}
+                                kApplicationLocale,
+                                api_url_override) {}
 
   net::TestURLFetcher* GetRunningURLFetcher() {
     // All created URLFetchers have ID 0 by default.
@@ -283,3 +288,46 @@
   "page_hooks": {}
 }}})json");
 }
+
+class OneGoogleBarFetcherImplWithRelativeApiUrlOverrideTest
+    : public OneGoogleBarFetcherImplTest {
+ public:
+  OneGoogleBarFetcherImplWithRelativeApiUrlOverrideTest()
+      : OneGoogleBarFetcherImplTest(std::string("/testapi?q=a")) {}
+};
+
+TEST_F(OneGoogleBarFetcherImplWithRelativeApiUrlOverrideTest,
+       RequestUrlRespectsOverride) {
+  // Trigger a request.
+  base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback;
+  one_google_bar_fetcher()->Fetch(callback.Get());
+
+  // Make sure the request URL corresponds to the override, but also contains
+  // the "hl=" query param.
+  GURL request_url = GetRunningURLFetcher()->GetOriginalURL();
+  EXPECT_EQ("/testapi", request_url.path());
+  std::string expected_query =
+      base::StringPrintf("q=a&hl=%s", kApplicationLocale);
+  EXPECT_EQ(expected_query, request_url.query());
+}
+
+class OneGoogleBarFetcherImplWithAbsoluteApiUrlOverrideTest
+    : public OneGoogleBarFetcherImplTest {
+ public:
+  OneGoogleBarFetcherImplWithAbsoluteApiUrlOverrideTest()
+      : OneGoogleBarFetcherImplTest(std::string("http://test.com/path?q=a")) {}
+};
+
+TEST_F(OneGoogleBarFetcherImplWithAbsoluteApiUrlOverrideTest,
+       RequestUrlRespectsOverride) {
+  // Trigger a request.
+  base::MockCallback<OneGoogleBarFetcher::OneGoogleCallback> callback;
+  one_google_bar_fetcher()->Fetch(callback.Get());
+
+  // Make sure the request URL corresponds to the override, but also contains
+  // the "hl=" query param.
+  GURL request_url = GetRunningURLFetcher()->GetOriginalURL();
+  GURL expected_url = GURL(
+      base::StringPrintf("http://test.com/path?q=a&hl=%s", kApplicationLocale));
+  EXPECT_EQ(expected_url, request_url);
+}
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc b/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc
index a86114c..526b584 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_service_factory.cc
@@ -4,13 +4,17 @@
 
 #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h"
 
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/optional.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_url_tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/one_google_bar/one_google_bar_fetcher_impl.h"
 #include "chrome/browser/search/one_google_bar/one_google_bar_service.h"
 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
+#include "chrome/common/chrome_features.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
@@ -38,13 +42,24 @@
 
 KeyedService* OneGoogleBarServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
+  if (!base::FeatureList::IsEnabled(features::kOneGoogleBarOnLocalNtp)) {
+    return nullptr;
+  }
+
   Profile* profile = Profile::FromBrowserContext(context);
   GaiaCookieManagerService* cookie_service =
       GaiaCookieManagerServiceFactory::GetForProfile(profile);
   GoogleURLTracker* google_url_tracker =
       GoogleURLTrackerFactory::GetForProfile(profile);
+  std::string override_api_url_str = base::GetFieldTrialParamValueByFeature(
+      features::kOneGoogleBarOnLocalNtp, "one-google-api-url");
+  base::Optional<std::string> override_api_url;
+  if (!override_api_url_str.empty()) {
+    override_api_url = override_api_url_str;
+  }
   return new OneGoogleBarService(
-      cookie_service, base::MakeUnique<OneGoogleBarFetcherImpl>(
-                          profile->GetRequestContext(), google_url_tracker,
-                          g_browser_process->GetApplicationLocale()));
+      cookie_service,
+      base::MakeUnique<OneGoogleBarFetcherImpl>(
+          profile->GetRequestContext(), google_url_tracker,
+          g_browser_process->GetApplicationLocale(), override_api_url));
 }
diff --git a/chrome/test/data/webui/i18n_process_test.html b/chrome/test/data/webui/i18n_process_test.html
index 8072639..c503cc1 100644
--- a/chrome/test/data/webui/i18n_process_test.html
+++ b/chrome/test/data/webui/i18n_process_test.html
@@ -2,8 +2,7 @@
 <html>
   <head>
     <title i18n-content="title"></title>
-    <link rel="import" href="data:text/html,
-        <link rel=import href='data:text/html,<div i18n-content=nested>'>">
+    <link rel="import" href="data:text/html,<link rel=import href='data:text/html,<div i18n-content=nested>'>">
     <script>
       document.write('<link id=cycle rel=import href="' + location.href + '">');
     </script>
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index 1094395..3d4fe6c 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -371,7 +371,10 @@
 
 autofill::PossibleUsernamePair MakePossibleUsernamePair(
     const blink::WebInputElement& input) {
-  return autofill::PossibleUsernamePair(input.Value().Utf16(),
+  base::string16 trimmed_input_value, trimmed_input_autofill;
+  base::TrimString(input.Value().Utf16(), base::ASCIIToUTF16(" "),
+                   &trimmed_input_value);
+  return autofill::PossibleUsernamePair(trimmed_input_value,
                                         input.NameForAutofill().Utf16());
 }
 
diff --git a/components/guest_view/browser/BUILD.gn b/components/guest_view/browser/BUILD.gn
index 96b4390..00bd7eb 100644
--- a/components/guest_view/browser/BUILD.gn
+++ b/components/guest_view/browser/BUILD.gn
@@ -11,6 +11,8 @@
 static_library("browser") {
   output_name = "guest_view_browser"
   sources = [
+    "//components/guest_view/browser/bad_message.cc",
+    "//components/guest_view/browser/bad_message.h",
     "//components/guest_view/browser/guest_view.h",
     "//components/guest_view/browser/guest_view_base.cc",
     "//components/guest_view/browser/guest_view_base.h",
diff --git a/components/guest_view/browser/PRESUBMIT.py b/components/guest_view/browser/PRESUBMIT.py
new file mode 100644
index 0000000..57effd1
--- /dev/null
+++ b/components/guest_view/browser/PRESUBMIT.py
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Chromium presubmit script to check that BadMessage enums in histograms.xml
+match the corresponding bad_message.h file.
+"""
+
+def _RunHistogramChecks(input_api, output_api, histogram_name):
+  try:
+    # Setup sys.path so that we can call histograms code.
+    import sys
+    original_sys_path = sys.path
+    sys.path = sys.path + [input_api.os_path.join(
+      input_api.change.RepositoryRoot(),
+      'tools', 'metrics', 'histograms')]
+
+    import presubmit_bad_message_reasons
+    return presubmit_bad_message_reasons.PrecheckBadMessage(input_api,
+      output_api, histogram_name)
+  except:
+    return [output_api.PresubmitError('Could not verify histogram!')]
+  finally:
+    sys.path = original_sys_path
+
+def CheckChangeOnUpload(input_api, output_api):
+  return _RunHistogramChecks(input_api, output_api, "BadMessageReasonGuestView")
diff --git a/components/guest_view/browser/bad_message.cc b/components/guest_view/browser/bad_message.cc
new file mode 100644
index 0000000..f16f086
--- /dev/null
+++ b/components/guest_view/browser/bad_message.cc
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/guest_view/browser/bad_message.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace guest_view {
+namespace bad_message {
+
+namespace {
+
+void LogBadMessage(BadMessageReason reason) {
+  LOG(ERROR) << "Terminating renderer for bad IPC message, reason " << reason;
+  UMA_HISTOGRAM_SPARSE_SLOWLY("Stability.BadMessageTerminated.GuestView",
+                              reason);
+}
+
+}  // namespace
+
+void ReceivedBadMessage(content::RenderProcessHost* host,
+                        BadMessageReason reason) {
+  LogBadMessage(reason);
+  host->ShutdownForBadMessage(
+      content::RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
+}
+
+void ReceivedBadMessage(int render_process_id, BadMessageReason reason) {
+  content::RenderProcessHost* rph =
+      content::RenderProcessHost::FromID(render_process_id);
+  if (!rph)
+    return;
+
+  ReceivedBadMessage(rph, reason);
+}
+
+void ReceivedBadMessage(content::BrowserMessageFilter* filter,
+                        BadMessageReason reason) {
+  LogBadMessage(reason);
+  filter->ShutdownForBadMessage();
+}
+
+}  // namespace bad_message
+}  // namespace guest_view
diff --git a/components/guest_view/browser/bad_message.h b/components/guest_view/browser/bad_message.h
new file mode 100644
index 0000000..2e81eed
--- /dev/null
+++ b/components/guest_view/browser/bad_message.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_GUEST_VIEW_BROWSER_BAD_MESSAGE_H_
+#define COMPONENTS_GUEST_VIEW_BROWSER_BAD_MESSAGE_H_
+
+namespace content {
+class BrowserMessageFilter;
+class RenderProcessHost;
+}  // namespace content
+
+namespace guest_view {
+namespace bad_message {
+
+// The browser process often chooses to terminate a renderer if it receives
+// a bad IPC message. The reasons are tracked for metrics.
+//
+// See also content/browser/bad_message.h.
+//
+// NOTE: Do not remove or reorder elements in this list. Add new entries at the
+// end. Items may be renamed but do not change the values. We rely on the enum
+// values in histograms.
+enum BadMessageReason {
+  GVM_EMBEDDER_FORBIDDEN_ACCESS_TO_GUEST = 0,
+
+  // Please add new elements here. The naming convention is abbreviated class
+  // name (e.g. GuestViewManager becomes GVM) plus a unique description of
+  // the reason. After making changes, you MUST update histograms.xml by
+  // running:
+  // "python tools/metrics/histograms/update_bad_message_reasons.py"
+  BAD_MESSAGE_MAX
+};
+
+// Called when the browser receives a bad IPC message from a renderer.
+// Logs the event, records a histogram metric for the |reason|,
+// and terminates the process for |host| / |render_process_id|.
+void ReceivedBadMessage(content::RenderProcessHost* host,
+                        BadMessageReason reason);
+void ReceivedBadMessage(int render_process_id, BadMessageReason reason);
+
+// Called when a browser message filter receives a bad IPC message from a
+// renderer process. Logs the event, records a histogram metric for the
+// |reason|, and terminates the process for |filter|.
+void ReceivedBadMessage(content::BrowserMessageFilter* filter,
+                        BadMessageReason reason);
+
+}  // namespace bad_message
+}  // namespace guest_view
+
+#endif  // COMPONENTS_GUEST_VIEW_BROWSER_BAD_MESSAGE_H_
diff --git a/components/guest_view/browser/guest_view_manager.cc b/components/guest_view/browser/guest_view_manager.cc
index bc36a92..ec30cd29 100644
--- a/components/guest_view/browser/guest_view_manager.cc
+++ b/components/guest_view/browser/guest_view_manager.cc
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/metrics/user_metrics.h"
+#include "components/guest_view/browser/bad_message.h"
 #include "components/guest_view/browser/guest_view_base.h"
 #include "components/guest_view/browser/guest_view_manager_delegate.h"
 #include "components/guest_view/browser/guest_view_manager_factory.h"
@@ -20,7 +20,6 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/child_process_host.h"
-#include "content/public/common/result_codes.h"
 #include "content/public/common/url_constants.h"
 #include "url/gurl.h"
 
@@ -421,9 +420,9 @@
   if (!CanEmbedderAccessInstanceID(embedder_render_process_id,
                                    guest_instance_id)) {
     // The embedder process is trying to access a guest it does not own.
-    base::RecordAction(base::UserMetricsAction("BadMessageTerminate_BPGM"));
-    content::RenderProcessHost::FromID(embedder_render_process_id)
-        ->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
+    bad_message::ReceivedBadMessage(
+        embedder_render_process_id,
+        bad_message::GVM_EMBEDDER_FORBIDDEN_ACCESS_TO_GUEST);
     return false;
   }
   return true;
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc
index eae331d..3800175 100644
--- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc
+++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.cc
@@ -12,8 +12,10 @@
 #include "components/gcm_driver/gcm_profile_service.h"
 #include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/gcm_driver/instance_id/instance_id_driver.h"
+#include "components/ntp_snippets/features.h"
 #include "components/ntp_snippets/pref_names.h"
 #include "components/ntp_snippets/time_serialization.h"
+#include "components/variations/variations_associated_data.h"
 
 using instance_id::InstanceID;
 
@@ -41,6 +43,33 @@
   return base::TimeDelta::FromHours(kTokenValidationPeriodHours);
 }
 
+const bool kEnableTokenValidationDefault = true;
+const char kEnableTokenValidationParamName[] = "enable_token_validation";
+
+bool IsTokenValidationEnabled() {
+  return variations::GetVariationParamByFeatureAsBool(
+      kBreakingNewsPushFeature, kEnableTokenValidationParamName,
+      kEnableTokenValidationDefault);
+}
+
+// Lower bound time between two forced subscriptions when listening. A
+// forced subscription is a normal subscription to the content
+// suggestions server, which cannot be omitted.
+const int kForcedSubscriptionPeriodHours = 7 * 24;
+
+base::TimeDelta GetForcedSubscriptionPeriod() {
+  return base::TimeDelta::FromHours(kForcedSubscriptionPeriodHours);
+}
+
+const bool kEnableForcedSubscriptionDefault = true;
+const char kEnableForcedSubscriptionParamName[] = "enable_forced_subscription";
+
+bool IsForcedSubscriptionEnabled() {
+  return variations::GetVariationParamByFeatureAsBool(
+      kBreakingNewsPushFeature, kEnableForcedSubscriptionParamName,
+      kEnableForcedSubscriptionDefault);
+}
+
 }  // namespace
 
 BreakingNewsGCMAppHandler::BreakingNewsGCMAppHandler(
@@ -50,7 +79,8 @@
     std::unique_ptr<SubscriptionManager> subscription_manager,
     const ParseJSONCallback& parse_json_callback,
     std::unique_ptr<base::Clock> clock,
-    std::unique_ptr<base::OneShotTimer> token_validation_timer)
+    std::unique_ptr<base::OneShotTimer> token_validation_timer,
+    std::unique_ptr<base::OneShotTimer> forced_subscription_timer)
     : gcm_driver_(gcm_driver),
       instance_id_driver_(instance_id_driver),
       pref_service_(pref_service),
@@ -58,6 +88,7 @@
       parse_json_callback_(parse_json_callback),
       clock_(std::move(clock)),
       token_validation_timer_(std::move(token_validation_timer)),
+      forced_subscription_timer_(std::move(forced_subscription_timer)),
       weak_ptr_factory_(this) {
 #if !defined(OS_ANDROID)
 #error The BreakingNewsGCMAppHandler should only be used on Android.
@@ -80,12 +111,18 @@
       std::move(on_new_remote_suggestion_callback);
   Subscribe(/*force_token_retrieval=*/false);
   gcm_driver_->AddAppHandler(kBreakingNewsGCMAppID, this);
-  ScheduleNextTokenValidation();
+  if (IsTokenValidationEnabled()) {
+    ScheduleNextTokenValidation();
+  }
+  if (IsForcedSubscriptionEnabled()) {
+    ScheduleNextForcedSubscription();
+  }
 }
 
 void BreakingNewsGCMAppHandler::StopListening() {
   DCHECK(IsListening());
   token_validation_timer_->Stop();
+  forced_subscription_timer_->Stop();
   DCHECK_EQ(gcm_driver_->GetAppHandler(kBreakingNewsGCMAppID), this);
   gcm_driver_->RemoveAppHandler(kBreakingNewsGCMAppID);
   on_new_remote_suggestion_callback_ = OnNewRemoteSuggestionCallback();
@@ -127,7 +164,9 @@
       // validation.
       pref_service_->SetInt64(prefs::kBreakingNewsGCMLastTokenValidationTime,
                               SerializeTime(clock_->Now()));
-      ScheduleNextTokenValidation();
+      if (IsTokenValidationEnabled()) {
+        ScheduleNextTokenValidation();
+      }
       pref_service_->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
                                subscription_token);
       subscription_manager_->Subscribe(subscription_token);
@@ -148,6 +187,7 @@
 
 void BreakingNewsGCMAppHandler::ResubscribeIfInvalidToken() {
   DCHECK(IsListening());
+  DCHECK(IsTokenValidationEnabled());
 
   // InstanceIDAndroid::ValidateToken just returns |true| on Android. Instead it
   // is ok to retrieve a token, because it is cached.
@@ -185,6 +225,7 @@
 
 void BreakingNewsGCMAppHandler::ScheduleNextTokenValidation() {
   DCHECK(IsListening());
+  DCHECK(IsTokenValidationEnabled());
 
   const base::Time last_validation_time = DeserializeTime(
       pref_service_->GetInt64(prefs::kBreakingNewsGCMLastTokenValidationTime));
@@ -197,6 +238,38 @@
                  weak_ptr_factory_.GetWeakPtr()));
 }
 
+void BreakingNewsGCMAppHandler::ForceSubscribe() {
+  DCHECK(IsForcedSubscriptionEnabled());
+
+  // We intentionally reschedule as normal even if there is no token or
+  // subscription fails.
+  pref_service_->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                          SerializeTime(clock_->Now()));
+  ScheduleNextForcedSubscription();
+
+  const std::string token =
+      pref_service_->GetString(prefs::kBreakingNewsGCMSubscriptionTokenCache);
+  if (!token.empty()) {
+    subscription_manager_->Subscribe(token);
+  }
+}
+
+void BreakingNewsGCMAppHandler::ScheduleNextForcedSubscription() {
+  DCHECK(IsListening());
+  DCHECK(IsForcedSubscriptionEnabled());
+
+  const base::Time last_forced_subscription_time =
+      DeserializeTime(pref_service_->GetInt64(
+          prefs::kBreakingNewsGCMLastForcedSubscriptionTime));
+  // Timer runs the task immediately if delay is <= 0.
+  forced_subscription_timer_->Start(
+      FROM_HERE,
+      /*delay=*/last_forced_subscription_time + GetForcedSubscriptionPeriod() -
+          clock_->Now(),
+      base::Bind(&BreakingNewsGCMAppHandler::ForceSubscribe,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
 void BreakingNewsGCMAppHandler::ShutdownHandler() {}
 
 void BreakingNewsGCMAppHandler::OnStoreReset() {
@@ -250,6 +323,8 @@
                                /*default_value=*/std::string());
   registry->RegisterInt64Pref(prefs::kBreakingNewsGCMLastTokenValidationTime,
                               /*default_value=*/0);
+  registry->RegisterInt64Pref(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                              /*default_value=*/0);
 }
 
 void BreakingNewsGCMAppHandler::OnJsonSuccess(
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h
index 63d00e9..01a0710 100644
--- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h
+++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h
@@ -53,7 +53,8 @@
       std::unique_ptr<SubscriptionManager> subscription_manager,
       const ParseJSONCallback& parse_json_callback,
       std::unique_ptr<base::Clock> clock,
-      std::unique_ptr<base::OneShotTimer> token_validation_timer);
+      std::unique_ptr<base::OneShotTimer> token_validation_timer,
+      std::unique_ptr<base::OneShotTimer> forced_subscription_timer);
 
   // If still listening, calls StopListening()
   ~BreakingNewsGCMAppHandler() override;
@@ -100,6 +101,12 @@
   // If the validation is due, it may be scheduled immediately.
   void ScheduleNextTokenValidation();
 
+  // Subscribe to content suggestions service using the existing token.
+  void ForceSubscribe();
+
+  // If the subscription is due, it may be scheduled immediately.
+  void ScheduleNextForcedSubscription();
+
   // Called after successfully parsing the received suggestion JSON.
   void OnJsonSuccess(std::unique_ptr<base::Value> content);
 
@@ -119,6 +126,7 @@
   OnNewRemoteSuggestionCallback on_new_remote_suggestion_callback_;
 
   std::unique_ptr<base::OneShotTimer> token_validation_timer_;
+  std::unique_ptr<base::OneShotTimer> forced_subscription_timer_;
 
   base::WeakPtrFactory<BreakingNewsGCMAppHandler> weak_ptr_factory_;
 
diff --git a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
index a08ef48..c940329 100644
--- a/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
+++ b/components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler_unittest.cc
@@ -19,10 +19,12 @@
 #include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/gcm_driver/instance_id/instance_id_driver.h"
 #include "components/ntp_snippets/breaking_news/subscription_manager.h"
+#include "components/ntp_snippets/features.h"
 #include "components/ntp_snippets/pref_names.h"
 #include "components/ntp_snippets/remote/test_utils.h"
 #include "components/ntp_snippets/time_serialization.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/variations/variations_params_manager.h"
 #include "google_apis/gcm/engine/account_mapping.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -182,8 +184,16 @@
   return base::TimeDelta::FromHours(24);
 }
 
+base::TimeDelta GetForcedSubscriptionPeriod() {
+  return base::TimeDelta::FromHours(7 * 24);
+}
+
 const char kBreakingNewsGCMAppID[] = "com.google.breakingnews.gcm";
 
+std::string BoolToString(bool value) {
+  return value ? "true" : "false";
+}
+
 }  // namespace
 
 class BreakingNewsGCMAppHandlerTest : public testing::Test {
@@ -208,6 +218,8 @@
     tick_clock_ = timer_mock_task_runner->GetMockTickClock();
     message_loop_.SetTaskRunner(timer_mock_task_runner);
 
+    // TODO(vitaliii): Initialize MockSubscriptionManager in the constructor, so
+    // that one could set up expectations before creating the handler.
     auto wrapped_mock_subscription_manager =
         base::MakeUnique<NiceMock<MockSubscriptionManager>>();
     mock_subscription_manager_ = wrapped_mock_subscription_manager.get();
@@ -216,12 +228,33 @@
         base::MakeUnique<base::OneShotTimer>(tick_clock_.get());
     token_validation_timer->SetTaskRunner(timer_mock_task_runner);
 
+    auto forced_subscription_timer =
+        base::MakeUnique<base::OneShotTimer>(tick_clock_.get());
+    forced_subscription_timer->SetTaskRunner(timer_mock_task_runner);
+
     return base::MakeUnique<BreakingNewsGCMAppHandler>(
         mock_gcm_driver_.get(), mock_instance_id_driver_.get(), pref_service(),
         std::move(wrapped_mock_subscription_manager),
         BreakingNewsGCMAppHandler::ParseJSONCallback(),
         timer_mock_task_runner->GetMockClock(),
-        std::move(token_validation_timer));
+        std::move(token_validation_timer),
+        std::move(forced_subscription_timer));
+  }
+
+  void SetFeatureParams(bool enable_token_validation,
+                        bool enable_forced_subscription) {
+    // VariationParamsManager supports only one
+    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
+    // previous settings first to make this explicit.
+    params_manager_.ClearAllVariationParams();
+    params_manager_.SetVariationParamsWithFeatureAssociations(
+        kBreakingNewsPushFeature.name,
+        {
+            {"enable_token_validation", BoolToString(enable_token_validation)},
+            {"enable_forced_subscription",
+             BoolToString(enable_forced_subscription)},
+        },
+        {kBreakingNewsPushFeature.name});
   }
 
   PrefService* pref_service() { return utils_.pref_service(); }
@@ -233,6 +266,7 @@
   }
 
  private:
+  variations::testing::VariationParamsManager params_manager_;
   base::MessageLoop message_loop_;
   test::RemoteSuggestionsTestUtils utils_;
   NiceMock<MockSubscriptionManager>* mock_subscription_manager_;
@@ -244,6 +278,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldValidateTokenImmediatelyIfValidationIsDue) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // Last validation was long time ago.
   const base::Time last_validation =
       GetDummyNow() - 10 * GetTokenValidationPeriod();
@@ -270,6 +307,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldScheduleTokenValidationIfNotYetDue) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // The next validation will be soon.
   const base::TimeDelta time_to_validation = base::TimeDelta::FromHours(1);
   const base::Time last_validation =
@@ -292,7 +332,7 @@
   task_runner->FastForwardBy(time_to_validation -
                              base::TimeDelta::FromSeconds(1));
 
-  // But when it is a time, validation happens.
+  // But when it is time, validation happens.
   EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
       .WillOnce(
           InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
@@ -300,6 +340,9 @@
 }
 
 TEST_F(BreakingNewsGCMAppHandlerTest, ShouldNotValidateTokenBeforeListening) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // Last validation was long time ago.
   const base::Time last_validation =
       GetDummyNow() - 10 * GetTokenValidationPeriod();
@@ -317,7 +360,11 @@
   task_runner->FastForwardBy(10 * GetTokenValidationPeriod());
 }
 
-TEST_F(BreakingNewsGCMAppHandlerTest, ShouldNotValidateTokenAfterListening) {
+TEST_F(BreakingNewsGCMAppHandlerTest,
+       ShouldNotValidateTokenAfterStopListening) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // The next validation will be soon.
   const base::TimeDelta time_to_validation = base::TimeDelta::FromHours(1);
   const base::Time last_validation =
@@ -344,6 +391,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldRescheduleTokenValidationWhenRetrievingToken) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // The next validation will be soon.
   const base::TimeDelta time_to_validation = base::TimeDelta::FromHours(1);
   const base::Time last_validation =
@@ -377,6 +427,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldScheduleNewTokenValidationAfterValidation) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // The next validation will be soon.
   const base::TimeDelta time_to_validation = base::TimeDelta::FromHours(1);
   const base::Time last_validation =
@@ -413,6 +466,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldResubscribeWithNewTokenIfOldIsInvalidAfterValidation) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // Last validation was long time ago.
   const base::Time last_validation =
       GetDummyNow() - 10 * GetTokenValidationPeriod();
@@ -441,6 +497,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        ShouldDoNothingIfOldTokenIsValidAfterValidation) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/false);
+
   // Last validation was long time ago.
   const base::Time last_validation =
       GetDummyNow() - 10 * GetTokenValidationPeriod();
@@ -469,6 +528,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        IsListeningShouldReturnFalseBeforeListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/false);
+
   scoped_refptr<TestMockTimeTaskRunner> task_runner(
       new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
   auto handler = MakeHandler(task_runner);
@@ -478,6 +540,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        IsListeningShouldReturnTrueAfterStartListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/false);
+
   scoped_refptr<TestMockTimeTaskRunner> task_runner(
       new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
   auto handler = MakeHandler(task_runner);
@@ -494,6 +559,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        IsListeningShouldReturnFalseAfterStopListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/false);
+
   scoped_refptr<TestMockTimeTaskRunner> task_runner(
       new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
   auto handler = MakeHandler(task_runner);
@@ -513,6 +581,9 @@
 
 TEST_F(BreakingNewsGCMAppHandlerTest,
        IsListeningShouldReturnTrueAfterSecondStartListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/false);
+
   scoped_refptr<TestMockTimeTaskRunner> task_runner(
       new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
   auto handler = MakeHandler(task_runner);
@@ -534,4 +605,191 @@
   EXPECT_TRUE(handler->IsListening());
 }
 
+TEST_F(BreakingNewsGCMAppHandlerTest, ShouldForceSubscribeImmediatelyIfDue) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/true);
+
+  // Last subscription was long time ago.
+  const base::Time last_subscription =
+      GetDummyNow() - 10 * GetForcedSubscriptionPeriod();
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+  auto handler = MakeHandler(task_runner);
+
+  handler->StartListening(
+      base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}));
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
+  task_runner->RunUntilIdle();
+}
+
+TEST_F(BreakingNewsGCMAppHandlerTest,
+       ShouldScheduleForcedSubscribtionIfNotYetDue) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/true);
+
+  // The next forced subscription will be soon.
+  const base::TimeDelta time_to_subscription = base::TimeDelta::FromHours(1);
+  const base::Time last_subscription =
+      GetDummyNow() - (GetForcedSubscriptionPeriod() - time_to_subscription);
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+  auto handler = MakeHandler(task_runner);
+
+  // Check that handler does not force subscribe yet.
+  handler->StartListening(
+      base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}));
+  // TODO(vitaliii): Consider making FakeSubscriptionManager, because
+  // IsSubscribed() affects forced subscriptions. Currently we have to carefully
+  // avoid the initial subscription.
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
+  task_runner->FastForwardBy(time_to_subscription -
+                             base::TimeDelta::FromSeconds(1));
+
+  // But when it is time, forced subscription happens.
+  testing::Mock::VerifyAndClearExpectations(mock_subscription_manager());
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
+  task_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
+}
+
+TEST_F(BreakingNewsGCMAppHandlerTest, ShouldNotForceSubscribeBeforeListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/true);
+
+  // Last subscription was long time ago.
+  const base::Time last_subscription =
+      GetDummyNow() - 10 * GetForcedSubscriptionPeriod();
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+
+  // Check that handler does not force subscribe before StartListening even
+  // though a forced subscription is due.
+  auto handler = MakeHandler(task_runner);
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
+  task_runner->FastForwardBy(10 * GetForcedSubscriptionPeriod());
+}
+
+TEST_F(BreakingNewsGCMAppHandlerTest,
+       ShouldNotForceSubscribeAfterStopListening) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/true);
+
+  // The next forced subscription will be soon.
+  const base::TimeDelta time_to_subscription = base::TimeDelta::FromHours(1);
+  const base::Time last_subscription =
+      GetDummyNow() - (GetForcedSubscriptionPeriod() - time_to_subscription);
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+
+  // Check that handler does not force subscribe after StopListening even
+  // though a forced subscription is due.
+  auto handler = MakeHandler(task_runner);
+  handler->StartListening(
+      base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}));
+  handler->StopListening();
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
+  task_runner->FastForwardBy(10 * GetForcedSubscriptionPeriod());
+}
+
+TEST_F(BreakingNewsGCMAppHandlerTest,
+       ShouldScheduleNewForcedSubscriptionAfterForcedSubscription) {
+  SetFeatureParams(/*enable_token_validation=*/false,
+                   /*enable_forced_subscription=*/true);
+
+  // The next forced subscription will be soon.
+  const base::TimeDelta time_to_subscription = base::TimeDelta::FromHours(1);
+  const base::Time last_subscription =
+      GetDummyNow() - (GetForcedSubscriptionPeriod() - time_to_subscription);
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+  auto handler = MakeHandler(task_runner);
+  handler->StartListening(
+      base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}));
+
+  // Handler force subscribes.
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
+  task_runner->FastForwardBy(time_to_subscription);
+
+  // Check that the next forced subscription is scheduled in time.
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
+  task_runner->FastForwardBy(GetForcedSubscriptionPeriod() -
+                             base::TimeDelta::FromSeconds(1));
+
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
+  task_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
+}
+
+TEST_F(BreakingNewsGCMAppHandlerTest,
+       TokenValidationAndForcedSubscriptionShouldNotAffectEachOther) {
+  SetFeatureParams(/*enable_token_validation=*/true,
+                   /*enable_forced_subscription=*/true);
+
+  // The next forced subscription will be soon.
+  const base::TimeDelta time_to_subscription = base::TimeDelta::FromHours(1);
+  const base::Time last_subscription =
+      GetDummyNow() - (GetForcedSubscriptionPeriod() - time_to_subscription);
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+                           SerializeTime(last_subscription));
+
+  // The next validation will be sooner.
+  const base::TimeDelta time_to_validation = base::TimeDelta::FromMinutes(30);
+  const base::Time last_validation =
+      GetDummyNow() - (GetTokenValidationPeriod() - time_to_validation);
+  pref_service()->SetInt64(prefs::kBreakingNewsGCMLastTokenValidationTime,
+                           SerializeTime(last_validation));
+
+  // Omit receiving the token by putting it there directly.
+  pref_service()->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
+                            "token");
+
+  scoped_refptr<TestMockTimeTaskRunner> task_runner(
+      new TestMockTimeTaskRunner(GetDummyNow(), TimeTicks::Now()));
+  auto handler = MakeHandler(task_runner);
+  handler->StartListening(
+      base::Bind([](std::unique_ptr<RemoteSuggestion> remote_suggestion) {}));
+
+  // Check that the next validation is scheduled in time.
+  EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _)).Times(0);
+  task_runner->FastForwardBy(time_to_validation -
+                             base::TimeDelta::FromSeconds(1));
+
+  EXPECT_CALL(*mock_instance_id(), GetToken(_, _, _, _))
+      .WillOnce(
+          InvokeCallbackArgument<3>("token", InstanceID::Result::SUCCESS));
+  task_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // Check that the next forced subscription is scheduled in time.
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token")).Times(0);
+  task_runner->FastForwardBy((time_to_subscription - time_to_validation) -
+                             base::TimeDelta::FromSeconds(1));
+
+  EXPECT_CALL(*mock_subscription_manager(), Subscribe("token"));
+  task_runner->FastForwardBy(base::TimeDelta::FromSeconds(1));
+}
+
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index 231013a..95c3aeb 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -93,5 +93,8 @@
 const char kBreakingNewsGCMLastTokenValidationTime[] =
     "ntp_suggestions.breaking_news_gcm_last_token_validation_time";
 
+const char kBreakingNewsGCMLastForcedSubscriptionTime[] =
+    "ntp_suggestions.breaking_news_gcm_last_forced_subscription_time";
+
 }  // namespace prefs
 }  // namespace ntp_snippets
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index 0c213f3..8462d40 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -110,9 +110,12 @@
 // with the new one and update kBreakingNewsSubscriptionDataToken.
 extern const char kBreakingNewsGCMSubscriptionTokenCache[];
 
-// When the next GCM token validation is scheduled.
+// When the last GCM token validation was.
 extern const char kBreakingNewsGCMLastTokenValidationTime[];
 
+// When the last forced subscription to content suggestions service was.
+extern const char kBreakingNewsGCMLastForcedSubscriptionTime[];
+
 }  // namespace prefs
 }  // namespace ntp_snippets
 
diff --git a/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc b/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
index 929bc8f..b673c3c 100644
--- a/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
+++ b/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
@@ -12,8 +12,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/mock_callback.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/image_fetcher/core/image_decoder.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
@@ -59,17 +58,15 @@
 
 class CachedImageFetcherTest : public testing::Test {
  public:
-  CachedImageFetcherTest()
-      : fake_url_fetcher_factory_(nullptr),
-        mock_task_runner_(new base::TestSimpleTaskRunner()),
-        mock_task_runner_handle_(mock_task_runner_) {
+  CachedImageFetcherTest() : fake_url_fetcher_factory_(nullptr) {
     EXPECT_TRUE(database_dir_.CreateUniqueTempDir());
 
     RequestThrottler::RegisterProfilePrefs(pref_service_.registry());
-    database_ = base::MakeUnique<RemoteSuggestionsDatabase>(
-        database_dir_.GetPath(), mock_task_runner_);
+    database_ =
+        base::MakeUnique<RemoteSuggestionsDatabase>(database_dir_.GetPath());
     request_context_getter_ = scoped_refptr<net::TestURLRequestContextGetter>(
-        new net::TestURLRequestContextGetter(mock_task_runner_.get()));
+        new net::TestURLRequestContextGetter(
+            scoped_task_environment_.GetMainThreadTaskRunner()));
 
     auto decoder = base::MakeUnique<FakeImageDecoder>();
     fake_image_decoder_ = decoder.get();
@@ -81,6 +78,14 @@
     EXPECT_TRUE(database_->IsInitialized());
   }
 
+  ~CachedImageFetcherTest() override {
+    cached_image_fetcher_.reset();
+    database_.reset();
+    // We need to run until idle after deleting the database, because
+    // ProtoDatabaseImpl deletes the actual LevelDB asynchronously.
+    RunUntilIdle();
+  }
+
   void FetchImage(ImageFetchedCallback callback) {
     ContentSuggestion::ID content_suggestion_id(
         Category::FromKnownCategory(KnownCategories::ARTICLES), kSnippetID);
@@ -88,7 +93,7 @@
         content_suggestion_id, GURL(kImageURL), std::move(callback));
   }
 
-  void RunUntilIdle() { mock_task_runner_->RunUntilIdle(); }
+  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
 
   RemoteSuggestionsDatabase* database() { return database_.get(); }
   FakeImageDecoder* fake_image_decoder() { return fake_image_decoder_; }
@@ -102,10 +107,9 @@
   base::ScopedTempDir database_dir_;
   FakeImageDecoder* fake_image_decoder_;
   net::FakeURLFetcherFactory fake_url_fetcher_factory_;
-  scoped_refptr<base::TestSimpleTaskRunner> mock_task_runner_;
-  base::ThreadTaskRunnerHandle mock_task_runner_handle_;
   TestingPrefServiceSimple pref_service_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherTest);
 };
diff --git a/components/ntp_snippets/remote/remote_suggestions_database.cc b/components/ntp_snippets/remote/remote_suggestions_database.cc
index 82b42d6..96fc318f 100644
--- a/components/ntp_snippets/remote/remote_suggestions_database.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_database.cc
@@ -8,6 +8,7 @@
 
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "components/leveldb_proto/proto_database_impl.h"
 #include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h"
 
@@ -33,14 +34,18 @@
 namespace ntp_snippets {
 
 RemoteSuggestionsDatabase::RemoteSuggestionsDatabase(
-    const base::FilePath& database_dir,
-    scoped_refptr<base::SequencedTaskRunner> file_task_runner)
-    : database_(new ProtoDatabaseImpl<SnippetProto>(file_task_runner)),
-      database_initialized_(false),
-      image_database_(
-          new ProtoDatabaseImpl<SnippetImageProto>(file_task_runner)),
+    const base::FilePath& database_dir)
+    : database_initialized_(false),
       image_database_initialized_(false),
       weak_ptr_factory_(this) {
+  auto file_task_runner = base::CreateSequencedTaskRunnerWithTraits(
+      {base::MayBlock(), base::TaskPriority::BACKGROUND,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
+  database_ =
+      base::MakeUnique<ProtoDatabaseImpl<SnippetProto>>(file_task_runner);
+  image_database_ =
+      base::MakeUnique<ProtoDatabaseImpl<SnippetImageProto>>(file_task_runner);
+
   base::FilePath snippet_dir = database_dir.AppendASCII(kSnippetDatabaseFolder);
   database_->InitWithOptions(
       kDatabaseUMAClientName,
diff --git a/components/ntp_snippets/remote/remote_suggestions_database.h b/components/ntp_snippets/remote/remote_suggestions_database.h
index 07f102f..9190099 100644
--- a/components/ntp_snippets/remote/remote_suggestions_database.h
+++ b/components/ntp_snippets/remote/remote_suggestions_database.h
@@ -34,10 +34,7 @@
   using SnippetsCallback = base::Callback<void(RemoteSuggestion::PtrVector)>;
   using SnippetImageCallback = base::Callback<void(std::string)>;
 
-  // TODO(gaschler): create the task runner here rather than passing it
-  RemoteSuggestionsDatabase(
-      const base::FilePath& database_dir,
-      scoped_refptr<base::SequencedTaskRunner> file_task_runner);
+  RemoteSuggestionsDatabase(const base::FilePath& database_dir);
   ~RemoteSuggestionsDatabase();
 
   // Returns whether the database has finished initialization. While this is
diff --git a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
index df46935..d7347dd 100644
--- a/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
@@ -12,8 +12,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -66,11 +65,11 @@
   }
 
   ~RemoteSuggestionsDatabaseTest() override {
-    // We need to run the message loop after deleting the database, because
+    // We need to run until idle after deleting the database, because
     // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
     // runner. Without this, we'd get reports of memory leaks.
     db_.reset();
-    base::RunLoop().RunUntilIdle();
+    RunUntilIdle();
   }
 
   void CreateDatabase() {
@@ -78,10 +77,11 @@
     // on the file.
     db_.reset();
 
-    db_.reset(new RemoteSuggestionsDatabase(
-        database_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get()));
+    db_.reset(new RemoteSuggestionsDatabase(database_dir_.GetPath()));
   }
 
+  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+
   RemoteSuggestionsDatabase* db() { return db_.get(); }
 
   // TODO(tschumann): MOCK_METHODS on non mock objects are an anti-pattern.
@@ -95,9 +95,9 @@
   MOCK_METHOD1(OnImageLoaded, void(std::string));
 
  private:
-  base::MessageLoop message_loop_;
   base::ScopedTempDir database_dir_;
   std::unique_ptr<RemoteSuggestionsDatabase> db_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsDatabaseTest);
 };
@@ -108,7 +108,7 @@
   CreateDatabase();
   EXPECT_FALSE(db()->IsInitialized());
 
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(db()->IsInitialized());
 }
 
@@ -127,7 +127,7 @@
   // They should be serviced once initialization finishes.
   EXPECT_CALL(*this, OnSnippetsLoadedImpl(_));
   EXPECT_CALL(*this, OnImageLoaded(_));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(db()->IsInitialized());
 }
 
@@ -136,7 +136,7 @@
   EXPECT_FALSE(db()->IsInitialized());
 
   EXPECT_CALL(*this, OnSnippetsLoadedImpl(_)).Times(0);
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(db()->IsInitialized());
 
   Mock::VerifyAndClearExpectations(this);
@@ -149,12 +149,12 @@
   db()->LoadImage("id",
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, Save) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -170,7 +170,7 @@
   db()->LoadSnippets(
       base::Bind(&RemoteSuggestionsDatabaseTest::OnSnippetsLoaded,
                  base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   Mock::VerifyAndClearExpectations(this);
 
@@ -178,12 +178,12 @@
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, SavePersist) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -192,7 +192,7 @@
   // Store a snippet and an image.
   db()->SaveSnippet(*snippet);
   db()->SaveImage(snippet->id(), image_data);
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // They should still exist after recreating the database.
   CreateDatabase();
@@ -206,12 +206,12 @@
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, Update) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -229,12 +229,12 @@
   db()->LoadSnippets(
       base::Bind(&RemoteSuggestionsDatabaseTest::OnSnippetsLoaded,
                  base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, Delete) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -248,7 +248,7 @@
   db()->LoadSnippets(
       base::Bind(&RemoteSuggestionsDatabaseTest::OnSnippetsLoaded,
                  base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   Mock::VerifyAndClearExpectations(this);
 
@@ -260,12 +260,12 @@
   db()->LoadSnippets(
       base::Bind(&RemoteSuggestionsDatabaseTest::OnSnippetsLoaded,
                  base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, DeleteSnippetDoesNotDeleteImage) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -274,7 +274,7 @@
   // Store a snippet and image.
   db()->SaveSnippet(*snippet);
   db()->SaveImage(snippet->id(), image_data);
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // Make sure they're there.
   EXPECT_CALL(*this,
@@ -286,7 +286,7 @@
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   Mock::VerifyAndClearExpectations(this);
 
@@ -298,12 +298,12 @@
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsDatabaseTest, DeleteImage) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
@@ -311,14 +311,14 @@
 
   // Store the image.
   db()->SaveImage(snippet->id(), image_data);
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // Make sure the image is there.
   EXPECT_CALL(*this, OnImageLoaded(image_data));
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   Mock::VerifyAndClearExpectations(this);
 
@@ -330,7 +330,7 @@
   db()->LoadImage(snippet->id(),
                   base::Bind(&RemoteSuggestionsDatabaseTest::OnImageLoaded,
                              base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 namespace {
@@ -353,14 +353,14 @@
 
 TEST_F(RemoteSuggestionsDatabaseTest, ShouldGarbageCollectImages) {
   CreateDatabase();
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   ASSERT_TRUE(db()->IsInitialized());
 
   // Store images.
   db()->SaveImage("snippet-id-1", "pretty-image-1");
   db()->SaveImage("snippet-id-2", "pretty-image-2");
   db()->SaveImage("snippet-id-3", "pretty-image-3");
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // Make sure the to-be-garbage collected images are there.
   LoadExpectedImage(db(), "snippet-id-1", "pretty-image-1");
@@ -369,7 +369,7 @@
   // Garbage collect all except the second.
   db()->GarbageCollectImages(base::MakeUnique<std::set<std::string>>(
       std::set<std::string>({"snippet-id-2"})));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // Make sure the images are gone.
   LoadExpectedImage(db(), "snippet-id-1", "");
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
index 3432515..69cb08d 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -17,16 +17,14 @@
 #include "base/json/json_reader.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_clock.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "components/image_fetcher/core/image_decoder.h"
@@ -334,10 +332,10 @@
   }
 
   ~RemoteSuggestionsProviderImplTest() override {
-    // We need to run the message loop after deleting the database, because
+    // We need to run until idle after deleting the database, because
     // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task
     // runner. Without this, we'd get reports of memory leaks.
-    base::RunLoop().RunUntilIdle();
+    RunUntilIdle();
   }
 
   // TODO(vitaliii): Rewrite this function to initialize a test class member
@@ -358,9 +356,6 @@
       bool use_mock_prefetched_pages_tracker,
       bool use_fake_breaking_news_listener,
       bool use_mock_remote_suggestions_status_service) {
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner(
-        base::ThreadTaskRunnerHandle::Get());
-
     utils_.ResetSigninManager();
     auto mock_suggestions_fetcher =
         base::MakeUnique<StrictMock<MockRemoteSuggestionsFetcher>>();
@@ -407,8 +402,8 @@
         .WillByDefault(Return(&image_decoder_));
     EXPECT_FALSE(observer_);
     observer_ = base::MakeUnique<FakeContentSuggestionsProviderObserver>();
-    auto database = base::MakeUnique<RemoteSuggestionsDatabase>(
-        database_dir_.GetPath(), task_runner);
+    auto database =
+        base::MakeUnique<RemoteSuggestionsDatabase>(database_dir_.GetPath());
     database_ = database.get();
     return base::MakeUnique<RemoteSuggestionsProviderImpl>(
         observer_.get(), utils_.pref_service(), "fr", category_ranker_.get(),
@@ -434,7 +429,7 @@
               provider->state_);
 
     // TODO(treib): Find a better way to wait for initialization to finish.
-    base::RunLoop().RunUntilIdle();
+    RunUntilIdle();
   }
 
   void ResetSuggestionsProvider(
@@ -443,12 +438,16 @@
       bool use_fake_breaking_news_listener,
       bool use_mock_remote_suggestions_status_service) {
     provider->reset();
+    // We need to run until idle after deleting the RemoteSuggestionsDatabase.
+    RunUntilIdle();
     observer_.reset();
     *provider = MakeSuggestionsProvider(
         use_mock_prefetched_pages_tracker, use_fake_breaking_news_listener,
         use_mock_remote_suggestions_status_service);
   }
 
+  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+
   void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) {
     category_ranker_ = std::move(category_ranker);
   }
@@ -540,7 +539,7 @@
   }
 
   void SetOrderNewRemoteCategoriesBasedOnArticlesCategoryParam(bool value) {
-    // params_manager supports only one
+    // VariationParamsManager supports only one
     // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
     // previous settings first to make this explicit.
     params_manager_.ClearAllVariationParams();
@@ -554,7 +553,7 @@
   void EnableKeepingPrefetchedContentSuggestions(
       int max_additional_prefetched_suggestions,
       const base::TimeDelta& max_age_for_additional_prefetched_suggestion) {
-    // params_manager supports only one
+    // VariationParamsManager supports only one
     // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
     // previous settings first to make this explicit.
     params_manager_.ClearAllVariationParams();
@@ -572,7 +571,7 @@
 
   void SetTriggeringNotificationsParams(bool fetched_enabled,
                                         bool pushed_enabled) {
-    // params_manager supports only one
+    // VariationParamsManager supports only one
     // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
     // previous settings first to make this explicit.
     params_manager_.ClearAllVariationParams();
@@ -590,7 +589,6 @@
  private:
   variations::testing::VariationParamsManager params_manager_;
   test::RemoteSuggestionsTestUtils utils_;
-  base::MessageLoop message_loop_;
   std::unique_ptr<CategoryRanker> category_ranker_;
   UserClassifier user_classifier_;
   std::unique_ptr<FakeContentSuggestionsProviderObserver> observer_;
@@ -601,6 +599,7 @@
   std::unique_ptr<MockScheduler> scheduler_;
   FakeBreakingNewsListener* fake_breaking_news_listener_;
   RemoteSuggestionsStatusService* remote_suggestions_status_service_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   RemoteSuggestionsStatusService::StatusChangeCallback status_change_callback_;
 
@@ -1480,7 +1479,7 @@
                            IsEmpty()));
   provider->Fetch(articles_category(), std::set<std::string>(),
                   base::Bind(&SuggestionsLoaded, &loaded));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest,
@@ -1666,7 +1665,7 @@
             }
           },
           provider.get(), this));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 
   // There should be no dismissed suggestion after clearing the list.
   provider->ClearDismissedSuggestionsForDebugging(articles_category());
@@ -1679,7 +1678,7 @@
             EXPECT_EQ(0u, dismissed_suggestions.size());
           },
           provider.get(), this));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
 }
 
 TEST_F(RemoteSuggestionsProviderImplTest, RemoveExpiredDismissedContent) {
@@ -1973,7 +1972,7 @@
       MakeArticleID(kSuggestionUrl),
       base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
                  base::Unretained(&image_fetched)));
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   // Check that the image by ServeOneByOneImage is really served.
   EXPECT_EQ(1, image.Width());
 }
@@ -1994,7 +1993,7 @@
       base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
                  base::Unretained(&image_fetched)));
 
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(image.IsEmpty());
 }
 
@@ -2023,7 +2022,7 @@
       base::Bind(&MockFunction<void(const gfx::Image&)>::Call,
                  base::Unretained(&image_fetched)));
 
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   EXPECT_TRUE(image.IsEmpty()) << "got image with width: " << image.Width();
 }
 
@@ -2189,7 +2188,7 @@
       .RetiresOnSaturation();
   provider->RefetchInTheBackground(
       RemoteSuggestionsProvider::FetchStatusCallback());
-  base::RunLoop().RunUntilIdle();
+  RunUntilIdle();
   std::move(snippets_callback).Run(Status::Success(), base::nullopt);
   // TODO(jkrcal): Move together with the pref storage into the scheduler.
   EXPECT_EQ(
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_task.cc b/components/offline_pages/core/prefetch/generate_page_bundle_task.cc
index 506aa59..9641a3e 100644
--- a/components/offline_pages/core/prefetch/generate_page_bundle_task.cc
+++ b/components/offline_pages/core/prefetch/generate_page_bundle_task.cc
@@ -69,7 +69,7 @@
   return urls;
 }
 
-bool MarkExtraUrlsFinished(sql::Connection* db, const FetchedUrl& url) {
+bool MarkUrlFinishedWithError(sql::Connection* db, const FetchedUrl& url) {
   static const char kSql[] =
       "UPDATE prefetch_items SET state = ?, error_code = ?"
       " WHERE offline_id = ?";
@@ -98,7 +98,7 @@
   // and remove them from the list.
   if (urls->size() > kMaxUrlsToSend) {
     for (size_t index = kMaxUrlsToSend; index < urls->size(); ++index) {
-      if (!MarkExtraUrlsFinished(db, urls->at(index)))
+      if (!MarkUrlFinishedWithError(db, urls->at(index)))
         return nullptr;
     }
     urls->resize(kMaxUrlsToSend);
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 73a266a..8ea3004 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -466,6 +466,24 @@
   // Check if the username already exists.
   const PasswordForm* match = FindBestSavedMatch(&pending_credentials_);
   is_new_login_ = !match || match->is_public_suffix_match;
+  // Searching for the field of |match| where |new_username| was typed. If it is
+  // found, the field name is saved to |corrected_username_element_|. Otherwise,
+  // |corrected_username_element_| has no value.
+  base::string16 trimmed_username_value;
+  base::TrimString(new_username, base::ASCIIToUTF16(" "),
+                   &trimmed_username_value);
+  corrected_username_element_.reset();
+  if (!trimmed_username_value.empty()) {
+    for (size_t i = 0; i < pending_credentials_.other_possible_usernames.size();
+         ++i) {
+      if (pending_credentials_.other_possible_usernames[i].first ==
+          trimmed_username_value) {
+        corrected_username_element_ =
+            pending_credentials_.other_possible_usernames[i].second;
+        break;
+      }
+    }
+  }
 }
 
 void PasswordFormManager::PresaveGeneratedPassword(
@@ -866,6 +884,11 @@
       username_vote_type =
           autofill::AutofillUploadContents::Field::CREDENTIALS_REUSED;
     }
+    if (corrected_username_element_.has_value()) {
+      field_types[corrected_username_element_.value()] = autofill::USERNAME;
+      username_vote_type =
+          autofill::AutofillUploadContents::Field::USERNAME_EDITED;
+    }
   } else {  // User overwrites username.
     field_types[form_to_upload.username_element] = autofill::USERNAME;
     field_types[form_to_upload.password_element] =
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 5c1f5ea..f49990a 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -580,6 +580,11 @@
   // Make sure to call Init before using |*this|, to ensure it is not null.
   scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder_;
 
+  // Set if the user has edited username value in prompt. The value is the
+  // matched field name from |PasswordForm.other_possible_usernames| if the
+  // match found.
+  base::Optional<base::string16> corrected_username_element_;
+
   DISALLOW_COPY_AND_ASSIGN(PasswordFormManager);
 };
 
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 8e14116..687feb4 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -2326,12 +2326,13 @@
 TEST_F(PasswordFormManagerTest, TestUpdateUsernameMethod) {
   fake_form_fetcher()->SetNonFederated(std::vector<const PasswordForm*>(), 0u);
 
-  // User logs in, edits username.
+  // User enters credential in the form.
   PasswordForm credential(*observed_form());
   credential.username_value = ASCIIToUTF16("oldusername");
   credential.password_value = ASCIIToUTF16("password");
   form_manager()->ProvisionallySave(
       credential, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+  // User edits username in a prompt.
   form_manager()->UpdateUsername(ASCIIToUTF16("newusername"));
   EXPECT_EQ(form_manager()->pending_credentials().username_value,
             ASCIIToUTF16("newusername"));
@@ -2354,7 +2355,7 @@
   // We have an already existing credential.
   fake_form_fetcher()->SetNonFederated({saved_match()}, 0u);
 
-  // User submits credential to the observed form.
+  // User enters credential in the form.
   PasswordForm credential(*observed_form());
   credential.username_value = ASCIIToUTF16("different_username");
   credential.password_value = ASCIIToUTF16("different_pass");
@@ -2362,7 +2363,7 @@
   form_manager()->ProvisionallySave(
       credential, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
 
-  // User edits the username to the already existing one.
+  // User edits username in a prompt to one already existing.
   form_manager()->UpdateUsername(saved_match()->username_value);
 
   // The username in credentials is expected to be updated.
@@ -3106,6 +3107,7 @@
 TEST_F(PasswordFormManagerTest, ProbablyAccountCreationUpload) {
   PasswordForm form(*observed_form());
   form.form_data = saved_match()->form_data;
+  form.other_possible_usernames = saved_match()->other_possible_usernames;
 
   FakeFormFetcher fetcher;
   fetcher.Fetch();
@@ -3123,24 +3125,33 @@
 
   fetcher.SetNonFederated(std::vector<const PasswordForm*>(), 0u);
 
+  // A user submits a form and edits the username in the prompt.
+  form_manager.ProvisionallySave(
+      form_to_save, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+  form_manager.UpdateUsername(ASCIIToUTF16(" test2@gmail.com"));
+
   autofill::FormStructure pending_structure(form_to_save.form_data);
   autofill::ServerFieldTypeSet expected_available_field_types;
   std::map<base::string16, autofill::ServerFieldType> expected_types;
-  expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
   expected_types[saved_match()->username_element] = autofill::UNKNOWN_TYPE;
-  expected_available_field_types.insert(
-      autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD);
+  expected_types[ASCIIToUTF16("full_name")] = autofill::USERNAME;
   expected_types[saved_match()->password_element] =
       autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD;
+  expected_available_field_types.insert(
+      autofill::PROBABLY_ACCOUNT_CREATION_PASSWORD);
+  expected_available_field_types.insert(autofill::USERNAME);
 
-  EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
-              StartUploadRequest(
-                  CheckUploadedAutofillTypesAndSignature(
-                      pending_structure.FormSignatureAsStr(), expected_types,
-                      false /* expect_generation_vote */,
-                      autofill::AutofillUploadContents::Field::NO_INFORMATION
-                      /* expected_username_vote_type */),
-                  false, expected_available_field_types, std::string(), true));
+  autofill::AutofillUploadContents::Field::UsernameVoteType
+      expected_username_vote_type =
+          autofill::AutofillUploadContents::Field::USERNAME_EDITED;
+
+  EXPECT_CALL(
+      *client()->mock_driver()->mock_autofill_download_manager(),
+      StartUploadRequest(
+          CheckUploadedAutofillTypesAndSignature(
+              pending_structure.FormSignatureAsStr(), expected_types,
+              false /* expect_generation_vote */, expected_username_vote_type),
+          false, expected_available_field_types, std::string(), true));
 
   form_manager.ProvisionallySave(
       form_to_save, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc
index 23f7c86..8be6829 100644
--- a/components/payments/core/payments_profile_comparator.cc
+++ b/components/payments/core/payments_profile_comparator.cc
@@ -136,18 +136,6 @@
            GetRequiredProfileFieldsForContact());
 }
 
-base::string16 PaymentsProfileComparator::GetStringForMissingContactFields(
-    const autofill::AutofillProfile& profile) const {
-  return GetStringForMissingFields(GetMissingProfileFields(&profile) &
-                                   GetRequiredProfileFieldsForContact());
-}
-
-base::string16 PaymentsProfileComparator::GetTitleForMissingContactFields(
-    const autofill::AutofillProfile& profile) const {
-  return GetTitleForMissingFields(GetMissingProfileFields(&profile) &
-                                  GetRequiredProfileFieldsForContact());
-}
-
 std::vector<autofill::AutofillProfile*>
 PaymentsProfileComparator::FilterProfilesForShipping(
     const std::vector<autofill::AutofillProfile*>& profiles) const {
@@ -188,12 +176,30 @@
            GetRequiredProfileFieldsForShipping());
 }
 
+base::string16 PaymentsProfileComparator::GetStringForMissingContactFields(
+    const autofill::AutofillProfile& profile) const {
+  return GetStringForMissingFields(GetMissingProfileFields(&profile) &
+                                   GetRequiredProfileFieldsForContact());
+}
+
+base::string16 PaymentsProfileComparator::GetTitleForMissingContactFields(
+    const autofill::AutofillProfile& profile) const {
+  return GetTitleForMissingFields(GetMissingProfileFields(&profile) &
+                                  GetRequiredProfileFieldsForContact());
+}
+
 base::string16 PaymentsProfileComparator::GetStringForMissingShippingFields(
     const autofill::AutofillProfile& profile) const {
   return GetStringForMissingFields(GetMissingProfileFields(&profile) &
                                    GetRequiredProfileFieldsForShipping());
 }
 
+base::string16 PaymentsProfileComparator::GetTitleForMissingShippingFields(
+    const autofill::AutofillProfile& profile) const {
+  return GetTitleForMissingFields(GetMissingProfileFields(&profile) &
+                                  GetRequiredProfileFieldsForShipping());
+}
+
 void PaymentsProfileComparator::Invalidate(
     const autofill::AutofillProfile& profile) {
   cache_.erase(profile.guid());
diff --git a/components/payments/core/payments_profile_comparator.h b/components/payments/core/payments_profile_comparator.h
index ab7ea02..38d4332 100644
--- a/components/payments/core/payments_profile_comparator.h
+++ b/components/payments/core/payments_profile_comparator.h
@@ -101,6 +101,12 @@
   base::string16 GetStringForMissingShippingFields(
       const autofill::AutofillProfile& profile) const;
 
+  // Returns a localized string to be displayed as the title of a piece of UI,
+  // indicating what action must be taken for the given profile to be used as
+  // shipping address.
+  base::string16 GetTitleForMissingShippingFields(
+      const autofill::AutofillProfile& profile) const;
+
   // Clears the cached evaluation result for |profile|. Must be called when a
   // profile is modified and saved during the course of a PaymentRequest.
   virtual void Invalidate(const autofill::AutofillProfile& profile);
diff --git a/components/search_provider_logos/logo_tracker_unittest.cc b/components/search_provider_logos/logo_tracker_unittest.cc
index 00875da..23afb26 100644
--- a/components/search_provider_logos/logo_tracker_unittest.cc
+++ b/components/search_provider_logos/logo_tracker_unittest.cc
@@ -26,6 +26,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "build/build_config.h"
 #include "components/search_provider_logos/google_logo_api.h"
 #include "net/base/url_util.h"
 #include "net/http/http_response_headers.h"
@@ -697,7 +698,14 @@
                             base::ConstRef(observers), start_index + 1));
 }
 
-TEST_F(LogoTrackerTest, SupportOverlappingLogoRequests) {
+#if defined(THREAD_SANITIZER)
+// Flakes on Linux TSan: http://crbug/754599 (data race).
+#define MAYBE_SupportOverlappingLogoRequests \
+  DISABLED_SupportOverlappingLogoRequests
+#else
+#define MAYBE_SupportOverlappingLogoRequests SupportOverlappingLogoRequests
+#endif
+TEST_F(LogoTrackerTest, MAYBE_SupportOverlappingLogoRequests) {
   Logo cached_logo = GetSampleLogo(logo_url_, test_clock_->Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
   ON_CALL(*logo_cache_, SetCachedLogo(_)).WillByDefault(Return());
diff --git a/components/test/data/payments/bobpay.js b/components/test/data/payments/bobpay.js
index ac32393c..d93d678 100644
--- a/components/test/data/payments/bobpay.js
+++ b/components/test/data/payments/bobpay.js
@@ -7,14 +7,23 @@
 /* global PaymentRequest:false */
 
 /**
+ * Builds a payment request with URL based payment methods.
+ * @return {!PaymentRequest} A payment request with URL based payment methods.
+ * @private
+ */
+function buildPaymentRequest() {
+  return new PaymentRequest(
+      [{supportedMethods: ['https://bobpay.com', 'https://alicepay.com']}],
+      {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}});
+}
+
+/**
  * Launches the PaymentRequest UI with Bob Pay as one of multiple payment
  * methods.
  */
 function buy() {  // eslint-disable-line no-unused-vars
   try {
-    new PaymentRequest(
-        [{supportedMethods: ['https://bobpay.com', 'https://alicepay.com']}],
-        {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}})
+    buildPaymentRequest()
         .show()
         .then(function(resp) {
           resp.complete('success')
@@ -34,3 +43,21 @@
     print('exception thrown<br>' + error);
   }
 }
+
+/**
+ * Queries CanMakePayment but does not show the PaymentRequest after.
+ */
+function canMakePayment() {  // eslint-disable-line no-unused-vars
+  try {
+    buildPaymentRequest()
+        .canMakePayment()
+        .then(function(result) {
+          print(result);
+        })
+        .catch(function(error) {
+          print(error);
+        });
+  } catch (error) {
+    print('exception thrown<br>' + error);
+  }
+}
diff --git a/components/test/data/payments/payment_request_bobpay_test.html b/components/test/data/payments/payment_request_bobpay_test.html
index d2643cd..cb2d45b 100644
--- a/components/test/data/payments/payment_request_bobpay_test.html
+++ b/components/test/data/payments/payment_request_bobpay_test.html
@@ -12,7 +12,12 @@
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
-<div><button onclick="buy()" id="buy">Bob Pay Test</button></div>
+<div><button onclick="buy()" id="buy">Query buy</button></div>
+<div>
+  <button onclick="canMakePayment()" id="canMakePayment">
+    Query canMakePayment
+  </button>
+</div>
 <pre id="result"></pre>
 <script src="util.js"></script>
 <script src="bobpay.js"></script>
diff --git a/content/browser/android/string_message_codec_unittest.cc b/content/browser/android/string_message_codec_unittest.cc
index 00a85ba..d32233e3 100644
--- a/content/browser/android/string_message_codec_unittest.cc
+++ b/content/browser/android/string_message_codec_unittest.cc
@@ -5,7 +5,7 @@
 #include "content/browser/android/string_message_codec.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_async_task_scheduler.h"
+#include "base/test/scoped_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "v8/include/v8.h"
 
@@ -13,7 +13,7 @@
 namespace {
 
 base::string16 DecodeWithV8(const std::vector<uint8_t>& encoded) {
-  base::test::ScopedAsyncTaskScheduler task_scheduler;
+  base::test::ScopedTaskEnvironment scoped_task_environment;
   base::string16 result;
 
   v8::Isolate::CreateParams params;
@@ -45,7 +45,7 @@
 }
 
 std::vector<uint8_t> EncodeWithV8(const base::string16& message) {
-  base::test::ScopedAsyncTaskScheduler task_scheduler;
+  base::test::ScopedTaskEnvironment scoped_task_environment;
   std::vector<uint8_t> result;
 
   v8::Isolate::CreateParams params;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index f474afc..a6c4f7b 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -790,7 +790,13 @@
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
+#if defined(OS_ANDROID)
+// Failing/Flaky on Android: https://crbug.com/754679
+#define MAYBE_DownloadCancelled DISABLED_DownloadCancelled
+#else
+#define MAYBE_DownloadCancelled DownloadCancelled
+#endif
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, MAYBE_DownloadCancelled) {
   SetupEnsureNoPendingDownloads();
 
   // Create a download, wait until it's started, and confirm
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index c7bde34..66146f0 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2614,7 +2614,7 @@
     saved_frame_.frame = std::move(frame);
     saved_frame_.local_surface_id = local_surface_id;
     saved_frame_.max_shared_bitmap_sequence_number = max_sequence_number;
-    // TODO(gklassen): save hit-test data and restore on use.
+    saved_frame_.hit_test_region_list = std::move(hit_test_region_list);
     TRACE_EVENT_ASYNC_BEGIN2("renderer_host", "PauseCompositorFrameSink", this,
                              "LastRegisteredSequenceNumber",
                              last_registered_sequence_number,
@@ -2729,7 +2729,8 @@
     TRACE_EVENT_CATEGORY_GROUP_ENABLED(
         TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"), &tracing_enabled);
     SubmitCompositorFrame(
-        saved_frame_.local_surface_id, std::move(saved_frame_.frame), nullptr,
+        saved_frame_.local_surface_id, std::move(saved_frame_.frame),
+        std::move(saved_frame_.hit_test_region_list),
         tracing_enabled ? base::TimeTicks::Now().since_origin().InMicroseconds()
                         : 0);
     saved_frame_.local_surface_id = viz::LocalSurfaceId();
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index acf2bf5..8cc2749 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -1002,6 +1002,7 @@
     viz::LocalSurfaceId local_surface_id;
     cc::CompositorFrame frame;
     uint32_t max_shared_bitmap_sequence_number = 0;
+    viz::mojom::HitTestRegionListPtr hit_test_region_list;
   } saved_frame_;
 
   std::unique_ptr<LegacyIPCWidgetInputHandler> legacy_widget_input_handler_;
diff --git a/content/browser/webrtc/webrtc_depth_capture_browsertest.cc b/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
index 97a8e5e..f2936a8 100644
--- a/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
@@ -93,7 +93,7 @@
                        GetDepthStreamAndCameraCalibration) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   command_line->AppendSwitchASCII("--enable-blink-features",
-                                  "MediaGetSettings,MediaCaptureDepth");
+                                  "MediaCaptureDepth");
 
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -118,7 +118,7 @@
                        MAYBE_GetBothStreamsAndCheckForFeaturesPresence) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   command_line->AppendSwitchASCII("--enable-blink-features",
-                                  "MediaGetSettings,MediaCaptureDepth");
+                                  "MediaCaptureDepth");
 
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -134,7 +134,7 @@
                        GetStreamsByVideoKind) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   command_line->AppendSwitchASCII("--enable-blink-features",
-                                  "MediaGetSettings,MediaCaptureDepth");
+                                  "MediaCaptureDepthVideoKind");
 
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -150,7 +150,7 @@
                        GetStreamsByVideoKindNoDepth) {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   command_line->AppendSwitchASCII("--enable-blink-features",
-                                  "MediaGetSettings,MediaCaptureDepth");
+                                  "MediaCaptureDepthVideoKind");
 
   ASSERT_TRUE(embedded_test_server()->Start());
 
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc
index be92c59..ed7ec65 100644
--- a/content/renderer/media/user_media_client_impl.cc
+++ b/content/renderer/media/user_media_client_impl.cc
@@ -413,6 +413,12 @@
   }
 
   int request_id = g_next_request_id++;
+  WebRtcLogMessage(base::StringPrintf(
+      "UMCI::RequestUserMedia. request_id=%d, audio constraints=%s, "
+      "video constraints=%s",
+      request_id,
+      user_media_request.AudioConstraints().ToString().Utf8().c_str(),
+      user_media_request.VideoConstraints().ToString().Utf8().c_str()));
 
   // The value returned by isProcessingUserGesture() is used by the browser to
   // make decisions about the permissions UI. Its value can be lost while
@@ -701,11 +707,9 @@
 void UserMediaClientImpl::GenerateStreamForCurrentRequestInfo() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(current_request_info_);
-
   WebRtcLogMessage(base::StringPrintf(
-      "MSI::requestUserMedia. request_id=%d"
-      ", audio source id=%s"
-      ", video source id=%s",
+      "UMCI::GenerateStreamForCurrentRequestInfo. request_id=%d, "
+      "audio device id=\"%s\", video device id=\"%s\"",
       current_request_info_->request_id(),
       current_request_info_->stream_controls()->audio.device_id.c_str(),
       current_request_info_->stream_controls()->video.device_id.c_str()));
@@ -722,6 +726,11 @@
 void UserMediaClientImpl::CancelUserMediaRequest(
     const blink::WebUserMediaRequest& user_media_request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (IsCurrentRequestInfo(user_media_request)) {
+    WebRtcLogMessage(
+        base::StringPrintf("UMCI::CancelUserMediaRequest. request_id=%d",
+                           current_request_info_->request_id()));
+  }
   if (DeleteRequestInfo(user_media_request)) {
     // We can't abort the stream generation process.
     // Instead, erase the request. Once the stream is generated we will stop the
@@ -783,9 +792,10 @@
 
   for (const auto* array : {&audio_array, &video_array}) {
     for (const auto& info : *array) {
-      WebRtcLogMessage(base::StringPrintf("Request %d for device \"%s\"",
-                                          request_id,
-                                          info.device.name.c_str()));
+      WebRtcLogMessage(base::StringPrintf(
+          "UMCI::OnStreamGenerated. request_id=%d, device id=\"%s\", "
+          "device name=\"%s\"",
+          request_id, info.device.id.c_str(), info.device.name.c_str()));
     }
   }
 
@@ -1149,6 +1159,11 @@
 void UserMediaClientImpl::GetUserMediaRequestSucceeded(
     const blink::WebMediaStream& stream,
     blink::WebUserMediaRequest request) {
+  DCHECK(IsCurrentRequestInfo(request));
+  WebRtcLogMessage(
+      base::StringPrintf("UMCI::GetUserMediaRequestSucceeded. request_id=%d",
+                         current_request_info_->request_id()));
+
   // Completing the getUserMedia request can lead to that the RenderFrame and
   // the UserMediaClientImpl is destroyed if the JavaScript code request the
   // frame to be destroyed within the scope of the callback. Therefore,
@@ -1172,6 +1187,10 @@
     MediaStreamRequestResult result,
     const blink::WebString& result_name) {
   DCHECK(current_request_info_);
+  WebRtcLogMessage(
+      base::StringPrintf("UMCI::GetUserMediaRequestFailed. request_id=%d",
+                         current_request_info_->request_id()));
+
   // Completing the getUserMedia request can lead to that the RenderFrame and
   // the UserMediaClientImpl is destroyed if the JavaScript code request the
   // frame to be destroyed within the scope of the callback. Therefore,
diff --git a/extensions/browser/bad_message.h b/extensions/browser/bad_message.h
index f5dd8bc..4880568 100644
--- a/extensions/browser/bad_message.h
+++ b/extensions/browser/bad_message.h
@@ -33,6 +33,7 @@
   ESWMF_INVALID_DECREMENT_ACTIVITY = 7,
   EFD_BAD_MESSAGE = 8,
   EFD_BAD_MESSAGE_WORKER = 9,
+  WVG_PARTITION_ID_NOT_UTF8 = 10,
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. ExtensionHost becomes EH) plus a unique description of the
   // reason. After making changes, you MUST update histograms.xml by running:
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 5bda2f2..b05e286 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -47,6 +47,7 @@
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/guest_view/web_view/web_view_internal_api.h"
 #include "extensions/browser/api/web_request/web_request_api.h"
+#include "extensions/browser/bad_message.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/guest_view/web_view/web_view_constants.h"
@@ -331,9 +332,8 @@
   // creation. If the validation fails, treat it as a bad message and kill the
   // renderer process.
   if (!base::IsStringUTF8(storage_partition_id)) {
-    base::RecordAction(base::UserMetricsAction("BadMessageTerminate_BPGM"));
-    owner_render_process_host->Shutdown(content::RESULT_CODE_KILLED_BAD_MESSAGE,
-                                        false);
+    bad_message::ReceivedBadMessage(owner_render_process_host,
+                                    bad_message::WVG_PARTITION_ID_NOT_UTF8);
     callback.Run(nullptr);
     return;
   }
diff --git a/gpu/command_buffer/tests/gl_texture_storage_unittest.cc b/gpu/command_buffer/tests/gl_texture_storage_unittest.cc
index 3e474fc..73aeeda 100644
--- a/gpu/command_buffer/tests/gl_texture_storage_unittest.cc
+++ b/gpu/command_buffer/tests/gl_texture_storage_unittest.cc
@@ -169,6 +169,12 @@
 TEST_F(TextureStorageTest, CorrectImagePixels) {
   if (!extension_available_)
     return;
+  if (gl_.gpu_preferences().use_passthrough_cmd_decoder) {
+    // TODO(geofflang): crbug.com/754710
+    LOG(INFO) << "Passthrough command decoder unimplemented feature. Skipping "
+                 "test...";
+    return;
+  }
 
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BUFFER_USAGE_CHROMIUM,
                   GL_TEXTURE_BUFFER_SCANOUT_CHROMIUM);
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 9b64ed2..546e267 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -1376,6 +1376,14 @@
                               completion:nil];
 }
 
+- (void)closeSettingsUIAndOpenURL:(OpenUrlCommand*)command {
+  [self openUrlFromSettings:command];
+}
+
+- (void)closeSettingsUI {
+  [self closeSettingsAnimated:YES completion:NULL];
+}
+
 #pragma mark - chromeExecuteCommand
 
 - (IBAction)chromeExecuteCommand:(id)sender {
@@ -2370,12 +2378,12 @@
 #pragma mark - SettingsNavigationControllerDelegate
 
 - (void)closeSettings {
-  [self closeSettingsAnimated:YES completion:NULL];
+  [self closeSettingsUI];
 }
 
 // Handle a close settings and open URL command.
 - (void)closeSettingsAndOpenUrl:(OpenUrlCommand*)command {
-  [self openUrlFromSettings:command];
+  [self closeSettingsUIAndOpenURL:command];
 }
 
 - (void)closeSettingsAndOpenNewIncognitoTab {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index a231e40..eb48d60 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1167,6 +1167,9 @@
       <message name="IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE" desc="Message informing the user that the password was not copied because the authentication failed. This is shown alone in an infobar at the bottom of the screen after the user tries to reauthenticate with Touch ID or PIN to copy the password and fails. [Length: one line]">
         Can't verify your identity. Password not copied.
       </message>
+      <message name="IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_MESSAGE" desc="Message informing the user that in order to view or copy the password, a screen lock needs to be set up on the device. This is shown alone in an infobar at the bottom of the screen after the user tries to view or copy the password from a settings page. [Length: about two lines]">
+        To see passwords, set a screen lock on your device
+      </message>
       <message name="IDS_IOS_SETTINGS_TITLE" desc="Title for the settings panel [iOS].">
         Settings
       </message>
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
index 80e518b..9391c7d 100644
--- a/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/content_suggestions_mediator.mm
@@ -196,7 +196,11 @@
     if (!self.sectionInformationByCategory[categoryWrapper]) {
       [self addSectionInformationForCategory:category];
     }
-    [sectionsInfo addObject:self.sectionInformationByCategory[categoryWrapper]];
+    if (IsCategoryStatusAvailable(
+            self.contentService->GetCategoryStatus(category))) {
+      [sectionsInfo
+          addObject:self.sectionInformationByCategory[categoryWrapper]];
+    }
   }
 
   [sectionsInfo addObject:self.learnMoreSectionInfo];
@@ -340,15 +344,21 @@
             (ntp_snippets::ContentSuggestionsService*)suggestionsService
                          category:(ntp_snippets::Category)category
                   statusChangedTo:(ntp_snippets::CategoryStatus)status {
+  ContentSuggestionsCategoryWrapper* wrapper =
+      [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category];
   if (!ntp_snippets::IsCategoryStatusInitOrAvailable(status)) {
     // Remove the category from the UI if it is not available.
-    ContentSuggestionsCategoryWrapper* wrapper =
-        [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category];
     ContentSuggestionsSectionInformation* sectionInfo =
         self.sectionInformationByCategory[wrapper];
 
     [self.dataSink clearSection:sectionInfo];
     [self.sectionInformationByCategory removeObjectForKey:wrapper];
+  } else {
+    if (!self.sectionInformationByCategory[wrapper]) {
+      [self addSectionInformationForCategory:category];
+    }
+    [self.dataSink
+        dataAvailableForSection:self.sectionInformationByCategory[wrapper]];
   }
 }
 
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
index 2473324..808c492 100644
--- a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
+++ b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
@@ -9,7 +9,6 @@
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
-#include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -169,10 +168,6 @@
       browser_state->GetRequestContext();
   base::FilePath database_dir(
       browser_state->GetStatePath().Append(ntp_snippets::kDatabaseFolder));
-  scoped_refptr<base::SequencedTaskRunner> task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BACKGROUND,
-           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
 
   std::string api_key;
   // This API needs whitelisted API keys. Get the key only if it is not a
@@ -194,7 +189,7 @@
       std::move(suggestions_fetcher),
       base::MakeUnique<ImageFetcherImpl>(CreateIOSImageDecoder(),
                                          request_context.get()),
-      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir, task_runner),
+      base::MakeUnique<RemoteSuggestionsDatabase>(database_dir),
       base::MakeUnique<RemoteSuggestionsStatusServiceImpl>(signin_manager,
                                                            prefs, pref_name),
       /*prefetched_pages_tracker=*/nullptr,
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index 5d7f181..b0e8632 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -188,6 +188,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/ui",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/ntp:ntp_controller",
     "//ios/chrome/browser/ui/settings",
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
index 4436692..a4470ba 100644
--- a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
+++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
@@ -10,6 +10,7 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "ios/chrome/browser/experimental_flags.h"
 #include "ios/chrome/browser/signin/signin_manager_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/commands/open_url_command.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
@@ -62,16 +63,21 @@
       forConfigKey:kGREYConfigKeySynchronizationEnabled];
 }
 
-// Taps the view with acessibility identifier |accessibility_id|.
-void TapViewWithAccessibilityId(NSString* accessiblity_id) {
+// Taps the view with accessibility matcher |accessibility_matcher|.
+void TapViewWithMatcher(id<GREYMatcher> accessibility_matcher) {
   // grey_sufficientlyVisible() is necessary because reloading a cell in a
   // collection view might duplicate it (with the old one being hidden but
   // EarlGrey can find it).
-  id<GREYMatcher> matcher = grey_allOf(grey_accessibilityID(accessiblity_id),
-                                       grey_sufficientlyVisible(), nil);
+  id<GREYMatcher> matcher =
+      grey_allOf(accessibility_matcher, grey_sufficientlyVisible(), nil);
   [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
 }
 
+// Taps the view with acessibility identifier |accessibility_id|.
+void TapViewWithAccessibilityId(NSString* accessiblity_id) {
+  TapViewWithMatcher(grey_accessibilityID(accessiblity_id));
+}
+
 // Taps the button with accessibility label |label|.
 void TapButtonWithAccessibilityLabel(NSString* label) {
   id<GREYMatcher> matcher =
@@ -468,7 +474,7 @@
   TapButtonWithLabelId(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE);
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
-  TapViewWithAccessibilityId(kSettingsSignInCellId);
+  TapViewWithMatcher(chrome_test_util::SignInMenuButton());
   [ChromeEarlGreyUI signInToIdentityByEmail:identity1.userEmail];
 
   // Open new tab to cancel sign-in.
@@ -525,7 +531,7 @@
   [[EarlGrey selectElementWithMatcher:all_bookmarks_matcher]
       performAction:grey_tap()];
 
-  TapButtonWithLabelId(IDS_IOS_BOOKMARK_PROMO_SIGN_IN_BUTTON);
+  TapViewWithAccessibilityId(kSigninPromoSecondaryButtonId);
 
   // Assert sign-in screen was shown.
   id<GREYMatcher> signin_matcher =
@@ -554,7 +560,7 @@
   }
   [[EarlGrey selectElementWithMatcher:all_bookmarks_matcher]
       performAction:grey_tap()];
-  TapButtonWithLabelId(IDS_IOS_BOOKMARK_PROMO_SIGN_IN_BUTTON);
+  TapViewWithAccessibilityId(kSigninPromoSecondaryButtonId);
   [[EarlGrey selectElementWithMatcher:signin_matcher]
       assertWithMatcher:grey_sufficientlyVisible()];
 
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view.h b/ios/chrome/browser/ui/authentication/signin_promo_view.h
index d9eaa27..fda056f 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view.h
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view.h
@@ -20,6 +20,11 @@
   SigninPromoViewModeWarmState,
 };
 
+extern NSString* const kSigninPromoViewId;
+extern NSString* const kSigninPromoPrimaryButtonId;
+extern NSString* const kSigninPromoSecondaryButtonId;
+extern NSString* const kSigninPromoCloseButtonId;
+
 // This class creates an image view, a label and 2 buttons. This view can be
 // configured with 2 modes : "Cold State" and "Warm State".
 // + "Cold State" mode displays the chomium icon in the image view, and only
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view.mm b/ios/chrome/browser/ui/authentication/signin_promo_view.mm
index 31bb7b3..b67421d 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view.mm
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view.mm
@@ -32,6 +32,12 @@
 const CGFloat kButtonHeight = 36;
 }
 
+NSString* const kSigninPromoViewId = @"kSigninPromoViewId";
+NSString* const kSigninPromoPrimaryButtonId = @"kSigninPromoPrimaryButtonId";
+NSString* const kSigninPromoSecondaryButtonId =
+    @"kSigninPromoSecondaryButtonId";
+NSString* const kSigninPromoCloseButtonId = @"kSigninPromoCloseButtonId";
+
 @implementation SigninPromoView {
   NSArray<NSLayoutConstraint*>* _coldStateConstraints;
   NSArray<NSLayoutConstraint*>* _warmStateConstraints;
@@ -50,6 +56,7 @@
   self = [super initWithFrame:frame];
   if (self) {
     self.isAccessibilityElement = YES;
+    self.accessibilityIdentifier = kSigninPromoViewId;
 
     // Adding subviews.
     self.clipsToBounds = YES;
@@ -63,7 +70,7 @@
 
     _primaryButton = [[MDCFlatButton alloc] init];
     _primaryButton.translatesAutoresizingMaskIntoConstraints = NO;
-    _primaryButton.accessibilityIdentifier = @"signin_promo_primary_button";
+    _primaryButton.accessibilityIdentifier = kSigninPromoPrimaryButtonId;
     _primaryButton.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
     [_primaryButton addTarget:self
                        action:@selector(onPrimaryButtonAction:)
@@ -72,7 +79,7 @@
 
     _secondaryButton = [[MDCFlatButton alloc] init];
     _secondaryButton.translatesAutoresizingMaskIntoConstraints = NO;
-    _secondaryButton.accessibilityIdentifier = @"signin_promo_secondary_button";
+    _secondaryButton.accessibilityIdentifier = kSigninPromoSecondaryButtonId;
     [_secondaryButton addTarget:self
                          action:@selector(onSecondaryButtonAction:)
                forControlEvents:UIControlEventTouchUpInside];
@@ -80,7 +87,7 @@
 
     _closeButton = [[UIButton alloc] init];
     _closeButton.translatesAutoresizingMaskIntoConstraints = NO;
-    _closeButton.accessibilityIdentifier = @"signin_promo_close_button";
+    _closeButton.accessibilityIdentifier = kSigninPromoCloseButtonId;
     [self addSubview:_closeButton];
 
     // Adding style.
diff --git a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
index df450c2..5ee028e 100644
--- a/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
+++ b/ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.mm
@@ -36,8 +36,6 @@
 
 namespace {
 
-const CGFloat kTitleVerticalSpacing = 2.0f;
-
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
   SectionIdentifierMain = kSectionIdentifierEnumZero,
 };
@@ -153,6 +151,7 @@
       [super initWithLayout:layout style:CollectionViewControllerStyleAppBar];
   if (self) {
     _bridge = bridge;
+    self.title = SysUTF16ToNSString(_bridge->GetController()->GetWindowTitle());
   }
   return self;
 }
@@ -165,22 +164,6 @@
 
   self.styler.cellStyle = MDCCollectionViewCellStyleCard;
 
-  UILabel* titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-  titleLabel.text =
-      SysUTF16ToNSString(_bridge->GetController()->GetWindowTitle());
-  titleLabel.font = [UIFont boldSystemFontOfSize:16];
-  titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader;
-  [titleLabel sizeToFit];
-
-  UIView* titleView = [[UIView alloc] initWithFrame:CGRectZero];
-  [titleView addSubview:titleLabel];
-  CGRect titleBounds = titleView.bounds;
-  titleBounds.origin.y -= kTitleVerticalSpacing;
-  titleView.bounds = titleBounds;
-  titleView.autoresizingMask = UIViewAutoresizingFlexibleLeadingMargin() |
-                               UIViewAutoresizingFlexibleBottomMargin;
-  self.appBar.navigationBar.titleView = titleView;
-
   [self showCVCInputForm];
 
   // Add the navigation buttons.
@@ -540,8 +523,13 @@
   if (item.type == ItemTypeStatus) {
     return [self statusCellHeight];
   }
+
+  UIEdgeInsets inset = [self collectionView:collectionView
+                                     layout:collectionView.collectionViewLayout
+                     insetForSectionAtIndex:indexPath.section];
   return [MDCCollectionViewCell
-      cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
+      cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) -
+                                 inset.left - inset.right
                          forItem:item];
 }
 
diff --git a/ios/chrome/browser/ui/autofill/cells/cvc_item.mm b/ios/chrome/browser/ui/autofill/cells/cvc_item.mm
index b658d57..a0f3784 100644
--- a/ios/chrome/browser/ui/autofill/cells/cvc_item.mm
+++ b/ios/chrome/browser/ui/autofill/cells/cvc_item.mm
@@ -31,8 +31,6 @@
 const CGFloat kTextFieldHeight = 50;
 // Width of the date text fields.
 const CGFloat kDateTextFieldWidth = 40;
-// Width of the CVC text field.
-const CGFloat kCVCTextFieldWidth = 60;
 }
 
 @interface CVCCell ()<UITextFieldDelegate>
@@ -253,7 +251,6 @@
       // CVC content - CVC input
       [_CVCInput.leadingAnchor
           constraintEqualToAnchor:_CVCContainerView.leadingAnchor],
-      [_CVCInput.widthAnchor constraintEqualToConstant:kCVCTextFieldWidth],
       [_CVCInput.firstBaselineAnchor
           constraintEqualToAnchor:_monthInput.firstBaselineAnchor],
       [_CVCInput.bottomAnchor
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index 91ce5d6..8d4f289 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -187,6 +187,7 @@
     "//ios/chrome/browser/bookmarks:bookmarks_utils",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/ui",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/toolbar",
     "//ios/chrome/browser/ui/tools_menu",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index 9fd6d95..785d4e4 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -18,6 +18,7 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/experimental_flags.h"
 #include "ios/chrome/browser/pref_names.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
@@ -1095,16 +1096,16 @@
   }];
   // Check that promo is visible.
   [BookmarksTestCase verifyPromoAlreadySeen:NO];
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
-      assertWithMatcher:grey_notNil()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::SignInPromoView()]
+      assertWithMatcher:grey_sufficientlyVisible()];
 
   // Tap the dismiss button.
   [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(@"promo_no_thanks_button")]
+      selectElementWithMatcher:grey_accessibilityID(kSigninPromoCloseButtonId)]
       performAction:grey_tap()];
 
   // Wait until promo is gone.
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::SignInPromoView()]
       assertWithMatcher:grey_notVisible()];
 
   // Check that the promo already seen state is updated.
@@ -1126,12 +1127,16 @@
 
   // Check that promo is visible.
   [BookmarksTestCase verifyPromoAlreadySeen:NO];
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
+  [[EarlGrey
+      selectElementWithMatcher:grey_allOf(chrome_test_util::SignInPromoView(),
+                                          grey_sufficientlyVisible(), nil)]
       assertWithMatcher:grey_notNil()];
 
   // Tap the Sign in button.
   [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(@"promo_sign_in_button")]
+      selectElementWithMatcher:grey_allOf(grey_accessibilityID(
+                                              kSigninPromoSecondaryButtonId),
+                                          grey_sufficientlyVisible(), nil)]
       performAction:grey_tap()];
 
   // Tap the CANCEL button.
@@ -1141,7 +1146,9 @@
                      uppercaseString])] performAction:grey_tap()];
 
   // Check that the bookmarks UI reappeared and the cell is still here.
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"promo_view")]
+  [[EarlGrey
+      selectElementWithMatcher:grey_allOf(chrome_test_util::SignInPromoView(),
+                                          grey_sufficientlyVisible(), nil)]
       assertWithMatcher:grey_notNil()];
 
   [BookmarksTestCase verifyPromoAlreadySeen:NO];
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index e2ccc99..0a40ac3 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -283,10 +283,6 @@
   return !(url.SchemeIs(kChromeUIScheme) && url.host() == kChromeUIHistoryHost);
 }
 
-// Temporary key to use when storing native controllers vended to tabs before
-// they are added to the tab model.
-NSString* const kNativeControllerTemporaryKey = @"NativeControllerTemporaryKey";
-
 }  // namespace
 
 #pragma mark - HeaderDefinition helper
@@ -514,9 +510,8 @@
   // The currently displayed "Rate This App" dialog, if one exists.
   id<AppRatingPrompt> _rateThisAppDialog;
 
-  // Maps tab IDs to the most recent native content controller vended to that
-  // tab's web controller.
-  NSMapTable* _nativeControllersForTabIDs;
+  // Native controller vended to tab before Tab is added to the tab model.
+  id _temporaryNativeController;
 
   // Notifies the toolbar menu of reading list changes.
   ReadingListMenuNotifier* _readingListMenuNotifier;
@@ -966,7 +961,6 @@
     DCHECK(factory);
 
     _dependencyFactory = factory;
-    _nativeControllersForTabIDs = [NSMapTable strongToWeakObjectsMapTable];
     _dialogPresenter = [[DialogPresenter alloc] initWithDelegate:self
                                         presentingViewController:self];
     _dispatcher = [[CommandDispatcher alloc] init];
@@ -1562,14 +1556,7 @@
   Tab* tab = notify.userInfo[kTabModelTabKey];
   DCHECK(tab);
 
-  // Update map if a native controller was vended before the tab was added.
-  id<CRWNativeContent> nativeController =
-      [_nativeControllersForTabIDs objectForKey:kNativeControllerTemporaryKey];
-  if (nativeController) {
-    [_nativeControllersForTabIDs
-        removeObjectForKey:kNativeControllerTemporaryKey];
-    [_nativeControllersForTabIDs setObject:nativeController forKey:tab.tabId];
-  }
+  _temporaryNativeController = nil;
 
   // When adding new tabs, check what kind of reminder infobar should
   // be added to the new tab. Try to add only one of them.
@@ -3269,27 +3256,17 @@
   // TODO(crbug.com/498568): To reduce complexity here, refactor the flow so
   // that native controllers vended here always correspond to the current tab.
   Tab* currentTab = [_model currentTab];
-  NSString* nativeControllerKey = currentTab.tabId;
   if (!currentTab || currentTab.lastCommittedURL != url ||
-      [[_nativeControllersForTabIDs objectForKey:nativeControllerKey]
+      [currentTab.webController.nativeController
           isKindOfClass:[nativeController class]]) {
-    nativeControllerKey = kNativeControllerTemporaryKey;
+    _temporaryNativeController = nativeController;
   }
-  DCHECK(nativeControllerKey);
-  [_nativeControllersForTabIDs setObject:nativeController
-                                  forKey:nativeControllerKey];
   return nativeController;
 }
 
 - (id)nativeControllerForTab:(Tab*)tab {
-  id nativeController = [_nativeControllersForTabIDs objectForKey:tab.tabId];
-  if (!nativeController) {
-    // If there is no controller, check for a native controller stored under
-    // the temporary key.
-    nativeController = [_nativeControllersForTabIDs
-        objectForKey:kNativeControllerTemporaryKey];
-  }
-  return nativeController;
+  id nativeController = tab.webController.nativeController;
+  return nativeController ? nativeController : _temporaryNativeController;
 }
 
 #pragma mark - DialogPresenterDelegate methods
@@ -4767,9 +4744,6 @@
   // Cancel dialogs for |tab|'s WebState.
   [self.dialogPresenter cancelDialogForWebState:tab.webState];
 
-  // Remove stored native controllers for the tab.
-  [_nativeControllersForTabIDs removeObjectForKey:tab.tabId];
-
   // Ignore changes while the tab stack view is visible (or while suspended).
   // The display will be refreshed when this view becomes active again.
   if (!self.visible || !model.webUsageEnabled)
diff --git a/ios/chrome/browser/ui/commands/application_commands.h b/ios/chrome/browser/ui/commands/application_commands.h
index 3eee129..41f5830 100644
--- a/ios/chrome/browser/ui/commands/application_commands.h
+++ b/ios/chrome/browser/ui/commands/application_commands.h
@@ -8,6 +8,7 @@
 #import <Foundation/Foundation.h>
 
 @class OpenNewTabCommand;
+@class OpenUrlCommand;
 @class StartVoiceSearchCommand;
 
 // This protocol groups commands that are part of ApplicationCommands, but
@@ -45,6 +46,12 @@
 // Shows the History UI.
 - (void)showHistory;
 
+// Closes the History UI and opens a URL.
+- (void)closeSettingsUIAndOpenURL:(OpenUrlCommand*)command;
+
+// Closes the History UI.
+- (void)closeSettingsUI;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_APPLICATION_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
index 967abb0..5aa5a63 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -343,6 +343,8 @@
   NSInteger sectionIdentifier = SectionIdentifierForInfo(sectionInfo);
 
   if (suggestions.count == 0) {
+    // No suggestions for this section. Add the item signaling this section is
+    // empty if there is currently no item in it.
     if ([model hasSectionForSectionIdentifier:sectionIdentifier] &&
         [model numberOfItemsInSection:[model sectionForSectionIdentifier:
                                                  sectionIdentifier]] == 0) {
@@ -356,6 +358,35 @@
     return indexPaths;
   }
 
+  if (sectionIdentifier == SectionIdentifierLearnMore) {
+    // The "Learn more" items should only be displayed if there is at least one
+    // ContentSuggestions section.
+    if ((![model hasSectionForSectionIdentifier:SectionIdentifierArticles] &&
+         !
+         [model hasSectionForSectionIdentifier:SectionIdentifierReadingList]) ||
+        [model itemsInSectionWithIdentifier:sectionIdentifier].count > 0) {
+      return @[];
+    }
+  } else if (IsFromContentSuggestions(sectionIdentifier)) {
+    // If the section is a ContentSuggestions section, add the "Learn more"
+    // items if they are not already present.
+    if ([model hasSectionForSectionIdentifier:SectionIdentifierLearnMore] &&
+        [model itemsInSectionWithIdentifier:SectionIdentifierLearnMore].count ==
+            0) {
+      ContentSuggestionsSectionInformation* learnMoreSectionInfo =
+          self.sectionInfoBySectionIdentifier[@(SectionIdentifierLearnMore)];
+      for (CSCollectionViewItem* item in
+           [self.dataSource itemsForSectionInfo:learnMoreSectionInfo]) {
+        item.type = ItemTypeForInfo(learnMoreSectionInfo);
+        NSIndexPath* addedIndexPath = [self addItem:item
+                            toSectionWithIdentifier:SectionIdentifierLearnMore];
+
+        [indexPaths addObject:addedIndexPath];
+      }
+    }
+  }
+
+  // Add the items from this section.
   [suggestions enumerateObjectsUsingBlock:^(CSCollectionViewItem* item,
                                             NSUInteger index, BOOL* stop) {
     NSInteger section = [model sectionForSectionIdentifier:sectionIdentifier];
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index ed52dc6..10674d9 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -207,6 +207,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/settings",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm
index 51b4fee..590f142 100644
--- a/ios/chrome/browser/ui/history/history_ui_egtest.mm
+++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -14,6 +14,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/history/history_entry_item.h"
 #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index 0362378..21910e7 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -149,6 +149,7 @@
   testonly = true
   sources = [
     "address_edit_coordinator_unittest.mm",
+    "address_edit_mediator_unittest.mm",
     "billing_address_selection_coordinator_unittest.mm",
     "billing_address_selection_mediator_unittest.mm",
     "contact_info_edit_coordinator_unittest.mm",
@@ -229,6 +230,7 @@
     "payment_request_egtest_base.h",
     "payment_request_egtest_base.mm",
     "payment_request_misc_egtest.mm",
+    "payment_request_payment_app_egtest.mm",
     "payment_request_payment_method_identifier_egtest.mm",
     "payment_request_payment_response_egtest.mm",
     "payment_request_use_stats_egtest.mm",
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
index 99cb37e..64b972c 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -112,10 +112,17 @@
 #pragma mark - CreditCardEditViewControllerDataSource
 
 - (NSString*)title {
-  // TODO(crbug.com/602666): Title varies depending on what field is missing.
-  // e.g., Add Email vs. Add Phone Number.
-  return self.address ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_ADDRESS)
-                      : l10n_util::GetNSString(IDS_PAYMENTS_ADD_ADDRESS);
+  if (!self.address)
+    return l10n_util::GetNSString(IDS_PAYMENTS_ADD_ADDRESS);
+
+  if (self.paymentRequest->profile_comparator()->IsShippingComplete(
+          self.address)) {
+    return l10n_util::GetNSString(IDS_PAYMENTS_EDIT_ADDRESS);
+  }
+
+  return base::SysUTF16ToNSString(
+      self.paymentRequest->profile_comparator()
+          ->GetTitleForMissingShippingFields(*self.address));
 }
 
 - (CollectionViewItem*)headerItem {
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm
new file mode 100644
index 0000000..1968301
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator_unittest.mm
@@ -0,0 +1,60 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/payments/address_edit_mediator.h"
+
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/payments/payment_request_unittest_base.h"
+#include "testing/platform_test.h"
+#include "third_party/ocmock/gtest_support.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+class PaymentRequestAddressEditMediatorTest : public PaymentRequestUnitTestBase,
+                                              public PlatformTest {
+ protected:
+  void SetUp() override {
+    PaymentRequestUnitTestBase::SetUp();
+
+    CreateTestPaymentRequest();
+  }
+
+  void TearDown() override { PaymentRequestUnitTestBase::TearDown(); }
+};
+
+// Tests that the editor's title is correct in various situations.
+TEST_F(PaymentRequestAddressEditMediatorTest, Title) {
+  // No address, so the title should ask to add an address.
+  AddressEditMediator* mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:nil];
+  EXPECT_TRUE([mediator.title
+      isEqualToString:l10n_util::GetNSString(IDS_PAYMENTS_ADD_ADDRESS)]);
+
+  // Complete address, to title should prompt to edit the address.
+  autofill::AutofillProfile autofill_profile = autofill::test::GetFullProfile();
+  mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:&autofill_profile];
+  EXPECT_TRUE([mediator.title
+      isEqualToString:l10n_util::GetNSString(IDS_PAYMENTS_EDIT_ADDRESS)]);
+
+  // Some address fields are missing, so title should ask to add a valid
+  // address.
+  payment_request()->profile_comparator()->Invalidate(autofill_profile);
+  autofill::test::SetProfileInfo(
+      &autofill_profile, nullptr, nullptr, nullptr, nullptr, nullptr,
+      /* address1= */ "", /* address2= */ "",
+      /* city= */ "", nullptr, nullptr, /* country= */ "", nullptr);
+  mediator =
+      [[AddressEditMediator alloc] initWithPaymentRequest:payment_request()
+                                                  address:&autofill_profile];
+  EXPECT_TRUE([mediator.title
+      isEqualToString:l10n_util::GetNSString(IDS_PAYMENTS_ADD_VALID_ADDRESS)]);
+}
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm
new file mode 100644
index 0000000..e821ea9
--- /dev/null
+++ b/ios/chrome/browser/ui/payments/payment_request_payment_app_egtest.mm
@@ -0,0 +1,61 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/ios/ios_util.h"
+#import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h"
+#import "ios/chrome/browser/ui/payments/payment_request_view_controller.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/web/public/test/http_server/http_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// URLs of the test pages.
+const char kBobPayPage[] =
+    "https://components/test/data/payments/"
+    "payment_request_bobpay_test.html";
+
+}  // namepsace
+
+// Tests for a merchant that requests payment apps as the payment method.
+@interface PaymentRequestPaymentAppEGTest : PaymentRequestEGTestBase
+
+@end
+
+@implementation PaymentRequestPaymentAppEGTest
+
+#pragma mark - Tests
+
+// Tests that the Promise returned by show() gets rejected with a
+// NotSupportedError if the requested payment methods are payment apps that
+// are not installed.
+- (void)testShowPaymentAppNotInstalled {
+  if (!base::ios::IsRunningOnOrLater(10, 3, 0)) {
+    EARL_GREY_TEST_DISABLED(
+        @"Disabled on iOS versions below 10.3 because DOMException is not "
+        @"available.");
+  }
+
+  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kBobPayPage)];
+
+  [ChromeEarlGrey tapWebViewElementWithID:@"buy"];
+
+  [self waitForWebViewContainingTexts:{"NotSupportedError",
+                                       "The payment method is not supported"}];
+}
+
+// Tests that the Promise returned by canMakePayment() gets resolved with false
+// if the requested payment methods are payment apps that are not installed.
+- (void)testCanMakePaymentPaymentAppNotInstalled {
+  [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kBobPayPage)];
+
+  [ChromeEarlGrey tapWebViewElementWithID:@"canMakePayment"];
+
+  [self waitForWebViewContainingTexts:{"false"}];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index bb4f70b..96bcdce 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -350,6 +350,7 @@
     "//ios/chrome/browser/search_engines",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/ui:ui_internal",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/settings:test_support",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/browser/ui/util:util",
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
index 4442aac..432b587a 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
+++ b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
@@ -32,6 +32,7 @@
 using chrome_test_util::SettingsAccountButton;
 using chrome_test_util::SignOutAccountsButton;
 using chrome_test_util::SignInMenuButton;
+using chrome_test_util::SignInPromoView;
 
 namespace {
 
@@ -121,7 +122,7 @@
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()
       ->ForgetIdentity(identity, nil);
 
-  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
+  [[EarlGrey selectElementWithMatcher:SignInPromoView()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
@@ -151,7 +152,7 @@
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()
       ->ForgetIdentity(identity, nil);
 
-  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
+  [[EarlGrey selectElementWithMatcher:SignInPromoView()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
@@ -265,7 +266,7 @@
       performAction:grey_tap()];
 
   // Check that the user is signed out and the Main Settings screen is shown.
-  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
+  [[EarlGrey selectElementWithMatcher:SignInPromoView()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
index 0d97487..ebbb1623 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
+++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
@@ -18,6 +18,7 @@
 // The accessibility identifier of the sync account cell.
 extern NSString* const kSettingsAccountsSyncCellId;
 
+@protocol ApplicationCommands;
 @protocol ApplicationSettingsCommands;
 namespace ios {
 class ChromeBrowserState;
@@ -32,10 +33,11 @@
 // |browserState| must not be nil.
 // If |closeSettingsOnAddAccount| is YES, then this account table view
 // controller will close the setting screen when an account is added.
-- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
-           closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
-                          dispatcher:(id<ApplicationSettingsCommands>)dispatcher
-    NS_DESIGNATED_INITIALIZER;
+- (instancetype)
+     initWithBrowserState:(ios::ChromeBrowserState*)browserState
+closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
+               dispatcher:(id<ApplicationCommands, ApplicationSettingsCommands>)
+                              dispatcher NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)initWithLayout:(UICollectionViewLayout*)layout
                          style:(CollectionViewControllerStyle)style
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
index 08f0da6..a625081 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
@@ -34,9 +34,7 @@
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
-#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
-#import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
-#include "ios/chrome/browser/ui/commands/ios_command_ids.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/open_url_command.h"
 #import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
@@ -111,7 +109,9 @@
 // phase to avoid observing services for a browser state that is being killed.
 - (void)stopBrowserStateServiceObservers;
 
-@property(nonatomic, readonly, weak) id<ApplicationSettingsCommands> dispatcher;
+@property(nonatomic, readonly, weak)
+    id<ApplicationCommands, ApplicationSettingsCommands>
+        dispatcher;
 
 @end
 
@@ -119,10 +119,11 @@
 
 @synthesize dispatcher = _dispatcher;
 
-- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
-           closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
-                          dispatcher:
-                              (id<ApplicationSettingsCommands>)dispatcher {
+- (instancetype)
+     initWithBrowserState:(ios::ChromeBrowserState*)browserState
+closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
+               dispatcher:(id<ApplicationCommands, ApplicationSettingsCommands>)
+                              dispatcher {
   DCHECK(browserState);
   DCHECK(!browserState->IsOffTheRecord());
   UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init];
@@ -510,9 +511,7 @@
   _signinInteractionController = nil;
   [self handleAuthenticationOperationDidFinish];
   if (success && _closeSettingsOnAddAccount) {
-    GenericChromeCommand* closeSettingsCommand =
-        [[GenericChromeCommand alloc] initWithTag:IDC_CLOSE_SETTINGS];
-    [self chromeExecuteCommand:closeSettingsCommand];
+    [self.dispatcher closeSettingsUI];
   }
 }
 
@@ -648,8 +647,7 @@
     viewController:(UIViewController*)viewController {
   OpenUrlCommand* command =
       [[OpenUrlCommand alloc] initWithURLFromChrome:net::GURLWithNSURL(url)];
-  [command setTag:IDC_CLOSE_SETTINGS_AND_OPEN_URL];
-  [self chromeExecuteCommand:command];
+  [self.dispatcher closeSettingsUIAndOpenURL:command];
 }
 
 #pragma mark - ChromeIdentityServiceObserver
diff --git a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
index 6f91bea..9f49fec 100644
--- a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
@@ -319,17 +319,17 @@
 - (void)copySite {
   UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
   generalPasteboard.string = _site;
-  [self showCopyResultToast:l10n_util::GetNSString(
-                                IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE)
-                 forSuccess:YES];
+  [self showToast:l10n_util::GetNSString(
+                      IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE)
+       forSuccess:YES];
 }
 
 - (void)copyUsername {
   UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
   generalPasteboard.string = _username;
-  [self showCopyResultToast:l10n_util::GetNSString(
-                                IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE)
-                 forSuccess:YES];
+  [self showToast:l10n_util::GetNSString(
+                      IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE)
+       forSuccess:YES];
 }
 
 - (NSString*)showHideButtonText {
@@ -381,6 +381,10 @@
         attemptReauthWithLocalizedReason:
             l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_SHOW)
                                  handler:showPasswordHandler];
+  } else {
+    [self showToast:l10n_util::GetNSString(
+                        IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_MESSAGE)
+         forSuccess:NO];
   }
 }
 
@@ -402,9 +406,9 @@
   if (_plainTextPasswordShown) {
     UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
     generalPasteboard.string = _password;
-    [self showCopyResultToast:l10n_util::GetNSString(
-                                  IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)
-                   forSuccess:YES];
+    [self showToast:l10n_util::GetNSString(
+                        IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)
+         forSuccess:YES];
     UMA_HISTOGRAM_ENUMERATION(
         "PasswordManager.AccessPasswordInSettings",
         password_manager::metrics_util::ACCESS_PASSWORD_COPIED,
@@ -422,31 +426,34 @@
       if (success) {
         UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
         generalPasteboard.string = strongSelf->_password;
-        [strongSelf showCopyResultToast:
-                        l10n_util::GetNSString(
-                            IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)
-                             forSuccess:YES];
+        [strongSelf showToast:l10n_util::GetNSString(
+                                  IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE)
+                   forSuccess:YES];
         UMA_HISTOGRAM_ENUMERATION(
             "PasswordManager.AccessPasswordInSettings",
             password_manager::metrics_util::ACCESS_PASSWORD_COPIED,
             password_manager::metrics_util::ACCESS_PASSWORD_COUNT);
       } else {
-        [strongSelf showCopyResultToast:
-                        l10n_util::GetNSString(
-                            IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE)
-                             forSuccess:NO];
+        [strongSelf
+             showToast:l10n_util::GetNSString(
+                           IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE)
+            forSuccess:NO];
       }
     };
     [_weakReauthenticationModule
         attemptReauthWithLocalizedReason:
             l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_REAUTH_REASON_COPY)
                                  handler:copyPasswordHandler];
+  } else {
+    [self showToast:l10n_util::GetNSString(
+                        IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_MESSAGE)
+         forSuccess:NO];
   }
 }
 
-// Show a MD snack bar and provide haptic feedback. The haptic feedback is
-// either for success or for error, depending on |success|.
-- (void)showCopyResultToast:(NSString*)message forSuccess:(BOOL)success {
+// Show a MD snack bar with |message| and provide haptic feedback. The haptic
+// feedback is either for success or for error, depending on |success|.
+- (void)showToast:(NSString*)message forSuccess:(BOOL)success {
   // TODO(crbug.com/159166): Route this through some delegate API to be able
   // to mock it in the unittest, and avoid having an EGTest just for that?
   TriggerHapticFeedbackForNotification(success
diff --git a/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
index ea10af5..d64bccf 100644
--- a/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
@@ -348,6 +348,11 @@
 
 @interface MockReauthenticationModule : NSObject<ReauthenticationProtocol>
 
+// Indicates whether the device is capable of reauthenticating the user.
+@property(nonatomic, assign) BOOL canAttempt;
+
+// Indicates whether (mock) authentication should succeed or not. Setting
+// |shouldSucceed| to any value sets |canAttempt| to YES.
 @property(nonatomic, assign) BOOL shouldSucceed;
 
 @end
@@ -355,9 +360,15 @@
 @implementation MockReauthenticationModule
 
 @synthesize shouldSucceed = _shouldSucceed;
+@synthesize canAttempt = _canAttempt;
+
+- (void)setShouldSucceed:(BOOL)shouldSucceed {
+  _canAttempt = YES;
+  _shouldSucceed = shouldSucceed;
+}
 
 - (BOOL)canAttemptReauth {
-  return YES;
+  return _canAttempt;
 }
 
 - (void)attemptReauthWithLocalizedReason:(NSString*)localizedReason
@@ -1191,4 +1202,68 @@
       performAction:grey_tap()];
 }
 
+// Checks that an attempt to copy a password provides appropriate feedback when
+// reauthentication cannot be attempted.
+- (void)testCopyPasswordToastNoReauth {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      password_manager::features::kViewPasswords);
+
+  // Saving a form is needed for using the "password details" view.
+  SaveExamplePasswordForm();
+
+  OpenPasswordSettings();
+
+  [GetInteractionForPasswordEntry(@"example.com, concrete username")
+      performAction:grey_tap()];
+
+  MockReauthenticationModule* mock_reauthentication_module =
+      SetUpAndReturnMockReauthenticationModule();
+
+  mock_reauthentication_module.canAttempt = NO;
+  [GetInteractionForPasswordDetailItem(CopyPasswordButton())
+      performAction:grey_tap()];
+
+  NSString* snackbarLabel =
+      l10n_util::GetNSString(IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_MESSAGE);
+  // The tap checks the existence of the snackbar and also closes it.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
+      performAction:grey_tap()];
+
+  [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
+      performAction:grey_tap()];
+}
+
+// Checks that an attempt to view a password provides appropriate feedback when
+// reauthentication cannot be attempted.
+- (void)testShowPasswordToastNoReauth {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      password_manager::features::kViewPasswords);
+
+  // Saving a form is needed for using the "password details" view.
+  SaveExamplePasswordForm();
+
+  OpenPasswordSettings();
+
+  [GetInteractionForPasswordEntry(@"example.com, concrete username")
+      performAction:grey_tap()];
+
+  MockReauthenticationModule* mock_reauthentication_module =
+      SetUpAndReturnMockReauthenticationModule();
+
+  mock_reauthentication_module.canAttempt = NO;
+  [GetInteractionForPasswordDetailItem(ShowPasswordButton())
+      performAction:grey_tap()];
+
+  NSString* snackbarLabel =
+      l10n_util::GetNSString(IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_MESSAGE);
+  // The tap checks the existence of the snackbar and also closes it.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
+      performAction:grey_tap()];
+
+  [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
+      performAction:grey_tap()];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm
index b8d9fc4..6d5ae00 100644
--- a/ios/chrome/browser/ui/settings/settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -21,6 +21,7 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "ios/chrome/browser/pref_names.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
@@ -777,7 +778,7 @@
 
   // Present the Sign-in UI.
   id<GREYMatcher> matcher =
-      grey_allOf(grey_accessibilityID(kSettingsSignInCellId),
+      grey_allOf(grey_accessibilityID(kSigninPromoPrimaryButtonId),
                  grey_sufficientlyVisible(), nil);
   [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
   // Wait for UI to finish loading the Sign-in screen.
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index b17e032..15f8d63 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -165,9 +165,10 @@
   DCHECK(ios::GetChromeBrowserProvider()
              ->GetUserFeedbackProvider()
              ->IsUserFeedbackEnabled());
-  UIViewController* controller = ios::GetChromeBrowserProvider()
-                                     ->GetUserFeedbackProvider()
-                                     ->CreateViewController(dataSource);
+  UIViewController* controller =
+      ios::GetChromeBrowserProvider()
+          ->GetUserFeedbackProvider()
+          ->CreateViewController(dataSource, [delegate dispatcherForSettings]);
   DCHECK(controller);
   SettingsNavigationController* nc = [[SettingsNavigationController alloc]
       initWithRootViewController:controller
diff --git a/ios/chrome/browser/ui/settings/settings_utils.h b/ios/chrome/browser/ui/settings/settings_utils.h
index e1601b1..dcf6acd 100644
--- a/ios/chrome/browser/ui/settings/settings_utils.h
+++ b/ios/chrome/browser/ui/settings/settings_utils.h
@@ -9,6 +9,7 @@
 
 #import "ios/chrome/browser/procedural_block_types.h"
 
+@protocol ApplicationCommands;
 namespace ios_internal_settings {
 
 // Returns a ProceduralBlockWithURL that sends a chrome command up the
@@ -16,6 +17,11 @@
 // (parameter to the block) in a new tab.
 ProceduralBlockWithURL BlockToOpenURL(UIResponder* responder);
 
+// Returns a ProceduralBlockWithURL that uses the dispatcher and opens url
+// (parameter to the block) in a new tab.
+ProceduralBlockWithURL BlockToOpenURL(UIResponder* responder,
+                                      id<ApplicationCommands> dispatcher);
+
 }  // namespace ios_internal_settings
 
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_SETTINGS_UTILS_H_
diff --git a/ios/chrome/browser/ui/settings/settings_utils.mm b/ios/chrome/browser/ui/settings/settings_utils.mm
index ae3e7e9..b0750cf 100644
--- a/ios/chrome/browser/ui/settings/settings_utils.mm
+++ b/ios/chrome/browser/ui/settings/settings_utils.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/settings/settings_utils.h"
 
 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
 #import "ios/chrome/browser/ui/commands/open_url_command.h"
@@ -29,4 +30,19 @@
   return [blockToOpenURL copy];
 }
 
+ProceduralBlockWithURL BlockToOpenURL(UIResponder* responder,
+                                      id<ApplicationCommands> dispatcher) {
+  __weak UIResponder* weakResponder = responder;
+  __weak id<ApplicationCommands> weakDispatcher = dispatcher;
+  ProceduralBlockWithURL blockToOpenURL = ^(const GURL& url) {
+    UIResponder* strongResponder = weakResponder;
+    if (!strongResponder)
+      return;
+    OpenUrlCommand* command =
+        [[OpenUrlCommand alloc] initWithURLFromChrome:url];
+    [weakDispatcher closeSettingsUIAndOpenURL:command];
+  };
+  return [blockToOpenURL copy];
+}
+
 }  // namespace ios_internal_settings
diff --git a/ios/chrome/browser/ui/sync/BUILD.gn b/ios/chrome/browser/ui/sync/BUILD.gn
index 164c866..de187ce 100644
--- a/ios/chrome/browser/ui/sync/BUILD.gn
+++ b/ios/chrome/browser/ui/sync/BUILD.gn
@@ -52,6 +52,7 @@
     "//ios/chrome/browser/bookmarks:bookmarks_utils",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/sync",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/settings",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
index 0c0f325..278d2c5 100644
--- a/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
+++ b/ios/chrome/browser/ui/sync/sync_fake_server_egtest.mm
@@ -16,6 +16,7 @@
 #include "ios/chrome/browser/signin/authentication_service.h"
 #include "ios/chrome/browser/signin/authentication_service_factory.h"
 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
 #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h"
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn
index c689139e..bdd90add 100644
--- a/ios/chrome/test/app/BUILD.gn
+++ b/ios/chrome/test/app/BUILD.gn
@@ -67,6 +67,7 @@
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui:ui_internal",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/main",
     "//ios/chrome/browser/ui/ntp:ntp_controller",
diff --git a/ios/chrome/test/app/signin_test_util.h b/ios/chrome/test/app/signin_test_util.h
index 1f9fcfa..b60ada3 100644
--- a/ios/chrome/test/app/signin_test_util.h
+++ b/ios/chrome/test/app/signin_test_util.h
@@ -25,6 +25,10 @@
 // the accounts were correctly removed from the keychain.
 bool SignOutAndClearAccounts();
 
+// Resets Sign-in promo impression preferences for bookmarks and settings view,
+// and resets kIosBookmarkPromoAlreadySeen flag for bookmarks.
+void ResetSigninPromoPreferences();
+
 }  // namespace chrome_test_util
 
 #endif  // IOS_CHROME_TEST_APP_SIGNIN_TEST_UTIL_H_
diff --git a/ios/chrome/test/app/signin_test_util.mm b/ios/chrome/test/app/signin_test_util.mm
index 8fc529e..096390c 100644
--- a/ios/chrome/test/app/signin_test_util.mm
+++ b/ios/chrome/test/app/signin_test_util.mm
@@ -12,10 +12,12 @@
 #include "components/signin/core/common/signin_pref_names.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/signin/account_tracker_service_factory.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #include "ios/chrome/browser/signin/authentication_service_factory.h"
 #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
@@ -172,4 +174,12 @@
   return !identity_service->HasIdentities();
 }
 
+void ResetSigninPromoPreferences() {
+  ios::ChromeBrowserState* browser_state = GetOriginalBrowserState();
+  PrefService* prefs = browser_state->GetPrefs();
+  prefs->SetInteger(prefs::kIosBookmarkSigninPromoDisplayedCount, 0);
+  prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, false);
+  prefs->SetInteger(prefs::kIosSettingsSigninPromoDisplayedCount, 0);
+}
+
 }  // namespace chrome_test_util
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn
index bee6b5d..ceb5f1e 100644
--- a/ios/chrome/test/earl_grey/BUILD.gn
+++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -179,10 +179,12 @@
   deps = [
     "//base",
     "//base/test:test_support",
+    "//components/signin/core/common",
     "//components/strings",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/authentication:authentication",
+    "//ios/chrome/browser/ui/authentication:authentication_ui",
     "//ios/chrome/browser/ui/collection_view/cells",
     "//ios/chrome/browser/ui/commands:commands",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h
index 3212dd553..0b4e542 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -104,6 +104,9 @@
 // Returns matcher for the OK button.
 id<GREYMatcher> OKButton();
 
+// Returns matcher for the sign-in promo view in the settings menu.
+id<GREYMatcher> SignInPromoView();
+
 // Returns matcher for the signin button in the settings menu.
 id<GREYMatcher> SignInMenuButton();
 
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index f1669b5..addbce3 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -12,6 +12,7 @@
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
@@ -193,8 +194,12 @@
   return ButtonWithAccessibilityLabelId(IDS_OK);
 }
 
+id<GREYMatcher> SignInPromoView() {
+  return grey_accessibilityID(kSigninPromoViewId);
+}
+
 id<GREYMatcher> SignInMenuButton() {
-  return grey_accessibilityID(kSettingsSignInCellId);
+  return grey_accessibilityID(kSigninPromoSecondaryButtonId);
 }
 
 id<GREYMatcher> SettingsAccountButton() {
diff --git a/ios/chrome/test/earl_grey/chrome_test_case.mm b/ios/chrome/test/earl_grey/chrome_test_case.mm
index 6da92b8..4aaf058 100644
--- a/ios/chrome/test/earl_grey/chrome_test_case.mm
+++ b/ios/chrome/test/earl_grey/chrome_test_case.mm
@@ -8,8 +8,10 @@
 
 #import <EarlGrey/EarlGrey.h>
 
+#include "base/command_line.h"
 #include "base/mac/scoped_block.h"
 #include "base/strings/sys_string_conversions.h"
+#include "components/signin/core/common/signin_switches.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #include "ios/chrome/test/app/settings_test_util.h"
 #include "ios/chrome/test/app/signin_test_util.h"
@@ -163,6 +165,7 @@
   _isMockAuthenticationDisabled = NO;
   _tearDownHandler = nil;
 
+  chrome_test_util::ResetSigninPromoPreferences();
   chrome_test_util::OpenNewTab();
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
 }
@@ -247,6 +250,11 @@
 }
 
 + (void)enableMockAuthentication {
+  // Enable sign-in promo for all tests.
+  // TODO(crbug.com/739910): Remove this line when the sign-in promo is enabled
+  // by default.
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableSigninPromo);
   chrome_test_util::SetUpMockAuthentication();
   chrome_test_util::SetUpMockAccountReconcilor();
   chrome_test_util::SetUpFakeSyncServer();
diff --git a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
index f97a6b7..e5cec58 100644
--- a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
+++ b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h
@@ -9,6 +9,8 @@
 
 #include "base/macros.h"
 
+@protocol ApplicationCommands;
+
 // This data source object is used to obtain initial data to populate the fields
 // on the User Feedback form.
 @protocol UserFeedbackDataSource<NSObject>
@@ -43,6 +45,10 @@
   // Returns view controller to present to the user to collect their feedback.
   virtual UIViewController* CreateViewController(
       id<UserFeedbackDataSource> dataSource);
+  // Returns view controller to present to the user to collect their feedback.
+  virtual UIViewController* CreateViewController(
+      id<UserFeedbackDataSource> dataSource,
+      id<ApplicationCommands> dispatcher);
   // Uploads collected feedback reports.
   virtual void Synchronize();
 
diff --git a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
index 1722761..b82856a7 100644
--- a/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
+++ b/ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.mm
@@ -21,4 +21,10 @@
   return nil;
 }
 
+UIViewController* UserFeedbackProvider::CreateViewController(
+    id<UserFeedbackDataSource> dataSource,
+    id<ApplicationCommands> dispatcher) {
+  return CreateViewController(dataSource);
+}
+
 void UserFeedbackProvider::Synchronize() {}
diff --git a/ios/web/shell/shell_browser_state.mm b/ios/web/shell/shell_browser_state.mm
index de2afc75..d1b2421 100644
--- a/ios/web/shell/shell_browser_state.mm
+++ b/ios/web/shell/shell_browser_state.mm
@@ -24,8 +24,7 @@
 
   request_context_getter_ = new ShellURLRequestContextGetter(
       GetStatePath(),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE));
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::IO));
 
   BrowserState::Initialize(this, path_);
 }
diff --git a/ios/web/shell/shell_url_request_context_getter.h b/ios/web/shell/shell_url_request_context_getter.h
index 1296c1b..fc4bf06 100644
--- a/ios/web/shell/shell_url_request_context_getter.h
+++ b/ios/web/shell/shell_url_request_context_getter.h
@@ -29,8 +29,7 @@
  public:
   ShellURLRequestContextGetter(
       const base::FilePath& base_path,
-      const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner);
+      const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner);
 
   // net::URLRequestContextGetter implementation.
   net::URLRequestContext* GetURLRequestContext() override;
@@ -42,7 +41,6 @@
 
  private:
   base::FilePath base_path_;
-  scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
   std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
   std::unique_ptr<net::NetworkDelegate> network_delegate_;
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index a6c4d10..96dd6f7 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -47,10 +47,8 @@
 
 ShellURLRequestContextGetter::ShellURLRequestContextGetter(
     const base::FilePath& base_path,
-    const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
+    const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner)
     : base_path_(base_path),
-      file_task_runner_(file_task_runner),
       network_task_runner_(network_task_runner),
       proxy_config_service_(new net::ProxyConfigServiceIOS),
       net_log_(new net::NetLog()) {}
@@ -104,7 +102,9 @@
         base::WrapUnique(new net::CTPolicyEnforcer));
     transport_security_persister_.reset(new net::TransportSecurityPersister(
         url_request_context_->transport_security_state(), base_path_,
-        file_task_runner_, false));
+        base::CreateSequencedTaskRunnerWithTraits(
+            {base::MayBlock(), base::TaskPriority::BACKGROUND}),
+        false));
     storage_->set_channel_id_service(base::MakeUnique<net::ChannelIDService>(
         new net::DefaultChannelIDStore(nullptr)));
     storage_->set_http_server_properties(
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 1750621..e9617da 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -343,11 +343,6 @@
   GURL _defaultURL;
   // Show overlay view, don't reload web page.
   BOOL _overlayPreviewMode;
-  // The URL of an expected future recreation of the |webView|. Valid
-  // only if the web view was discarded for non-user-visible reasons, such that
-  // if the next load request is for that URL, it should be treated as a
-  // reconstruction that should use cache aggressively.
-  GURL _expectedReconstructionURL;
   // Whether the web page is currently performing window.history.pushState or
   // window.history.replaceState
   // Set to YES on window.history.willChangeState message. To NO on
@@ -535,9 +530,8 @@
 // Wraps the web view in a CRWWebViewContentView and adds it to the container
 // view.
 - (void)displayWebView;
-// Removes webView, optionally tracking the URL of the evicted
-// page for later cache-based reconstruction.
-- (void)removeWebViewAllowingCachedReconstruction:(BOOL)allowCache;
+// Removes webView.
+- (void)removeWebView;
 // Called when web view process has been terminated.
 - (void)webViewWebProcessDidCrash;
 // Returns the WKWebViewConfigurationProvider associated with the web
@@ -1105,7 +1099,7 @@
       // Don't create the web view; let it be lazy created as needed.
     } else {
       [self clearTransientContentView];
-      [self removeWebViewAllowingCachedReconstruction:YES];
+      [self removeWebView];
       _touchTrackingRecognizer.get().touchTrackingDelegate = nil;
       _touchTrackingRecognizer.reset();
       [self resetContainerView];
@@ -1114,7 +1108,7 @@
 }
 
 - (void)requirePageReconstruction {
-  [self removeWebViewAllowingCachedReconstruction:NO];
+  [self removeWebView];
 }
 
 - (void)requirePageReload {
@@ -1183,7 +1177,7 @@
   _isBeingDestroyed = YES;
 
   // Remove the web view now. Otherwise, delegate callbacks occur.
-  [self removeWebViewAllowingCachedReconstruction:NO];
+  [self removeWebView];
 
   // Explicitly reset content to clean up views and avoid dangling KVO
   // observers.
@@ -1764,7 +1758,7 @@
 
 - (void)loadErrorInNativeView:(NSError*)error
             navigationContext:(web::NavigationContextImpl*)context {
-  [self removeWebViewAllowingCachedReconstruction:NO];
+  [self removeWebView];
   web::NavigationItem* item = self.currentNavItem;
   const GURL currentURL = item ? item->GetVirtualURL() : GURL::EmptyGURL();
 
@@ -1791,7 +1785,7 @@
 // provider.
 - (void)loadCurrentURLInNativeView {
   // Free the web view.
-  [self removeWebViewAllowingCachedReconstruction:NO];
+  [self removeWebView];
 
   web::NavigationItem* item = self.currentNavItem;
   const GURL targetURL = item ? item->GetURL() : GURL::EmptyGURL();
@@ -1911,10 +1905,6 @@
   } else {
     [self loadCurrentURLInWebView];
   }
-
-  // Once a URL has been loaded, any cached-based reconstruction state has
-  // either been handled or obsoleted.
-  _expectedReconstructionURL = GURL();
 }
 
 - (GURL)webURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel {
@@ -3089,7 +3079,7 @@
           [_delegate controllerForUnhandledContentAtURL:errorGURL];
       if (controller) {
         [self loadCompleteWithSuccess:NO forNavigation:navigation];
-        [self removeWebViewAllowingCachedReconstruction:NO];
+        [self removeWebView];
         [self setNativeController:controller];
         [self loadNativeViewWithSuccess:YES
                       navigationContext:navigationContext];
@@ -4069,19 +4059,12 @@
   [_containerView displayWebViewContentView:webViewContentView];
 }
 
-- (void)removeWebViewAllowingCachedReconstruction:(BOOL)allowCache {
+- (void)removeWebView {
   if (!_webView)
     return;
 
   _webStateImpl->CancelDialogs();
 
-  web::NavigationItem* item = self.currentNavItem;
-  if (allowCache && item) {
-    _expectedReconstructionURL = item->GetVirtualURL();
-  } else {
-    _expectedReconstructionURL = GURL::EmptyGURL();
-  }
-
   [self abortLoad];
   [_webView removeFromSuperview];
   [_containerView resetContent];
@@ -5193,7 +5176,7 @@
 #pragma mark Testing-Only Methods
 
 - (void)injectWebViewContentView:(CRWWebViewContentView*)webViewContentView {
-  [self removeWebViewAllowingCachedReconstruction:NO];
+  [self removeWebView];
 
   _lastRegisteredRequestURL = _defaultURL;
   [_containerView displayWebViewContentView:webViewContentView];
diff --git a/net/base/net_string_util_icu_alternatives_android.cc b/net/base/net_string_util_icu_alternatives_android.cc
index 1b56c48..76d9326 100644
--- a/net/base/net_string_util_icu_alternatives_android.cc
+++ b/net/base/net_string_util_icu_alternatives_android.cc
@@ -26,8 +26,8 @@
   base::android::ScopedJavaLocalRef<jstring> java_charset =
       base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
   ScopedJavaLocalRef<jstring> java_result =
-      android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer.obj(),
-                                                   java_charset.obj());
+      android::Java_NetStringUtil_convertToUnicode(env, java_byte_buffer,
+                                                   java_charset);
   return java_result;
 }
 
@@ -44,7 +44,7 @@
       base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
   ScopedJavaLocalRef<jstring> java_result =
       android::Java_NetStringUtil_convertToUnicodeAndNormalize(
-          env, java_byte_buffer.obj(), java_charset.obj());
+          env, java_byte_buffer, java_charset);
   return java_result;
 }
 
@@ -60,7 +60,7 @@
       base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
   ScopedJavaLocalRef<jstring> java_result =
       android::Java_NetStringUtil_convertToUnicodeWithSubstitutions(
-          env, java_byte_buffer.obj(), java_charset.obj());
+          env, java_byte_buffer, java_charset);
   return java_result;
 }
 
diff --git a/services/resource_coordinator/OWNERS b/services/resource_coordinator/OWNERS
index 90125c9..a7d39f9 100644
--- a/services/resource_coordinator/OWNERS
+++ b/services/resource_coordinator/OWNERS
@@ -1,5 +1,6 @@
 chrisha@chromium.org
 haraken@chromium.org
 oysteine@chromium.org
-primiano@chromium.org
 zhenw@chromium.org
+
+per-file BUILD.gn=file://services/resource_coordinator/memory_instrumentation/OWNERS
diff --git a/services/resource_coordinator/memory_instrumentation/OWNERS b/services/resource_coordinator/memory_instrumentation/OWNERS
new file mode 100644
index 0000000..ca595d7
--- /dev/null
+++ b/services/resource_coordinator/memory_instrumentation/OWNERS
@@ -0,0 +1,2 @@
+hjd@chromium.org
+primiano@chromium.org
diff --git a/services/resource_coordinator/public/cpp/OWNERS b/services/resource_coordinator/public/cpp/OWNERS
index 6847a94..8d2da1a 100644
--- a/services/resource_coordinator/public/cpp/OWNERS
+++ b/services/resource_coordinator/public/cpp/OWNERS
@@ -1,3 +1,5 @@
+per-file BUILD.gn=file://services/resource_coordinator/memory_instrumentation/OWNERS
+
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
 
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS b/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
index 6847a94..eb6a334 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
@@ -1,3 +1,5 @@
+file://services/resource_coordinator/memory_instrumentation/OWNERS
+
 per-file *.typemap=set noparent
 per-file *.typemap=file://ipc/SECURITY_OWNERS
 
diff --git a/services/resource_coordinator/public/cpp/tracing/OWNERS b/services/resource_coordinator/public/cpp/tracing/OWNERS
index b67fe43..dd00922 100644
--- a/services/resource_coordinator/public/cpp/tracing/OWNERS
+++ b/services/resource_coordinator/public/cpp/tracing/OWNERS
@@ -1 +1,2 @@
+file://base/trace_event/OWNERS
 chiniforooshan@chromium.org
diff --git a/services/resource_coordinator/public/interfaces/OWNERS b/services/resource_coordinator/public/interfaces/OWNERS
index 08850f4..5c3a6ac4 100644
--- a/services/resource_coordinator/public/interfaces/OWNERS
+++ b/services/resource_coordinator/public/interfaces/OWNERS
@@ -1,2 +1,4 @@
+per-file BUILD.gn=file://services/resource_coordinator/memory_instrumentation/OWNERS
+
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn
index 231f064..126bb9a 100644
--- a/services/service_manager/embedder/BUILD.gn
+++ b/services/service_manager/embedder/BUILD.gn
@@ -3,33 +3,40 @@
 # found in the LICENSE file.
 
 component("embedder") {
-  sources = [
-    "embedded_service_info.cc",
+  public = [
     "embedded_service_info.h",
-    "embedded_service_runner.cc",
     "embedded_service_runner.h",
-    "manifest_utils.cc",
     "manifest_utils.h",
   ]
 
+  sources = [
+    "embedded_instance_manager.cc",
+    "embedded_instance_manager.h",
+    "embedded_service_info.cc",
+    "embedded_service_runner.cc",
+    "manifest_utils.cc",
+  ]
+
   # iOS embeds the Service Manager but does not use service_manager::Main() (and
   # cannot use or even build it as-is).
   if (!is_ios) {
-    sources += [
-      "main.cc",
+    public += [
       "main.h",
-      "main_delegate.cc",
       "main_delegate.h",
       "process_type.h",
+      "set_process_title.h",
+      "set_process_title_linux.h",
+      "shared_file_util.h",
+      "switches.h",
+    ]
+    sources += [
+      "main.cc",
+      "main_delegate.cc",
       "service_manager_embedder_export.h",
       "set_process_title.cc",
-      "set_process_title.h",
       "set_process_title_linux.cc",
-      "set_process_title_linux.h",
       "shared_file_util.cc",
-      "shared_file_util.h",
       "switches.cc",
-      "switches.h",
     ]
   }
 
diff --git a/services/service_manager/embedder/embedded_instance_manager.cc b/services/service_manager/embedder/embedded_instance_manager.cc
new file mode 100644
index 0000000..b5c4104
--- /dev/null
+++ b/services/service_manager/embedder/embedded_instance_manager.cc
@@ -0,0 +1,127 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/service_manager/embedder/embedded_instance_manager.h"
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace service_manager {
+
+EmbeddedInstanceManager::EmbeddedInstanceManager(
+    const base::StringPiece& name,
+    const EmbeddedServiceInfo& info,
+    const base::Closure& quit_closure)
+    : name_(name.as_string()),
+      factory_callback_(info.factory),
+      use_own_thread_(!info.task_runner && info.use_own_thread),
+      message_loop_type_(info.message_loop_type),
+      thread_priority_(info.thread_priority),
+      quit_closure_(quit_closure),
+      quit_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      service_task_runner_(info.task_runner) {
+  if (!use_own_thread_ && !service_task_runner_)
+    service_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+}
+
+void EmbeddedInstanceManager::BindServiceRequest(
+    service_manager::mojom::ServiceRequest request) {
+  DCHECK_CALLED_ON_VALID_THREAD(runner_thread_checker_);
+
+  if (use_own_thread_ && !thread_) {
+    // Start a new thread if necessary.
+    thread_.reset(new base::Thread(name_));
+    base::Thread::Options options;
+    options.message_loop_type = message_loop_type_;
+    options.priority = thread_priority_;
+    thread_->StartWithOptions(options);
+    service_task_runner_ = thread_->task_runner();
+  }
+
+  DCHECK(service_task_runner_);
+  service_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&EmbeddedInstanceManager::BindServiceRequestOnServiceSequence,
+                 this, base::Passed(&request)));
+}
+
+void EmbeddedInstanceManager::ShutDown() {
+  DCHECK_CALLED_ON_VALID_THREAD(runner_thread_checker_);
+  if (!service_task_runner_)
+    return;
+  // Any extant ServiceContexts must be destroyed on the application thread.
+  if (service_task_runner_->RunsTasksInCurrentSequence()) {
+    QuitOnServiceSequence();
+  } else {
+    service_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&EmbeddedInstanceManager::QuitOnServiceSequence, this));
+  }
+}
+
+EmbeddedInstanceManager::~EmbeddedInstanceManager() {
+  // If this instance had its own thread, it MUST be explicitly destroyed by
+  // QuitOnRunnerThread() by the time this destructor is run.
+  DCHECK(!thread_);
+}
+
+void EmbeddedInstanceManager::BindServiceRequestOnServiceSequence(
+    service_manager::mojom::ServiceRequest request) {
+  DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
+
+  int instance_id = next_instance_id_++;
+
+  std::unique_ptr<service_manager::ServiceContext> context =
+      base::MakeUnique<service_manager::ServiceContext>(factory_callback_.Run(),
+                                                        std::move(request));
+
+  service_manager::ServiceContext* raw_context = context.get();
+  context->SetQuitClosure(
+      base::Bind(&EmbeddedInstanceManager::OnInstanceLost, this, instance_id));
+  contexts_.insert(std::make_pair(raw_context, std::move(context)));
+  id_to_context_map_.insert(std::make_pair(instance_id, raw_context));
+}
+
+void EmbeddedInstanceManager::OnInstanceLost(int instance_id) {
+  DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
+
+  auto id_iter = id_to_context_map_.find(instance_id);
+  CHECK(id_iter != id_to_context_map_.end());
+
+  auto context_iter = contexts_.find(id_iter->second);
+  CHECK(context_iter != contexts_.end());
+  contexts_.erase(context_iter);
+  id_to_context_map_.erase(id_iter);
+
+  // If we've lost the last instance, run the quit closure.
+  if (contexts_.empty())
+    QuitOnServiceSequence();
+}
+
+void EmbeddedInstanceManager::QuitOnServiceSequence() {
+  DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
+
+  contexts_.clear();
+  if (quit_task_runner_->RunsTasksInCurrentSequence()) {
+    QuitOnRunnerThread();
+  } else {
+    quit_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&EmbeddedInstanceManager::QuitOnRunnerThread, this));
+  }
+}
+
+void EmbeddedInstanceManager::QuitOnRunnerThread() {
+  DCHECK_CALLED_ON_VALID_THREAD(runner_thread_checker_);
+  if (thread_) {
+    thread_.reset();
+    service_task_runner_ = nullptr;
+  }
+  quit_closure_.Run();
+}
+
+}  // namespace service_manager
diff --git a/services/service_manager/embedder/embedded_instance_manager.h b/services/service_manager/embedder/embedded_instance_manager.h
new file mode 100644
index 0000000..4a9519d
--- /dev/null
+++ b/services/service_manager/embedder/embedded_instance_manager.h
@@ -0,0 +1,98 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_SERVICE_MANAGER_EMBEDDER_EMBEDDED_INSTANCE_MANAGER_H_
+#define SERVICES_SERVICE_MANAGER_EMBEDDER_EMBEDDED_INSTANCE_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_piece.h"
+#include "base/threading/thread_checker.h"
+#include "services/service_manager/embedder/embedded_service_info.h"
+#include "services/service_manager/embedder/service_manager_embedder_export.h"
+#include "services/service_manager/public/cpp/service_context.h"
+
+namespace base {
+class SequencedTaskRunner;
+class SingleThreadTaskRunner;
+class Thread;
+
+enum class ThreadPriority : int;
+}  // namespace base
+
+namespace service_manager {
+
+// EmbeddedInstanceManager is an implementation detail of EmbeddedServiceRunner.
+// Outside of tests there is no need to use it directly.
+class SERVICE_MANAGER_EMBEDDER_EXPORT EmbeddedInstanceManager
+    : public base::RefCountedThreadSafe<EmbeddedInstanceManager> {
+ public:
+  EmbeddedInstanceManager(const base::StringPiece& name,
+                          const EmbeddedServiceInfo& info,
+                          const base::Closure& quit_closure);
+
+  void BindServiceRequest(service_manager::mojom::ServiceRequest request);
+
+  void ShutDown();
+
+ private:
+  friend class base::RefCountedThreadSafe<EmbeddedInstanceManager>;
+
+  ~EmbeddedInstanceManager();
+
+  void BindServiceRequestOnServiceSequence(
+      service_manager::mojom::ServiceRequest request);
+
+  void OnInstanceLost(int instance_id);
+
+  void QuitOnServiceSequence();
+
+  void QuitOnRunnerThread();
+
+  const std::string name_;
+  const EmbeddedServiceInfo::ServiceFactory factory_callback_;
+  const bool use_own_thread_;
+  base::MessageLoop::Type message_loop_type_;
+  base::ThreadPriority thread_priority_;
+  const base::Closure quit_closure_;
+  const scoped_refptr<base::SingleThreadTaskRunner> quit_task_runner_;
+
+  // Thread checker used to ensure certain operations happen only on the
+  // runner's (i.e. our owner's) thread.
+  THREAD_CHECKER(runner_thread_checker_);
+
+  // These fields must only be accessed from the runner's thread.
+  std::unique_ptr<base::Thread> thread_;
+  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
+
+  // These fields must only be accessed from the service thread, except in
+  // the destructor which may run on either the runner thread or the service
+  // thread.
+
+  // A map which owns all existing Service instances for this service.
+  using ServiceContextMap =
+      std::map<service_manager::ServiceContext*,
+               std::unique_ptr<service_manager::ServiceContext>>;
+  ServiceContextMap contexts_;
+
+  int next_instance_id_ = 0;
+
+  // A mapping from instance ID to (not owned) ServiceContext.
+  //
+  // TODO(rockot): Remove this once we get rid of the quit closure argument to
+  // service factory functions.
+  std::map<int, service_manager::ServiceContext*> id_to_context_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmbeddedInstanceManager);
+};
+
+}  // namespace service_manager
+
+#endif  // SERVICES_SERVICE_MANAGER_EMBEDDER_EMBEDDED_INSTANCE_MANAGER_H_
diff --git a/services/service_manager/embedder/embedded_service_runner.cc b/services/service_manager/embedder/embedded_service_runner.cc
index 66cb85e..2b1e34b 100644
--- a/services/service_manager/embedder/embedded_service_runner.cc
+++ b/services/service_manager/embedder/embedded_service_runner.cc
@@ -4,178 +4,17 @@
 
 #include "services/service_manager/embedder/embedded_service_runner.h"
 
-#include <map>
-#include <memory>
-#include <utility>
-#include <vector>
-
 #include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "services/service_manager/embedder/embedded_instance_manager.h"
 #include "services/service_manager/public/cpp/service_context.h"
 
 namespace service_manager {
 
-class EmbeddedServiceRunner::InstanceManager
-    : public base::RefCountedThreadSafe<InstanceManager> {
- public:
-  InstanceManager(const base::StringPiece& name,
-                  const EmbeddedServiceInfo& info,
-                  const base::Closure& quit_closure)
-      : name_(name.as_string()),
-        factory_callback_(info.factory),
-        use_own_thread_(!info.task_runner && info.use_own_thread),
-        message_loop_type_(info.message_loop_type),
-        thread_priority_(info.thread_priority),
-        quit_closure_(quit_closure),
-        quit_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-        service_task_runner_(info.task_runner) {
-    if (!use_own_thread_ && !service_task_runner_)
-      service_task_runner_ = base::ThreadTaskRunnerHandle::Get();
-  }
-
-  void BindServiceRequest(service_manager::mojom::ServiceRequest request) {
-    DCHECK(runner_thread_checker_.CalledOnValidThread());
-
-    if (use_own_thread_ && !thread_) {
-      // Start a new thread if necessary.
-      thread_.reset(new base::Thread(name_));
-      base::Thread::Options options;
-      options.message_loop_type = message_loop_type_;
-      options.priority = thread_priority_;
-      thread_->StartWithOptions(options);
-      service_task_runner_ = thread_->task_runner();
-    }
-
-    DCHECK(service_task_runner_);
-    service_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&InstanceManager::BindServiceRequestOnServiceSequence, this,
-                   base::Passed(&request)));
-  }
-
-  void ShutDown() {
-    DCHECK(runner_thread_checker_.CalledOnValidThread());
-    if (!service_task_runner_)
-      return;
-    // Any extant ServiceContexts must be destroyed on the application thread.
-    if (service_task_runner_->RunsTasksInCurrentSequence()) {
-      QuitOnServiceSequence();
-    } else {
-      service_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&InstanceManager::QuitOnServiceSequence, this));
-    }
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<InstanceManager>;
-
-  ~InstanceManager() {
-    // If this instance had its own thread, it MUST be explicitly destroyed by
-    // QuitOnRunnerThread() by the time this destructor is run.
-    DCHECK(!thread_);
-  }
-
-  void BindServiceRequestOnServiceSequence(
-      service_manager::mojom::ServiceRequest request) {
-    DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
-
-    int instance_id = next_instance_id_++;
-
-    std::unique_ptr<service_manager::ServiceContext> context =
-        base::MakeUnique<service_manager::ServiceContext>(
-            factory_callback_.Run(), std::move(request));
-
-    service_manager::ServiceContext* raw_context = context.get();
-    context->SetQuitClosure(
-        base::Bind(&InstanceManager::OnInstanceLost, this, instance_id));
-    contexts_.insert(std::make_pair(raw_context, std::move(context)));
-    id_to_context_map_.insert(std::make_pair(instance_id, raw_context));
-  }
-
-  void OnInstanceLost(int instance_id) {
-    DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
-
-    auto id_iter = id_to_context_map_.find(instance_id);
-    CHECK(id_iter != id_to_context_map_.end());
-
-    auto context_iter = contexts_.find(id_iter->second);
-    CHECK(context_iter != contexts_.end());
-    contexts_.erase(context_iter);
-    id_to_context_map_.erase(id_iter);
-
-    // If we've lost the last instance, run the quit closure.
-    if (contexts_.empty())
-      QuitOnServiceSequence();
-  }
-
-  void QuitOnServiceSequence() {
-    DCHECK(service_task_runner_->RunsTasksInCurrentSequence());
-
-    contexts_.clear();
-    if (quit_task_runner_->RunsTasksInCurrentSequence()) {
-      QuitOnRunnerThread();
-    } else {
-      quit_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&InstanceManager::QuitOnRunnerThread, this));
-    }
-  }
-
-  void QuitOnRunnerThread() {
-    DCHECK(runner_thread_checker_.CalledOnValidThread());
-    if (thread_) {
-      thread_.reset();
-      service_task_runner_ = nullptr;
-    }
-    quit_closure_.Run();
-  }
-
-  const std::string name_;
-  const EmbeddedServiceInfo::ServiceFactory factory_callback_;
-  const bool use_own_thread_;
-  base::MessageLoop::Type message_loop_type_;
-  base::ThreadPriority thread_priority_;
-  const base::Closure quit_closure_;
-  const scoped_refptr<base::SingleThreadTaskRunner> quit_task_runner_;
-
-  // Thread checker used to ensure certain operations happen only on the
-  // runner's (i.e. our owner's) thread.
-  base::ThreadChecker runner_thread_checker_;
-
-  // These fields must only be accessed from the runner's thread.
-  std::unique_ptr<base::Thread> thread_;
-  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
-
-  // These fields must only be accessed from the service thread, except in
-  // the destructor which may run on either the runner thread or the service
-  // thread.
-
-  // A map which owns all existing Service instances for this service.
-  using ServiceContextMap =
-      std::map<service_manager::ServiceContext*,
-               std::unique_ptr<service_manager::ServiceContext>>;
-  ServiceContextMap contexts_;
-
-  int next_instance_id_ = 0;
-
-  // A mapping from instance ID to (not owned) ServiceContext.
-  //
-  // TODO(rockot): Remove this once we get rid of the quit closure argument to
-  // service factory functions.
-  std::map<int, service_manager::ServiceContext*> id_to_context_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstanceManager);
-};
 
 EmbeddedServiceRunner::EmbeddedServiceRunner(const base::StringPiece& name,
                                              const EmbeddedServiceInfo& info)
     : weak_factory_(this) {
-  instance_manager_ = new InstanceManager(
+  instance_manager_ = new EmbeddedInstanceManager(
       name, info,
       base::Bind(&EmbeddedServiceRunner::OnQuit, weak_factory_.GetWeakPtr()));
 }
diff --git a/services/service_manager/embedder/embedded_service_runner.h b/services/service_manager/embedder/embedded_service_runner.h
index 5321a62..11f7678 100644
--- a/services/service_manager/embedder/embedded_service_runner.h
+++ b/services/service_manager/embedder/embedded_service_runner.h
@@ -20,6 +20,8 @@
 
 namespace service_manager {
 
+class EmbeddedInstanceManager;
+
 // Hosts in-process service instances for a given service.
 class SERVICE_MANAGER_EMBEDDER_EXPORT EmbeddedServiceRunner {
  public:
@@ -43,7 +45,7 @@
   void OnQuit();
 
   // A reference to the instance manager, which may operate on another thread.
-  scoped_refptr<InstanceManager> instance_manager_;
+  scoped_refptr<EmbeddedInstanceManager> instance_manager_;
 
   base::Closure quit_closure_;
 
diff --git a/services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h b/services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h
index 41a87ca..aaba32e 100644
--- a/services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h
+++ b/services/viz/public/cpp/compositing/compositor_frame_metadata_struct_traits.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_IPC_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
-#define CC_IPC_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
+
+#include <vector>
 
 #include "cc/output/compositor_frame_metadata.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_metadata.mojom-shared.h"
@@ -136,4 +138,4 @@
 
 }  // namespace mojo
 
-#endif  // CC_IPC_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
+#endif  // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_COMPOSITOR_FRAME_METADATA_STRUCT_TRAITS_H_
diff --git a/services/viz/public/cpp/compositing/resource_settings_struct_traits.h b/services/viz/public/cpp/compositing/resource_settings_struct_traits.h
index 3c5021d..3620d89 100644
--- a/services/viz/public/cpp/compositing/resource_settings_struct_traits.h
+++ b/services/viz/public/cpp/compositing/resource_settings_struct_traits.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_VIZ_PUBLIC_INTERFACES_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
-#define SERVICES_VIZ_PUBLIC_INTERFACES_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
+
+#include <utility>
 
 #include "components/viz/common/resources/resource_settings.h"
 #include "services/viz/public/interfaces/compositing/resource_settings.mojom.h"
@@ -21,15 +23,21 @@
   static ConstIterator GetBegin(const viz::BufferToTextureTargetMap& input) {
     return input.begin();
   }
-  static Iterator GetBegin(viz::BufferToTextureTargetMap& input) {
+  static Iterator GetBegin(viz::BufferToTextureTargetMap& input) {  // NOLINT
     return input.begin();
   }
 
-  static void AdvanceIterator(ConstIterator& iterator) { iterator++; }
-  static void AdvanceIterator(Iterator& iterator) { iterator++; }
+  static void AdvanceIterator(ConstIterator& iterator) {  // NOLINT
+    iterator++;
+  }
+  static void AdvanceIterator(Iterator& iterator) {  // NOLINT
+    iterator++;
+  }
 
-  static const Element& GetValue(ConstIterator& iterator) { return *iterator; }
-  static Element& GetValue(Iterator& iterator) { return *iterator; }
+  static const Element& GetValue(ConstIterator& iterator) {  // NOLINT
+    return *iterator;
+  }
+  static Element& GetValue(Iterator& iterator) { return *iterator; }  // NOLINT
 
   static size_t GetSize(const viz::BufferToTextureTargetMap& input) {
     return input.size();
@@ -89,4 +97,4 @@
 
 }  // namespace mojo
 
-#endif  // SERVICES_VIZ_PUBLIC_INTERFACES_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
+#endif  // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RESOURCE_SETTINGS_STRUCT_TRAITS_H_
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 3e50d58..6c390a9 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -49,195 +49,6 @@
         "test": "android_webview_unittests"
       },
       {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "base_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "base_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "blink_heap_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "breakpad_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "breakpad_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "capture_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "cc_unittests"
-      },
-      {
         "args": [
           "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
           "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk"
@@ -282,333 +93,6 @@
         "test": "chrome_public_test_vr_apk"
       },
       {
-        "args": [
-          "--gs-results-bucket=chromium-result-details"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "chrome_sync_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "chrome_sync_shell_test_apk"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "components_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "components_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 2
-        },
-        "test": "components_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "4",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 1200,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 3
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "content_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "device_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "device_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "events_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "events_unittests"
-      },
-      {
         "merge": {
           "args": [
             "--bucket",
@@ -654,85 +138,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "gl_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gl_tests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gl_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 120,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gl_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "gpu_ipc_service_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -772,85 +177,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "gpu_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ipc_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "latency_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -929,627 +255,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "media_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_common_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 120,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_common_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_public_bindings_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 120,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_public_bindings_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_public_system_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 120,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_public_system_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_system_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 300,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_system_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 300,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_test_apk"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "net_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 3
-        },
-        "test": "net_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "sandbox_linux_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 300,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "services_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "sql_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "storage_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_android_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_android_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_base_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_touch_selection_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "unit_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 2
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "android_devices": "1",
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "vr_common_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index 5a7e2f7..f03da2b8 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -54,8 +54,6 @@
   # is not there yet -- so don't let manage.py add swarming automatically there.
   'Android User Builder Tests',
   'Android GN',
-  'Android Tests',
-  'Android Tests (dbg)',
 
   # http://crbug.com/441429
   'Linux Trusty (32)', 'Linux Trusty (dbg)(32)',
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 44fd6622..ce44765 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1084,9 +1084,6 @@
 crbug.com/377696 printing/setPrinting.html [ Skip ]
 crbug.com/377696 printing/width-overflow.html [ Skip ]
 
-# Skia roll
-crbug.com/630695 svg/custom/massive-coordinates.svg [ NeedsManualRebaseline ]
-
 crbug.com/658305 css3/filters/buffer-offset.html [ Failure Pass ]
 crbug.com/658305 css3/filters/effect-all-on-background-hw.html [ Failure Pass ]
 crbug.com/658305 css3/filters/effect-reference-after.html [ Failure Pass ]
@@ -2667,6 +2664,8 @@
 
 crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ]
 
+crbug.com/754669 virtual/mojo-loading/http/tests/media/media-source/mediasource-duration.html [ Failure Pass ]
+
 crbug.com/701445 external/wpt/dom/events/EventListener-invoke-legacy.html [ Timeout Pass ]
 
 # When WebAssembly is exposed in V8 (soon), this test has the wrong number of expected Object.getOwnPropertyNames() for global object.
@@ -2946,6 +2945,9 @@
 # module script lacks XHTML support
 crbug.com/717643 external/wpt/html/semantics/scripting-1/the-script-element/module/module-in-xhtml.xhtml [ Failure ]
 
+# Skia rebaseline
+skbug.com/6931 [ Linux ] fast/text/sub-pixel/text-scaling-pixel.html [ NeedsManualRebaseline ]
+
 # Geolocation tests
 crbug.com/745079 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
 
@@ -2986,6 +2988,9 @@
 crbug.com/708499 [ Win7 Mac10.11 Retina Debug ] virtual/wheelscrolllatching/fast/compositor-wheel-scroll-latching/touchpad-scroll-impl-to-main.html [ Failure Pass ]
 crbug.com/752845 [ Win ] inspector/sha1.html [ Pass Crash ]
 
+# Sheriff failure 2017-08-11
+crbug.com/754657 http/tests/media/media-source/mediasource-duration.html [ Pass Failure ]
+
 # Ganesh dither changes
 crbug.com/753462 virtual/gpu/fast/canvas/canvas-text-alignment.html [ NeedsManualRebaseline ]
 crbug.com/753462 virtual/gpu/fast/canvas/fillrect_gradient.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png
index 5cf728d..5fa2b0b 100644
--- a/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png
+++ b/third_party/WebKit/LayoutTests/compositing/overflow/border-radius-styles-with-composited-child-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed01-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed01-expected.png
index d0e1c1d..580dfdb 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed01-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed01-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed02-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed02-expected.png
index 197931b..fdd20cf 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed02-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed02-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed03-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed03-expected.png
index 93ad8819..4c35b3b 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed03-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed03-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed04-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed04-expected.png
index 6801ab8..e90bb24 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed04-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed04-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed05-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed05-expected.png
index d29e737..a8c99b6 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed05-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed05-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed06-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed06-expected.png
index 3f7e6d1..d2bdb27 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed06-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDashed06-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted01-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted01-expected.png
index 803dd07..5fef672 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted01-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted01-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted02-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted02-expected.png
index 5acb1d6..7a5509a 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted02-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted02-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted03-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted03-expected.png
index e9a9b90..f185080 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted03-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted03-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted04-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted04-expected.png
index ed9ed19..167098e 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted04-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted04-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted06-expected.png b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted06-expected.png
index 6d1964a..f4d0513 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted06-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/borderRadiusDotted06-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/dotted-border-ajoining-thick-expected.png b/third_party/WebKit/LayoutTests/fast/borders/dotted-border-ajoining-thick-expected.png
index 4f9ba4f..f82a02c 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/dotted-border-ajoining-thick-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/dotted-border-ajoining-thick-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
index 82e2f0c..6822f5f 100644
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/text-decoration-skip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch-expected.txt b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch-expected.txt
new file mode 100644
index 0000000..a1fc9e76
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch-expected.txt
@@ -0,0 +1,28 @@
+CONSOLE ERROR: line 9: This test relies on dumping data via `window.internals`.
+CONSOLE DEBUG: line 13: Preconnect triggered for http://1.should.preconnect.test/
+CONSOLE DEBUG: line 15: Preconnect triggered for http://2.should.preconnect.test/
+CONSOLE DEBUG: line 20: DNS prefetch triggered for 1.should.dns-prefetch.test
+CONSOLE DEBUG: line 22: DNS prefetch triggered for 2.should.dns-prefetch.test
+This is a testharness.js-based test.
+PASS Prefetch: /resources/square.png?1 
+PASS Prefetch: /resources/squ\nare.png?2 
+PASS Prefetch: /resources/squ\tare.png?3 
+PASS Prefetch: /resources/squ\rare.png?4 
+PASS Prefetch: /resources/square.png?img=<&amp;5 
+PASS Prefetch: /resources/square.png?img=&lt;&amp;6 
+PASS Prefetch: /resources/square.png?img=%3C&amp;7 
+PASS Prefetch: /resources/squ\nare.png?img=%3C&amp;8 
+PASS Prefetch: /resources/squ\rare.png?img=%3C&amp;9 
+PASS Prefetch: /resources/squ\tare.png?img=%3C&amp;10 
+PASS Prefetch: /resources/square.png?img=&#10;&amp;11 
+PASS Prefetch: /resources/squ\nare.png?img=&#10;&amp;12 
+PASS Prefetch: /resources/squ\rare.png?img=&#10;&amp;13 
+PASS Prefetch: /resources/squ\tare.png?img=&#10;&amp;14 
+PASS Prefetch: /resources/squ\nare.png?block=< 
+PASS Prefetch: /resources/squ\rare.png?block=< 
+PASS Prefetch: /resources/squ\tare.png?block=< 
+PASS Prefetch: /resources/square.png?<\n=block 
+PASS Prefetch: /resources/square.png?<\r=block 
+PASS Prefetch: /resources/square.png?<\t=block 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch.html b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch.html
new file mode 100644
index 0000000..53e2d1b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/dangling-markup/link-prefetch.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  if (window.internals) {
+    internals.settings.setLogDnsPrefetchAndPreconnect(true);
+  }
+  console.error("This test relies on dumping data via `window.internals`.");
+</script>
+
+<!-- PRECONNECT -->
+<link rel="preconnect" href="//1.should.preconnect.test">
+<link rel="preconnect" href="//2.should.preco
+nnect.test">
+<link rel="preconnect" href="//3.should.not.preco
+nnect.test<">
+
+<!-- DNS-PREFETCH -->
+<link rel="dns-prefetch" href="//1.should.dns-prefetch.test">
+<link rel="dns-prefetch" href="//2.should.dns-
+prefetch.test">
+<link rel="dns-prefetch" href="//3.should.not.dns-
+prefetch.test<">
+
+</head>
+<body>
+<script>
+  function readableURL(url) {
+    return url.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
+  }
+
+  var should_load = [
+    `/resources/square.png?1`,
+    `/resources/squ\nare.png?2`,
+    `/resources/squ\tare.png?3`,
+    `/resources/squ\rare.png?4`,
+    `/resources/square.png?img=<&amp;5`,
+    `/resources/square.png?img=&lt;&amp;6`,
+    `/resources/square.png?img=%3C&amp;7`,
+    `/resources/squ\nare.png?img=%3C&amp;8`,
+    `/resources/squ\rare.png?img=%3C&amp;9`,
+    `/resources/squ\tare.png?img=%3C&amp;10`,
+    `/resources/square.png?img=&#10;&amp;11`,
+    `/resources/squ\nare.png?img=&#10;&amp;12`,
+    `/resources/squ\rare.png?img=&#10;&amp;13`,
+    `/resources/squ\tare.png?img=&#10;&amp;14`,
+  ];
+  should_load.forEach(url => async_test(t => {
+    var link = document.createElement('link');
+    link.rel = "prefetch";
+    link.href = url;
+    link.onload = t.step_func_done();
+    link.onerror = t.unreached_func("Prefetch should not fail.");
+    document.body.appendChild(link);
+  }, "Prefetch: " + readableURL(url)));
+
+  var should_block = [
+    `/resources/squ\nare.png?block=<`,
+    `/resources/squ\rare.png?block=<`,
+    `/resources/squ\tare.png?block=<`,
+    `/resources/square.png?<\n=block`,
+    `/resources/square.png?<\r=block`,
+    `/resources/square.png?<\t=block`,
+  ];
+  should_block.forEach(url => async_test(t => {
+    var link = document.createElement('link');
+    link.rel = "prefetch";
+    link.href = url;
+    link.onload = t.unreached_func("Prefetch should fail.");
+    document.body.appendChild(link);
+
+    // We verify above that `load` doesn't fire, but `error` doesn't fire
+    // either. Ugh. Timeout after a bit, and check the resourcetiming entries.
+    setTimeout(t.step_func_done(_ => {
+      assert_equals(performance.getEntriesByName(url).length, 0);
+    }), 1000);
+  }, "Prefetch: " + readableURL(url)));
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/borderRadiusAllStylesAllCorners-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/borderRadiusAllStylesAllCorners-expected.png
index 2270d33..8d89e9d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/borderRadiusAllStylesAllCorners-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/borderRadiusAllStylesAllCorners-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-expected.png
index 41d451c..b7733b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-subpixel-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-subpixel-expected.png
index 75556d1..58dfb58 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-subpixel-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/box-shadow/inset-subpixel-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index ca8d82e..3c90c3f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png b/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
index 195cb05..e033448 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png b/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
index d167eb2..bd90da2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index cd663f9..fcbc538 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png
index add80dc..b0df1b0b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/borderRadiusAllStylesAllCorners-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png
index b807e53..30b359a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-subpixel-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-subpixel-expected.png
index b66e322a..e458c4f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-subpixel-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/box-shadow/inset-subpixel-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index ae63514..102d01a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png b/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
index dade1ad..12a32fa 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png b/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
index 7f63e2fd..1c33e38 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/borderRadiusAllStylesAllCorners-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/borderRadiusAllStylesAllCorners-expected.png
index 3e6d68a..8e076b8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/borderRadiusAllStylesAllCorners-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/borderRadiusAllStylesAllCorners-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-expected.png
index 9f9e6f2..83bdd2e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-subpixel-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-subpixel-expected.png
index 5f65b77..9549542 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-subpixel-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/box-shadow/inset-subpixel-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
index 29477d1..6c929e0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png b/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
index 9b37d8b..ffd46e6 100644
--- a/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png b/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
index 14572c8..f2c52f3 100644
--- a/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/ietestcenter/css3/bordersbackgrounds/border-radius-style-002-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/custom/massive-coordinates-expected.png b/third_party/WebKit/LayoutTests/svg/custom/massive-coordinates-expected.png
index b5daa85..9bd165c 100644
--- a/third_party/WebKit/LayoutTests/svg/custom/massive-coordinates-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/custom/massive-coordinates-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
index aadd637f..de8e4d6 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -626,8 +626,8 @@
 }
 
 DEFINE_TRACE_WRAPPERS(ContainerNode) {
-  visitor->TraceWrappersWithManualWriteBarrier(first_child_);
-  visitor->TraceWrappersWithManualWriteBarrier(last_child_);
+  visitor->TraceWrappers(first_child_);
+  visitor->TraceWrappers(last_child_);
   Node::TraceWrappers(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.h b/third_party/WebKit/Source/core/dom/ContainerNode.h
index d2c3c67..e3a3c23 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.h
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.h
@@ -30,6 +30,7 @@
 #include "core/dom/Node.h"
 #include "core/html/CollectionType.h"
 #include "platform/bindings/ScriptWrappableVisitor.h"
+#include "platform/bindings/TraceWrapperMember.h"
 #include "platform/wtf/Vector.h"
 #include "public/platform/WebFocusType.h"
 
@@ -348,11 +349,9 @@
 
   void SetFirstChild(Node* child) {
     first_child_ = child;
-    ScriptWrappableVisitor::WriteBarrier(first_child_);
   }
   void SetLastChild(Node* child) {
     last_child_ = child;
-    ScriptWrappableVisitor::WriteBarrier(last_child_);
   }
 
   // Utility functions for NodeListsNodeData API.
@@ -426,8 +425,8 @@
   bool GetUpperLeftCorner(FloatPoint&) const;
   bool GetLowerRightCorner(FloatPoint&) const;
 
-  Member<Node> first_child_;
-  Member<Node> last_child_;
+  TraceWrapperMember<Node> first_child_;
+  TraceWrapperMember<Node> last_child_;
 };
 
 #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 64dcd0b..8143f94 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -3084,14 +3084,14 @@
   return EnsureElementRareData().EnsureIntersectionObserverData();
 }
 
-HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>*
+HeapHashMap<TraceWrapperMember<ResizeObserver>, Member<ResizeObservation>>*
 Element::ResizeObserverData() const {
   if (HasRareData())
     return GetElementRareData()->ResizeObserverData();
   return nullptr;
 }
 
-HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>&
+HeapHashMap<TraceWrapperMember<ResizeObserver>, Member<ResizeObservation>>&
 Element::EnsureResizeObserverData() {
   return EnsureElementRareData().EnsureResizeObserverData();
 }
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 0560077..15a7807 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -36,6 +36,8 @@
 #include "core/dom/ElementData.h"
 #include "core/dom/SpaceSplitString.h"
 #include "core/dom/WhitespaceAttacher.h"
+#include "core/resize_observer/ResizeObserver.h"
+#include "platform/bindings/TraceWrapperMember.h"
 #include "platform/heap/Handle.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "public/platform/WebFocusType.h"
@@ -65,7 +67,6 @@
 class PseudoElement;
 class PseudoStyleRequest;
 class ResizeObservation;
-class ResizeObserver;
 class ScrollIntoViewOptions;
 class ScrollIntoViewOptionsOrBoolean;
 class ScrollState;
@@ -121,7 +122,7 @@
   Member<InputDeviceCapabilities> source_capabilities = nullptr;
 };
 
-typedef HeapVector<Member<Attr>> AttrNodeList;
+typedef HeapVector<TraceWrapperMember<Attr>> AttrNodeList;
 
 class CORE_EXPORT Element : public ContainerNode {
   DEFINE_WRAPPERTYPEINFO();
@@ -788,9 +789,9 @@
   ElementIntersectionObserverData* IntersectionObserverData() const;
   ElementIntersectionObserverData& EnsureIntersectionObserverData();
 
-  HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>*
+  HeapHashMap<TraceWrapperMember<ResizeObserver>, Member<ResizeObservation>>*
   ResizeObserverData() const;
-  HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>&
+  HeapHashMap<TraceWrapperMember<ResizeObserver>, Member<ResizeObservation>>&
   EnsureResizeObserverData();
   void SetNeedsResizeObserverUpdate();
 
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.cpp b/third_party/WebKit/Source/core/dom/ElementRareData.cpp
index eab7cbc..5d4d139 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.cpp
@@ -67,8 +67,8 @@
 ElementRareData::ResizeObserverDataMap&
 ElementRareData::EnsureResizeObserverData() {
   if (!resize_observer_data_)
-    resize_observer_data_ =
-        new HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>();
+    resize_observer_data_ = new HeapHashMap<TraceWrapperMember<ResizeObserver>,
+                                            Member<ResizeObservation>>();
   return *resize_observer_data_;
 }
 
@@ -93,18 +93,18 @@
 DEFINE_TRACE_WRAPPERS_AFTER_DISPATCH(ElementRareData) {
   if (attr_node_list_.Get()) {
     for (auto& attr : *attr_node_list_) {
-      visitor->TraceWrappersWithManualWriteBarrier(attr);
+      visitor->TraceWrappers(attr);
     }
   }
-  visitor->TraceWrappersWithManualWriteBarrier(shadow_);
-  visitor->TraceWrappersWithManualWriteBarrier(attribute_map_);
-  visitor->TraceWrappersWithManualWriteBarrier(dataset_);
-  visitor->TraceWrappersWithManualWriteBarrier(class_list_);
-  visitor->TraceWrappersWithManualWriteBarrier(accessible_node_);
-  visitor->TraceWrappersWithManualWriteBarrier(intersection_observer_data_);
+  visitor->TraceWrappers(dataset_);
+  visitor->TraceWrappers(shadow_);
+  visitor->TraceWrappers(class_list_);
+  visitor->TraceWrappers(attribute_map_);
+  visitor->TraceWrappers(accessible_node_);
+  visitor->TraceWrappers(intersection_observer_data_);
   if (resize_observer_data_) {
     for (auto& resize_observer : resize_observer_data_->Keys()) {
-      visitor->TraceWrappersWithManualWriteBarrier(resize_observer);
+      visitor->TraceWrappers(resize_observer);
     }
   }
   NodeRareData::TraceWrappersAfterDispatch(visitor);
diff --git a/third_party/WebKit/Source/core/dom/ElementRareData.h b/third_party/WebKit/Source/core/dom/ElementRareData.h
index ee6a56dd..eb2571c 100644
--- a/third_party/WebKit/Source/core/dom/ElementRareData.h
+++ b/third_party/WebKit/Source/core/dom/ElementRareData.h
@@ -38,6 +38,7 @@
 #include "core/html/custom/V0CustomElementDefinition.h"
 #include "core/intersection_observer/ElementIntersectionObserverData.h"
 #include "platform/bindings/ScriptWrappableVisitor.h"
+#include "platform/bindings/TraceWrapperMember.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/HashSet.h"
 
@@ -77,7 +78,6 @@
   ElementShadow& EnsureShadow() {
     if (!shadow_) {
       shadow_ = ElementShadow::Create();
-      ScriptWrappableVisitor::WriteBarrier(shadow_);
     }
     return *shadow_;
   }
@@ -85,7 +85,6 @@
   NamedNodeMap* AttributeMap() const { return attribute_map_.Get(); }
   void SetAttributeMap(NamedNodeMap* attribute_map) {
     attribute_map_ = attribute_map;
-    ScriptWrappableVisitor::WriteBarrier(attribute_map_);
   }
 
   ComputedStyle* GetComputedStyle() const { return computed_style_.Get(); }
@@ -97,13 +96,11 @@
   DOMTokenList* GetClassList() const { return class_list_.Get(); }
   void SetClassList(DOMTokenList* class_list) {
     class_list_ = class_list;
-    ScriptWrappableVisitor::WriteBarrier(class_list_);
   }
 
   DatasetDOMStringMap* Dataset() const { return dataset_.Get(); }
   void SetDataset(DatasetDOMStringMap* dataset) {
     dataset_ = dataset;
-    ScriptWrappableVisitor::WriteBarrier(dataset_);
   }
 
   ScrollOffset SavedLayerScrollOffset() const {
@@ -141,7 +138,6 @@
   AccessibleNode* EnsureAccessibleNode(Element* owner_element) {
     if (!accessible_node_) {
       accessible_node_ = new AccessibleNode(owner_element);
-      ScriptWrappableVisitor::WriteBarrier(accessible_node_);
     }
     return accessible_node_;
   }
@@ -151,7 +147,6 @@
   void RemoveAttrNodeList() { attr_node_list_.Clear(); }
   void AddAttr(Attr* attr) {
     EnsureAttrNodeList().push_back(attr);
-    ScriptWrappableVisitor::WriteBarrier(attr);
   }
 
   ElementIntersectionObserverData* IntersectionObserverData() const {
@@ -160,13 +155,12 @@
   ElementIntersectionObserverData& EnsureIntersectionObserverData() {
     if (!intersection_observer_data_) {
       intersection_observer_data_ = new ElementIntersectionObserverData();
-      ScriptWrappableVisitor::WriteBarrier(intersection_observer_data_);
     }
     return *intersection_observer_data_;
   }
 
-  using ResizeObserverDataMap =
-      HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>;
+  using ResizeObserverDataMap = HeapHashMap<TraceWrapperMember<ResizeObserver>,
+                                            Member<ResizeObservation>>;
 
   ResizeObserverDataMap* ResizeObserverData() const {
     return resize_observer_data_;
@@ -183,16 +177,17 @@
   ScrollOffset saved_layer_scroll_offset_;
   AtomicString nonce_;
 
-  Member<DatasetDOMStringMap> dataset_;
-  Member<ElementShadow> shadow_;
-  Member<DOMTokenList> class_list_;
-  Member<NamedNodeMap> attribute_map_;
+  TraceWrapperMember<DatasetDOMStringMap> dataset_;
+  TraceWrapperMember<ElementShadow> shadow_;
+  TraceWrapperMember<DOMTokenList> class_list_;
+  TraceWrapperMember<NamedNodeMap> attribute_map_;
   Member<AttrNodeList> attr_node_list_;
   Member<InlineCSSStyleDeclaration> cssom_wrapper_;
   Member<InlineStylePropertyMap> cssom_map_wrapper_;
 
   Member<ElementAnimations> element_animations_;
-  Member<ElementIntersectionObserverData> intersection_observer_data_;
+  TraceWrapperMember<ElementIntersectionObserverData>
+      intersection_observer_data_;
   Member<ResizeObserverDataMap> resize_observer_data_;
 
   RefPtr<ComputedStyle> computed_style_;
@@ -202,7 +197,7 @@
 
   Member<PseudoElementData> pseudo_element_data_;
 
-  Member<AccessibleNode> accessible_node_;
+  TraceWrapperMember<AccessibleNode> accessible_node_;
 
   explicit ElementRareData(NodeRenderingData*);
 };
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
index 716e69c..88be155 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.cpp
@@ -364,7 +364,7 @@
 }
 
 DEFINE_TRACE_WRAPPERS(ShadowRoot) {
-  visitor->TraceWrappersWithManualWriteBarrier(style_sheet_list_);
+  visitor->TraceWrappers(style_sheet_list_);
   DocumentFragment::TraceWrappers(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ShadowRoot.h b/third_party/WebKit/Source/core/dom/ShadowRoot.h
index d70d3e5..6acd488 100644
--- a/third_party/WebKit/Source/core/dom/ShadowRoot.h
+++ b/third_party/WebKit/Source/core/dom/ShadowRoot.h
@@ -34,6 +34,7 @@
 #include "core/dom/Element.h"
 #include "core/dom/TreeScope.h"
 #include "platform/bindings/ScriptWrappableVisitor.h"
+#include "platform/bindings/TraceWrapperMember.h"
 
 namespace blink {
 
@@ -155,7 +156,6 @@
   StyleSheetList& StyleSheets();
   void SetStyleSheets(StyleSheetList* style_sheet_list) {
     style_sheet_list_ = style_sheet_list;
-    ScriptWrappableVisitor::WriteBarrier(style_sheet_list_);
   }
 
   DECLARE_VIRTUAL_TRACE();
@@ -179,7 +179,7 @@
   void SkipRebuildLayoutTree(WhitespaceAttacher&) const;
 
   Member<ShadowRootRareDataV0> shadow_root_rare_data_v0_;
-  Member<StyleSheetList> style_sheet_list_;
+  TraceWrapperMember<StyleSheetList> style_sheet_list_;
   Member<SlotAssignment> slot_assignment_;
   unsigned child_shadow_root_count_ : 13;
   unsigned type_ : 2;
diff --git a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
index 3c60adf..13dcf41 100644
--- a/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
+++ b/third_party/WebKit/Source/core/dom/TreeScopeAdopter.cpp
@@ -33,6 +33,7 @@
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/ShadowRoot.h"
 #include "core/html/custom/CustomElement.h"
+#include "platform/bindings/TraceWrapperMember.h"
 
 namespace blink {
 
@@ -72,7 +73,8 @@
       continue;
     Element& element = ToElement(node);
 
-    if (HeapVector<Member<Attr>>* attrs = element.GetAttrNodeList()) {
+    if (HeapVector<TraceWrapperMember<Attr>>* attrs =
+            element.GetAttrNodeList()) {
       for (const auto& attr : *attrs)
         MoveTreeToNewScope(*attr);
     }
@@ -97,7 +99,8 @@
       continue;
     Element& element = ToElement(node);
 
-    if (HeapVector<Member<Attr>>* attrs = element.GetAttrNodeList()) {
+    if (HeapVector<TraceWrapperMember<Attr>>* attrs =
+            element.GetAttrNodeList()) {
       for (const auto& attr : *attrs)
         MoveTreeToNewDocument(*attr, old_document, new_document);
     }
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 3e5451d..5636e6e 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -118,7 +118,10 @@
 }
 
 bool HTMLLinkElement::ShouldLoadLink() {
-  return IsInDocumentTree() || (isConnected() && rel_attribute_.IsStyleSheet());
+  const KURL& href = GetNonEmptyURLAttribute(hrefAttr);
+  return (IsInDocumentTree() ||
+          (isConnected() && rel_attribute_.IsStyleSheet())) &&
+         !href.PotentiallyDanglingMarkup();
 }
 
 bool HTMLLinkElement::LoadLink(const String& type,
@@ -136,6 +139,7 @@
 LinkResource* HTMLLinkElement::LinkResourceToProcess() {
   if (!ShouldLoadLink()) {
     DCHECK(!GetLinkStyle() || !GetLinkStyle()->HasSheet());
+    // TODO(yoav): Ideally, the element's error event would be fired here.
     return nullptr;
   }
 
@@ -193,8 +197,7 @@
   if (!insertion_point->isConnected())
     return kInsertionDone;
   DCHECK(isConnected());
-  if (!ShouldLoadLink()) {
-    DCHECK(IsInShadowTree());
+  if (!ShouldLoadLink() && IsInShadowTree()) {
     String message = "HTML element <link> is ignored in shadow tree.";
     GetDocument().AddConsoleMessage(ConsoleMessage::Create(
         kJSMessageSource, kWarningMessageLevel, message));
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index d0de0b3..f4f0548 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -339,7 +339,7 @@
         String("<link rel=preload> has an unsupported `type` value")));
     return nullptr;
   }
-  ResourceRequest resource_request(document.CompleteURL(href));
+  ResourceRequest resource_request(href);
   resource_request.SetRequestContext(ResourceFetcher::DetermineRequestContext(
       resource_type.value(), ResourceFetcher::kImageNotImageSet, false));
 
@@ -376,7 +376,7 @@
   if (rel_attribute.IsLinkPrefetch() && href.IsValid() && document.GetFrame()) {
     UseCounter::Count(document, WebFeature::kLinkRelPrefetch);
 
-    ResourceRequest resource_request(document.CompleteURL(href));
+    ResourceRequest resource_request(href);
     if (referrer_policy != kReferrerPolicyDefault) {
       resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
           referrer_policy, href, document.OutgoingReferrer()));
diff --git a/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp b/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
index 3965f9a..e37ad43 100644
--- a/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxBorderPainter.cpp
@@ -1062,39 +1062,10 @@
   graphics_context.SetStrokeStyle(
       border_style == EBorderStyle::kDashed ? kDashedStroke : kDottedStroke);
 
-  // TODO(schenney): This code for setting up the dash effect is trying to
-  // do the same thing as StrokeData::setupPaintDashPathEffect and should be
-  // refactored to re-use that code. It would require
-  // GraphicsContext::strokePath to take a length parameter.
-  float dash_length = border_thickness;
-  float gap_length = dash_length;
-  if (border_style == EBorderStyle::kDashed) {
-    dash_length *= StrokeData::DashLengthRatio(border_thickness);
-    gap_length *= StrokeData::DashGapRatio(border_thickness);
-  }
-  float path_length = centerline_path.length();
-  // Don't try to show dashes if we have less than 2 dashes + 2 gaps.
-  // TODO(schenney): should do this test per side.
-  if (path_length >= 2 * dash_length + gap_length) {
-    float gap = gap_length;
-    if (border_style == EBorderStyle::kDashed)
-      gap = StrokeData::SelectBestDashGap(path_length, dash_length, gap_length);
-    DashArray line_dash;
-    line_dash.push_back(dash_length);
-    line_dash.push_back(gap);
-    graphics_context.SetLineDash(line_dash, dash_length);
-  } else if (path_length > dash_length) {
-    // Exactly 2 dashes proportionally sized
-    float multiplier = path_length / (2 * dash_length + gap_length);
-    DashArray line_dash;
-    line_dash.push_back(dash_length * multiplier);
-    line_dash.push_back(gap_length * multiplier);
-    graphics_context.SetLineDash(line_dash, 0);
-  }  // else don't dash at all
-
   // TODO(schenney): stroking the border path causes issues with tight corners:
   // https://bugs.chromium.org/p/chromium/issues/detail?id=344234
-  graphics_context.StrokePath(centerline_path);
+  graphics_context.StrokePath(centerline_path, centerline_path.length(),
+                              border_thickness);
 }
 
 void BoxBorderPainter::DrawWideDottedBoxSideFromPath(
@@ -1103,37 +1074,12 @@
     float border_thickness) const {
   graphics_context.SetStrokeThickness(border_thickness);
   graphics_context.SetStrokeStyle(kDottedStroke);
-
-  // TODO(schenney): This code for setting up the dash effect is largely
-  // duplicated from StrokeData::setupPaintDashPathEffect and both this code
-  // and the method above should be refactored to re-use that code. It would
-  // require GraphicsContext::strokePath to take a length parameter.
   graphics_context.SetLineCap(kRoundCap);
 
-  // Adjust the width to get equal dot spacing as much as possible.
-  float per_dot_length = border_thickness * 2;
-  float path_length = border_path.length();
-
-  if (path_length < per_dot_length) {
-    // Not enoguh space for 2 dots. Just draw 1 by giving a gap that is
-    // bigger than the length.
-    DashArray line_dash;
-    line_dash.push_back(0);
-    line_dash.push_back(per_dot_length);
-    graphics_context.SetLineDash(line_dash, 0);
-  } else {
-    float gap = StrokeData::SelectBestDashGap(path_length, border_thickness,
-                                              border_thickness);
-    static const float kEpsilon = 1.0e-2f;
-    DashArray line_dash;
-    line_dash.push_back(0);
-    line_dash.push_back(gap + border_thickness - kEpsilon);
-    graphics_context.SetLineDash(line_dash, 0);
-  }
-
   // TODO(schenney): stroking the border path causes issues with tight corners:
   // https://bugs.webkit.org/show_bug.cgi?id=58711
-  graphics_context.StrokePath(border_path);
+  graphics_context.StrokePath(border_path, border_path.length(),
+                              border_thickness);
 }
 
 void BoxBorderPainter::DrawDoubleBoxSideFromPath(
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
index 80b8193..028ced2 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
@@ -270,10 +270,13 @@
     settings.setHeight(platform_settings.height);
   if (platform_settings.HasAspectRatio())
     settings.setAspectRatio(platform_settings.aspect_ratio);
-  if (RuntimeEnabledFeatures::MediaCaptureDepthEnabled() &&
+  if (RuntimeEnabledFeatures::MediaCaptureDepthVideoKindEnabled() &&
       component_->Source()->GetType() == MediaStreamSource::kTypeVideo) {
     if (platform_settings.HasVideoKind())
       settings.setVideoKind(platform_settings.video_kind);
+  }
+  if (RuntimeEnabledFeatures::MediaCaptureDepthEnabled() &&
+      component_->Source()->GetType() == MediaStreamSource::kTypeVideo) {
     if (platform_settings.HasDepthNear())
       settings.setDepthNear(platform_settings.depth_near);
     if (platform_settings.HasDepthFar())
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaTrackConstraintSet.idl b/third_party/WebKit/Source/modules/mediastream/MediaTrackConstraintSet.idl
index f02e0c0..6b3bc20 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaTrackConstraintSet.idl
+++ b/third_party/WebKit/Source/modules/mediastream/MediaTrackConstraintSet.idl
@@ -29,7 +29,7 @@
     // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar,
     // focalLengthX and focalLengthY attributes should be declared as partial
     // dictionary but IDL parser can't support it yet. http://crbug.com/579896.
-    [RuntimeEnabled=MediaCaptureDepth] ConstrainDOMString videoKind;
+    [RuntimeEnabled=MediaCaptureDepthVideoKind] ConstrainDOMString videoKind;
     [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble depthNear;
     [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble depthFar;
     [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble focalLengthX;
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaTrackSettings.idl b/third_party/WebKit/Source/modules/mediastream/MediaTrackSettings.idl
index ac779fe..9633754 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaTrackSettings.idl
+++ b/third_party/WebKit/Source/modules/mediastream/MediaTrackSettings.idl
@@ -26,7 +26,7 @@
     // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar,
     // focalLengthX and focalLengthY attributes should be declared as partial
     // dictionary but IDL parser can't support it yet. http://crbug.com/579896.
-    [RuntimeEnabled=MediaCaptureDepth] DOMString videoKind;
+    [RuntimeEnabled=MediaCaptureDepthVideoKind] DOMString videoKind;
     [RuntimeEnabled=MediaCaptureDepth] double depthNear;
     [RuntimeEnabled=MediaCaptureDepth] double depthFar;
     [RuntimeEnabled=MediaCaptureDepth] double focalLengthX;
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl b/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
index 76b7b75..a08d618 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
+++ b/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
@@ -27,7 +27,7 @@
     // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar,
     // focalLengthX and focalLengthY attributes should be declared as partial
     // dictionary but IDL parser can't support it yet. http://crbug.com/579896.
-    [RuntimeEnabled=MediaCaptureDepth] boolean videoKind = true;
+    [RuntimeEnabled=MediaCaptureDepthVideoKind] boolean videoKind = true;
     [RuntimeEnabled=MediaCaptureDepth] boolean depthNear = true;
     [RuntimeEnabled=MediaCaptureDepth] boolean depthFar = true;
     [RuntimeEnabled=MediaCaptureDepth] boolean focalLengthX = true;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 43d271e..a18d81a8 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -599,6 +599,10 @@
       status: "experimental",
     },
     {
+      name: "MediaCaptureDepthVideoKind",
+      status: "experimental",
+    },
+    {
       name: "MediaCaptureFromCanvas",
       status: "stable",
     },
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
index 29aeb3f..3e0958e 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
@@ -1089,11 +1089,14 @@
   DrawOval(ellipse, ImmutableState()->FillFlags());
 }
 
-void GraphicsContext::StrokePath(const Path& path_to_stroke) {
+void GraphicsContext::StrokePath(const Path& path_to_stroke,
+                                 const int length,
+                                 const int dash_thickness) {
   if (ContextDisabled() || path_to_stroke.IsEmpty())
     return;
 
-  DrawPath(path_to_stroke.GetSkPath(), ImmutableState()->StrokeFlags());
+  DrawPath(path_to_stroke.GetSkPath(),
+           ImmutableState()->StrokeFlags(length, dash_thickness));
 }
 
 void GraphicsContext::StrokeRect(const FloatRect& rect, float line_width) {
@@ -1103,7 +1106,7 @@
   PaintFlags flags(ImmutableState()->StrokeFlags());
   flags.setStrokeWidth(WebCoreFloatToSkScalar(line_width));
   // Reset the dash effect to account for the width
-  ImmutableState()->GetStrokeData().SetupPaintDashPathEffect(&flags, 0);
+  ImmutableState()->GetStrokeData().SetupPaintDashPathEffect(&flags);
   // strokerect has special rules for CSS when the rect is degenerate:
   // if width==0 && height==0, do nothing
   // if width==0 || height==0, then just draw line for the other dimension
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContext.h b/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
index 04d3678..6cd467b 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContext.h
@@ -168,7 +168,16 @@
   void DrawLine(const IntPoint&, const IntPoint&);
 
   void FillPath(const Path&);
-  void StrokePath(const Path&);
+  // The length parameter is only used when the path has a dashed or dotted
+  // stroke style, with the default dash/dot path effect. If a non-zero length
+  // is provided the number of dashes/dots on a dashed/dotted
+  // line will be adjusted to start and end that length with a dash/dot.
+  // The dash_thickness parameter is only used when drawing dashed borders,
+  // where the stroke thickness has been set for corner miters but we want the
+  // dash length set from the border width.
+  void StrokePath(const Path&,
+                  const int length = 0,
+                  const int dash_thickness = 0);
 
   void FillEllipse(const FloatRect&);
   void StrokeEllipse(const FloatRect&);
@@ -332,8 +341,13 @@
                        Edges clipped_edges = kNoEdge);
 
   const PaintFlags& FillFlags() const { return ImmutableState()->FillFlags(); }
-  const PaintFlags& StrokeFlags() const {
-    return ImmutableState()->StrokeFlags();
+  // If the length of the path to be stroked is known, pass it in for correct
+  // dash or dot placement. Border painting uses a stroke thickness determined
+  // by the corner miters. Set the dash_thickness to a non-zero number for
+  // cases where dashes should be based on a different thickness.
+  const PaintFlags& StrokeFlags(const int length = 0,
+                                const int dash_thickness = 0) const {
+    return ImmutableState()->StrokeFlags(length, dash_thickness);
   }
 
   // ---------- Transformation methods -----------------
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp
index 71851e6..19ed98d 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContextState.cpp
@@ -49,8 +49,10 @@
 }
 
 const PaintFlags& GraphicsContextState::StrokeFlags(
-    int stroked_path_length) const {
-  stroke_data_.SetupPaintDashPathEffect(&stroke_flags_, stroked_path_length);
+    const int stroked_path_length,
+    const int dash_thickness) const {
+  stroke_data_.SetupPaintDashPathEffect(&stroke_flags_, stroked_path_length,
+                                        dash_thickness);
   return stroke_flags_;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h b/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
index ac4fdac..ebbd5a3 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContextState.h
@@ -61,7 +61,8 @@
 
   // PaintFlags objects that reflect the current state. If the length of the
   // path to be stroked is known, pass it in for correct dash or dot placement.
-  const PaintFlags& StrokeFlags(int stroked_path_length = 0) const;
+  const PaintFlags& StrokeFlags(const int stroked_path_length = 0,
+                                const int dash_thickness = 0) const;
   const PaintFlags& FillFlags() const { return fill_flags_; }
 
   uint16_t SaveCount() const { return save_count_; }
diff --git a/third_party/WebKit/Source/platform/graphics/StrokeData.cpp b/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
index 81c59d9..2c909df 100644
--- a/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
+++ b/third_party/WebKit/Source/platform/graphics/StrokeData.cpp
@@ -55,50 +55,56 @@
   dash_ = SkDashPathEffect::Make(intervals.get(), count, dash_offset);
 }
 
-void StrokeData::SetupPaint(PaintFlags* flags, int length) const {
+void StrokeData::SetupPaint(PaintFlags* flags,
+                            const int length,
+                            const int dash_thickness) const {
   flags->setStyle(PaintFlags::kStroke_Style);
   flags->setStrokeWidth(SkFloatToScalar(thickness_));
   flags->setStrokeCap(line_cap_);
   flags->setStrokeJoin(line_join_);
   flags->setStrokeMiter(SkFloatToScalar(miter_limit_));
 
-  SetupPaintDashPathEffect(flags, length);
+  SetupPaintDashPathEffect(flags, length, dash_thickness);
 }
 
-void StrokeData::SetupPaintDashPathEffect(PaintFlags* flags, int length) const {
+void StrokeData::SetupPaintDashPathEffect(PaintFlags* flags,
+                                          const int length,
+                                          const int dash_thickness) const {
+  int path_length = length;
+  int dash_width = dash_thickness ? dash_thickness : thickness_;
   if (dash_) {
     flags->setPathEffect(dash_);
-  } else if (StrokeIsDashed(thickness_, style_)) {
-    float dash_length = thickness_;
+  } else if (StrokeIsDashed(dash_width, style_)) {
+    float dash_length = dash_width;
     float gap_length = dash_length;
     if (style_ == kDashedStroke) {
-      dash_length *= StrokeData::DashLengthRatio(thickness_);
-      gap_length *= StrokeData::DashGapRatio(thickness_);
+      dash_length *= StrokeData::DashLengthRatio(dash_width);
+      gap_length *= StrokeData::DashGapRatio(dash_width);
     }
     // Account for modification to effective length in
     // GraphicsContext::adjustLineToPixelBoundaries
-    length -= 2 * thickness_;
-    if (length <= dash_length) {
+    path_length -= 2 * dash_width;
+    if (path_length <= dash_length) {
       // No space for dashes
       flags->setPathEffect(0);
-    } else if (length <= 2 * dash_length + gap_length) {
+    } else if (path_length <= 2 * dash_length + gap_length) {
       // Exactly 2 dashes proportionally sized
-      float multiplier = length / (2 * dash_length + gap_length);
+      float multiplier = path_length / (2 * dash_length + gap_length);
       SkScalar intervals[2] = {dash_length * multiplier,
                                gap_length * multiplier};
       flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
     } else {
       float gap = gap_length;
       if (style_ == kDashedStroke)
-        gap = SelectBestDashGap(length, dash_length, gap_length);
+        gap = SelectBestDashGap(path_length, dash_length, gap_length);
       SkScalar intervals[2] = {dash_length, gap};
       flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
     }
   } else if (style_ == kDottedStroke) {
     flags->setStrokeCap((PaintFlags::Cap)kRoundCap);
     // Adjust the width to get equal dot spacing as much as possible.
-    float per_dot_length = thickness_ * 2;
-    if (length < per_dot_length) {
+    float per_dot_length = dash_width * 2;
+    if (path_length < per_dot_length) {
       // Not enoguh space for 2 dots. Just draw 1 by giving a gap that is
       // bigger than the length.
       SkScalar intervals[2] = {0, per_dot_length};
@@ -107,8 +113,8 @@
     }
 
     static const float kEpsilon = 1.0e-2f;
-    float gap = SelectBestDashGap(length, thickness_, thickness_);
-    SkScalar intervals[2] = {0, gap + thickness_ - kEpsilon};
+    float gap = SelectBestDashGap(path_length, dash_width, dash_width);
+    SkScalar intervals[2] = {0, gap + dash_width - kEpsilon};
     flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
   } else {
     // TODO(schenney): WavyStroke https://crbug.com/229574
diff --git a/third_party/WebKit/Source/platform/graphics/StrokeData.h b/third_party/WebKit/Source/platform/graphics/StrokeData.h
index 1a72f83..8a1dc03 100644
--- a/third_party/WebKit/Source/platform/graphics/StrokeData.h
+++ b/third_party/WebKit/Source/platform/graphics/StrokeData.h
@@ -74,13 +74,18 @@
   // Sets everything on the paint except the pattern, gradient and color.
   // If a non-zero length is provided, the number of dashes/dots on a
   // dashed/dotted line will be adjusted to start and end that length with a
-  // dash/dot.
-  void SetupPaint(PaintFlags*, int length = 0) const;
+  // dash/dot. If non-zero, dash_thickness is the thickness to use when
+  // deciding on dash sizes. Used in border painting when we stroke thick
+  // to allow for clipping at corners, but still want small dashes.
+  void SetupPaint(PaintFlags*,
+                  const int length = 0,
+                  const int dash_thickess = 0) const;
 
-  // Setup any DashPathEffect on the paint. If a non-zero length is provided,
-  // and no line dash has been set, the number of dashes/dots on a dashed/dotted
-  // line will be adjusted to start and end that length with a dash/dot.
-  void SetupPaintDashPathEffect(PaintFlags*, int) const;
+  // Setup any DashPathEffect on the paint. See SetupPaint above for parameter
+  // information.
+  void SetupPaintDashPathEffect(PaintFlags*,
+                                const int path_length = 0,
+                                const int dash_thickness = 0) const;
 
   // Determine whether a stroked line should be drawn using dashes. In practice,
   // we draw dashes when a dashed stroke is specified or when a dotted stroke
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 78abe36..12ad253 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -2124,6 +2124,11 @@
 </action>
 
 <action name="BadMessageTerminate_BPGM">
+  <obsolete>
+    Deprecated 8/2017. Replaced by the histograms
+    Stability.BadMessageTerminated.GuestView and
+    Stability.BadMessageTerminated.Extensions.
+  </obsolete>
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
 </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index aa2061b..3b98f24 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -2619,6 +2619,13 @@
   <int value="7" label="ESWMF_INVALID_DECREMENT_ACTIVITY"/>
   <int value="8" label="EFD_BAD_MESSAGE"/>
   <int value="9" label="EFD_BAD_MESSAGE_WORKER"/>
+  <int value="10" label="WVG_PARTITION_ID_NOT_UTF8"/>
+</enum>
+
+<enum name="BadMessageReasonGuestView">
+<!-- Generated from components/guest_view/browser/bad_message.h -->
+
+  <int value="0" label="GVM_EMBEDDER_FORBIDDEN_ACCESS_TO_GUEST"/>
 </enum>
 
 <enum name="BadMessageReasonNaCl">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d086ac2..375f689 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -76103,6 +76103,16 @@
   </summary>
 </histogram>
 
+<histogram name="Stability.BadMessageTerminated.GuestView"
+    enum="BadMessageReasonGuestView">
+  <owner>mcnee@chromium.org</owner>
+  <owner>nick@chromium.org</owner>
+  <summary>
+    Count of processes killed because they sent a bad IPC that couldn't be
+    properly handled. Categories are the reasons (code locations) for the kills.
+  </summary>
+</histogram>
+
 <histogram name="Stability.BadMessageTerminated.NaCl"
     enum="BadMessageReasonNaCl">
   <owner>nick@chromium.org</owner>
@@ -80942,6 +80952,14 @@
   </summary>
 </histogram>
 
+<histogram name="Tabs.NumberOfTabsOnResume" units="tabs">
+  <owner>sebmarchand@chromium.org</owner>
+  <summary>
+    The number of tabs total at resume from sleep/hibernate. This is being
+    logged on all desktop platforms.
+  </summary>
+</histogram>
+
 <histogram name="Tabs.SadTab.CrashCreated" units="tabs">
   <owner>jamescook@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/update_bad_message_reasons.py b/tools/metrics/histograms/update_bad_message_reasons.py
index 01db78f..c274f46e 100644
--- a/tools/metrics/histograms/update_bad_message_reasons.py
+++ b/tools/metrics/histograms/update_bad_message_reasons.py
@@ -21,6 +21,7 @@
   histograms = {
     'chrome/browser/bad_message.h': 'BadMessageReasonChrome',
     'content/browser/bad_message.h': 'BadMessageReasonContent',
+    'components/guest_view/browser/bad_message.h': 'BadMessageReasonGuestView',
     'components/nacl/browser/bad_message.h': 'BadMessageReasonNaCl',
     'components/password_manager/content/browser/bad_message.h':
       'BadMessageReasonPasswordManager',
diff --git a/url/url_canon_icu_alternatives_android.cc b/url/url_canon_icu_alternatives_android.cc
index bf363b9..daa0582 100644
--- a/url/url_canon_icu_alternatives_android.cc
+++ b/url/url_canon_icu_alternatives_android.cc
@@ -25,7 +25,7 @@
       base::android::ConvertUTF16ToJavaString(
           env, base::StringPiece16(src, src_len));
   ScopedJavaLocalRef<jstring> java_result =
-      android::Java_IDNStringUtil_idnToASCII(env, java_src.obj());
+      android::Java_IDNStringUtil_idnToASCII(env, java_src);
   // NULL indicates failure.
   if (java_result.is_null())
     return false;