diff --git a/DEPS b/DEPS
index 203db0e..3503c05 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': 'd45afc036484e74d528ceb3274e3df1983d81ac5',
+  'skia_revision': 'ae39d2e917c61b4c1ee7342bab965c90a14ac8c0',
   # 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': '071b1f432154ea6cd332d918fe514d55deb55194',
+  'v8_revision': '0fbabcd16a78f8654a342300d2c2c38cf9c79a46',
   # 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.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '3c58aa0bf51c64eb126be165e7478e70fbb68043',
+  'pdfium_revision': 'ef73cf5838ab3a902872d9fc57a90621cc3d7f21',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'fd3eb1dce85a8482e93658fb3fc00eb88c9c6cc0',
+  'catapult_revision': 'ff3b45d456482f2ac0282d5532a9d38fe3d031d8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -202,7 +202,7 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'f4653c1efc0a8d758195572de34ae05271453d93',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'ac8f58f6ab73fea7948f40eaf608f832964d8a58',
 
   'src/third_party/ffmpeg':
     Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '28a5cdde5c32bcf66715343c10f74e85713f7aaf',
@@ -363,7 +363,7 @@
       Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0',
 
     'src/ios/third_party/material_components_ios/src':
-      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'd15c5d7a61b2aa4d0e05ef994857999bddb85452',
+      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2f9ba14f1e13bb077c4b01c96199ca2df7b7494d',
 
     'src/ios/third_party/material_font_disk_loader_ios/src':
       Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '8e30188777b016182658fbaa0a4a020a48183224',
@@ -403,7 +403,7 @@
 
     # For Linux and Chromium OS.
     'src/third_party/cros_system_api':
-      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '6139ae00925a21b9eb8eae77d0db9399061731e0',
+      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '2a19709e6f2e52d8e8e276b63e46a0ff31020d57',
 
     # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
     'src/third_party/chromite':
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 5117a07..a1e5230 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -19,6 +19,7 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/task_scheduler/post_task.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/metrics/metrics_service.h"
 #include "components/policy/core/browser/browser_policy_connector_base.h"
@@ -94,9 +95,9 @@
 
 policy::URLBlacklistManager* CreateURLBlackListManager(
     PrefService* pref_service) {
-  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
-      pool->GetSequencedTaskRunner(pool->GetSequenceToken());
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND});
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
 
@@ -173,11 +174,10 @@
   url_request_context_getter_ = new AwURLRequestContextGetter(
       cache_path, CreateProxyConfigService(), user_pref_service_.get());
 
-  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
   scoped_refptr<base::SequencedTaskRunner> db_task_runner =
-      pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          pool->GetSequenceToken(),
-          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   visitedlink_master_.reset(
       new visitedlink::VisitedLinkMaster(this, this, false));
   visitedlink_master_->Init();
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 2041abd..58e7802 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -22,6 +22,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/i18n/rtl.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "components/crash/content/browser/crash_dump_manager_android.h"
 #include "components/crash/content/browser/crash_dump_observer_android.h"
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.cc b/android_webview/browser/aw_safe_browsing_blocking_page.cc
index 0e1b40a8..b91adb7 100644
--- a/android_webview/browser/aw_safe_browsing_blocking_page.cc
+++ b/android_webview/browser/aw_safe_browsing_blocking_page.cc
@@ -7,14 +7,14 @@
 #include "android_webview/browser/aw_safe_browsing_ui_manager.h"
 #include "components/security_interstitials/content/security_interstitial_controller_client.h"
 #include "components/security_interstitials/content/unsafe_resource.h"
-#include "components/security_interstitials/core/safe_browsing_error_ui.h"
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 
 using content::InterstitialPage;
 using content::WebContents;
-using security_interstitials::SafeBrowsingErrorUI;
+using security_interstitials::BaseSafeBrowsingErrorUI;
 using security_interstitials::SecurityInterstitialControllerClient;
 
 namespace android_webview {
@@ -25,7 +25,7 @@
     const GURL& main_frame_url,
     const UnsafeResourceList& unsafe_resources,
     std::unique_ptr<SecurityInterstitialControllerClient> controller_client,
-    const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
+    const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
     : BaseBlockingPage(ui_manager,
                        web_contents,
                        main_frame_url,
@@ -52,8 +52,8 @@
     content::NavigationEntry* entry =
         unsafe_resource.GetNavigationEntryForResource();
     const UnsafeResourceList unsafe_resources{unsafe_resource};
-    SafeBrowsingErrorUI::SBErrorDisplayOptions display_options =
-        SafeBrowsingErrorUI::SBErrorDisplayOptions(
+    BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options =
+        BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
             IsMainPageLoadBlocked(unsafe_resources),
             false,  // kSafeBrowsingExtendedReportingOptInAllowed
             false,  // is_off_the_record
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.h b/android_webview/browser/aw_safe_browsing_blocking_page.h
index 3455325..6751d59 100644
--- a/android_webview/browser/aw_safe_browsing_blocking_page.h
+++ b/android_webview/browser/aw_safe_browsing_blocking_page.h
@@ -6,7 +6,7 @@
 #define ANDROID_WEBVIEW_BROWSER_AW_SAFE_BROWSING_BLOCKING_PAGE_H_
 
 #include "components/safe_browsing/base_blocking_page.h"
-#include "components/security_interstitials/core/safe_browsing_error_ui.h"
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
 
 namespace security_interstitials {
 struct UnsafeResource;
@@ -33,7 +33,7 @@
       std::unique_ptr<
           security_interstitials::SecurityInterstitialControllerClient>
           controller_client,
-      const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
 };
 
 }  // namespace android_webview
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc b/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
index 9757941..c5dd462 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
+++ b/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
@@ -12,6 +12,7 @@
 #include "android_webview/browser/net/input_stream_reader.h"
 #include "base/format_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/stringprintf.h"
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 97d7dc4..e5efae0 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/output/compositor_frame.h"
 #include "content/public/browser/android/synchronous_compositor.h"
diff --git a/ash/autoclick/mus/autoclick_application.cc b/ash/autoclick/mus/autoclick_application.cc
index e308ce4..b9e52e4 100644
--- a/ash/autoclick/mus/autoclick_application.cc
+++ b/ash/autoclick/mus/autoclick_application.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_context.h"
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index 6d03343..a999955d 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -41,7 +41,6 @@
     "//ui/gfx/image/mojo:interfaces",
   ]
 
-  component_output_prefix = "ash_public_interfaces_internal"
   export_class_attribute = "ASH_PUBLIC_EXPORT"
   export_define = "ASH_PUBLIC_IMPLEMENTATION=1"
   export_header = "ash/public/cpp/ash_public_export.h"
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 2fd0c8d..172a0bd 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -31,6 +31,7 @@
 #include "ash/wm_window.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/window_parenting_client.h"
diff --git a/ash/touch_hud/mus/touch_hud_application.cc b/ash/touch_hud/mus/touch_hud_application.cc
index 4d026f38..59f138ad 100644
--- a/ash/touch_hud/mus/touch_hud_application.cc
+++ b/ash/touch_hud/mus/touch_hud_application.cc
@@ -8,6 +8,7 @@
 #include "ash/touch_hud/touch_hud_renderer.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_context.h"
diff --git a/base/android/java/src/org/chromium/base/ActivityState.java b/base/android/java/src/org/chromium/base/ActivityState.java
index f4e64135..b14814c1 100644
--- a/base/android/java/src/org/chromium/base/ActivityState.java
+++ b/base/android/java/src/org/chromium/base/ActivityState.java
@@ -12,39 +12,37 @@
 /**
  * A set of states that represent the last state change of an Activity.
  */
-public interface ActivityState {
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({CREATED, STARTED, RESUMED, PAUSED, STOPPED, DESTROYED})
-    public @interface ActivityStateEnum {}
-
+@Retention(RetentionPolicy.SOURCE)
+@IntDef({ActivityState.CREATED, ActivityState.STARTED, ActivityState.RESUMED, ActivityState.PAUSED,
+        ActivityState.STOPPED, ActivityState.DESTROYED})
+public @interface ActivityState {
     /**
      * Represents Activity#onCreate().
      */
-    public final int CREATED = 1;
+    int CREATED = 1;
 
     /**
      * Represents Activity#onStart().
      */
-    public final int STARTED = 2;
+    int STARTED = 2;
 
     /**
      * Represents Activity#onResume().
      */
-    public final int RESUMED = 3;
+    int RESUMED = 3;
 
     /**
      * Represents Activity#onPause().
      */
-    public final int PAUSED = 4;
+    int PAUSED = 4;
 
     /**
      * Represents Activity#onStop().
      */
-    public final int STOPPED = 5;
+    int STOPPED = 5;
 
     /**
      * Represents Activity#onDestroy().  This is also used when the state of an Activity is unknown.
      */
-    public final int DESTROYED = 6;
+    int DESTROYED = 6;
 }
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
index 0917bf6d9..1a9d13c7 100644
--- a/base/android/java/src/org/chromium/base/ApplicationStatus.java
+++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -10,7 +10,6 @@
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.os.Bundle;
 
-import org.chromium.base.ActivityState.ActivityStateEnum;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.MainDex;
@@ -30,13 +29,12 @@
 public class ApplicationStatus {
     private static class ActivityInfo {
         private int mStatus = ActivityState.DESTROYED;
-        private ObserverList<ActivityStateListener> mListeners =
-                new ObserverList<ActivityStateListener>();
+        private ObserverList<ActivityStateListener> mListeners = new ObserverList<>();
 
         /**
          * @return The current {@link ActivityState} of the activity.
          */
-        @ActivityStateEnum
+        @ActivityState
         public int getStatus() {
             return mStatus;
         }
@@ -44,7 +42,7 @@
         /**
          * @param status The new {@link ActivityState} of the activity.
          */
-        public void setStatus(@ActivityStateEnum int status) {
+        public void setStatus(@ActivityState int status) {
             mStatus = status;
         }
 
@@ -56,7 +54,7 @@
         }
     }
 
-    private static Object sCachedApplicationStateLock = new Object();
+    private static final Object sCachedApplicationStateLock = new Object();
     @ApplicationState
     private static Integer sCachedApplicationState;
 
@@ -70,21 +68,20 @@
     /**
      * A map of which observers listen to state changes from which {@link Activity}.
      */
-    private static final Map<Activity, ActivityInfo> sActivityInfo =
-            new ConcurrentHashMap<Activity, ActivityInfo>();
+    private static final Map<Activity, ActivityInfo> sActivityInfo = new ConcurrentHashMap<>();
 
     /**
      * A list of observers to be notified when any {@link Activity} has a state change.
      */
     private static final ObserverList<ActivityStateListener> sGeneralActivityStateListeners =
-            new ObserverList<ActivityStateListener>();
+            new ObserverList<>();
 
     /**
      * A list of observers to be notified when the visibility state of this {@link Application}
      * changes.  See {@link #getStateForApplication()}.
      */
     private static final ObserverList<ApplicationStateListener> sApplicationStateListeners =
-            new ObserverList<ApplicationStateListener>();
+            new ObserverList<>();
 
     /**
      * Interface to be implemented by listeners.
@@ -94,7 +91,7 @@
          * Called when the application's state changes.
          * @param newState The application state.
          */
-        public void onApplicationStateChange(@ApplicationState int newState);
+        void onApplicationStateChange(@ApplicationState int newState);
     }
 
     /**
@@ -106,7 +103,7 @@
          * @param activity The activity that had a state change.
          * @param newState New activity state.
          */
-        public void onActivityStateChange(Activity activity, @ActivityStateEnum int newState);
+        void onActivityStateChange(Activity activity, @ActivityState int newState);
     }
 
     private ApplicationStatus() {}
@@ -175,7 +172,7 @@
      * @param activity Current activity.
      * @param newState New state value.
      */
-    private static void onStateChange(Activity activity, @ActivityStateEnum int newState) {
+    private static void onStateChange(Activity activity, @ActivityState int newState) {
         if (activity == null) throw new IllegalArgumentException("null activity is not supported");
 
         if (sActivity == null
@@ -252,9 +249,9 @@
      * @return A {@link List} of all non-destroyed {@link Activity}s.
      */
     public static List<WeakReference<Activity>> getRunningActivities() {
-        List<WeakReference<Activity>> activities = new ArrayList<WeakReference<Activity>>();
+        List<WeakReference<Activity>> activities = new ArrayList<>();
         for (Activity activity : sActivityInfo.keySet()) {
-            activities.add(new WeakReference<Activity>(activity));
+            activities.add(new WeakReference<>(activity));
         }
         return activities;
     }
@@ -302,7 +299,7 @@
      * @param activity The activity whose state is to be returned.
      * @return The state of the specified activity (see {@link ActivityState}).
      */
-    @ActivityStateEnum
+    @ActivityState
     public static int getStateForActivity(Activity activity) {
         ActivityInfo info = sActivityInfo.get(activity);
         return info != null ? info.getStatus() : ActivityState.DESTROYED;
@@ -318,7 +315,7 @@
             if (sCachedApplicationState == null) {
                 sCachedApplicationState = determineApplicationState();
             }
-            return sCachedApplicationState.intValue();
+            return sCachedApplicationState;
         }
     }
 
diff --git a/base/cancelable_callback_unittest.cc b/base/cancelable_callback_unittest.cc
index 23b6c1c..e793a83 100644
--- a/base/cancelable_callback_unittest.cc
+++ b/base/cancelable_callback_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
index a39b2d3..799ddcd 100644
--- a/base/deferred_sequenced_task_runner_unittest.cc
+++ b/base/deferred_sequenced_task_runner_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/non_thread_safe.h"
diff --git a/base/files/file_path_watcher_unittest.cc b/base/files/file_path_watcher_unittest.cc
index dcc6d5f..e280bbc5 100644
--- a/base/files/file_path_watcher_unittest.cc
+++ b/base/files/file_path_watcher_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/base/task_runner_util_unittest.cc b/base/task_runner_util_unittest.cc
index 1df54362..44baad47 100644
--- a/base/task_runner_util_unittest.cc
+++ b/base/task_runner_util_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/base/test/test_io_thread.cc b/base/test/test_io_thread.cc
index ce4a8d10..c69a269 100644
--- a/base/test/test_io_thread.cc
+++ b/base/test/test_io_thread.cc
@@ -5,6 +5,7 @@
 #include "base/test/test_io_thread.h"
 
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 
 namespace base {
 
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
index 32b42896..39f192c 100644
--- a/base/threading/thread_perftest.cc
+++ b/base/threading/thread_perftest.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/condition_variable.h"
diff --git a/base/trace_event/blame_context_unittest.cc b/base/trace_event/blame_context_unittest.cc
index afce25b..bd999aa 100644
--- a/base/trace_event/blame_context_unittest.cc
+++ b/base/trace_event/blame_context_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/trace_event_analyzer.h"
 #include "base/trace_event/trace_buffer.h"
diff --git a/base/trace_event/trace_event_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
index 3ec6eab8..cf9bdb7 100644
--- a/base/trace_event/trace_event_system_stats_monitor_unittest.cc
+++ b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/trace_event/trace_event_impl.h"
 #include "build/build_config.h"
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index d25f242b..b436216 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -547,7 +547,6 @@
         logging.error('Golden images not found on device.')
 
       for failure_filename in os.listdir(os.path.join(temp_dir, 'failures')):
-
         m = RE_RENDER_IMAGE_NAME.match(failure_filename)
         if not m:
           logging.warning('Unexpected file in render test failures: %s',
@@ -555,29 +554,20 @@
           continue
 
         failure_filepath = os.path.join(temp_dir, 'failures', failure_filename)
-        failure_link = google_storage_helper.upload(
-            google_storage_helper.unique_name(
-                'failure_%s' % failure_filename, device=device),
-            failure_filepath,
-            bucket=render_tests_bucket)
+        failure_link = google_storage_helper.upload_content_addressed(
+            failure_filepath, bucket=render_tests_bucket)
 
         golden_filepath = os.path.join(temp_dir, 'goldens', failure_filename)
         if os.path.exists(golden_filepath):
-          golden_link = google_storage_helper.upload(
-              google_storage_helper.unique_name(
-                  'golden_%s' % failure_filename, device=device),
-              golden_filepath,
-              bucket=render_tests_bucket)
+          golden_link = google_storage_helper.upload_content_addressed(
+              golden_filepath, bucket=render_tests_bucket)
         else:
           golden_link = ''
 
         diff_filepath = os.path.join(temp_dir, 'diffs', failure_filename)
         if os.path.exists(diff_filepath):
-          diff_link = google_storage_helper.upload(
-              google_storage_helper.unique_name(
-                  'diff_%s' % failure_filename, device=device),
-              diff_filepath,
-              bucket=render_tests_bucket)
+          diff_link = google_storage_helper.upload_content_addressed(
+              diff_filepath, bucket=render_tests_bucket)
         else:
           diff_link = ''
 
@@ -594,8 +584,7 @@
 
           temp_html.write(processed_template_output)
           temp_html.flush()
-          html_results_link = google_storage_helper.upload(
-              google_storage_helper.unique_name('render_html', device=device),
+          html_results_link = google_storage_helper.upload_content_addressed(
               temp_html.name,
               bucket=render_tests_bucket,
               content_type='text/html')
@@ -643,4 +632,4 @@
   if not isinstance(test, list):
     test = [test]
   return any([RENDER_TEST_FEATURE_ANNOTATION in t['annotations'].get(
-              FEATURE_ANNOTATION, ()) for t in test])
+              FEATURE_ANNOTATION, {}).get('value', ()) for t in test])
diff --git a/build/android/pylib/symbols/elf_symbolizer.py b/build/android/pylib/symbols/elf_symbolizer.py
index ed3fe5c..7f256ea 100644
--- a/build/android/pylib/symbols/elf_symbolizer.py
+++ b/build/android/pylib/symbols/elf_symbolizer.py
@@ -23,6 +23,20 @@
 ADDR2LINE_RECYCLE_LIMIT = 4000
 
 
+ELF_MAGIC = '\x7f\x45\x4c\x46'
+
+
+def ContainsElfMagic(file_path):
+  if os.path.getsize(file_path) < 4:
+    return False
+  try:
+    with open(file_path, 'r') as f:
+      b = f.read(4)
+      return b == ELF_MAGIC
+  except IOError:
+    return False
+
+
 class ELFSymbolizer(object):
   """An uber-fast (multiprocessing, pipelined and asynchronous) ELF symbolizer.
 
diff --git a/build/android/pylib/utils/google_storage_helper.py b/build/android/pylib/utils/google_storage_helper.py
index 7a993a16..a913073 100644
--- a/build/android/pylib/utils/google_storage_helper.py
+++ b/build/android/pylib/utils/google_storage_helper.py
@@ -9,6 +9,7 @@
 to Google Storage directly using this module.
 """
 
+import hashlib
 import logging
 import os
 import sys
@@ -45,10 +46,7 @@
   Returns:
     Web link to item uploaded to Google Storage bucket.
   """
-  if bucket.startswith('gs://'):
-    bucket = bucket[len('gs://'):]
-  if bucket.endswith('/'):
-    bucket = bucket[:-1]
+  bucket = _format_bucket_name(bucket)
 
   gs_path = 'gs://%s/%s' % (bucket, name)
   logging.info('Uploading %s to %s', filepath, gs_path)
@@ -60,8 +58,35 @@
 
   cmd_helper.RunCmd(cmd)
 
-  url_template = _AUTHENTICATED_URL if authenticated_link else _PUBLIC_URL
-  return os.path.join(url_template % bucket, name)
+  return get_url_link(name, bucket, authenticated_link)
+
+
+def upload_content_addressed(
+    filepath, bucket, content_type=None, authenticated_link=True):
+  """Uploads data to Google Storage with filename as sha1 hash.
+
+  If file already exists in bucket with hash name, nothing is uploaded.
+  """
+  sha1 = hashlib.sha1()
+  with open(filepath, 'rb') as f:
+    sha1.update(f.read())
+  sha1_hash = sha1.hexdigest()
+  if not exists(sha1_hash, bucket):
+    upload(sha1_hash, filepath, bucket, content_type, authenticated_link)
+  return get_url_link(sha1_hash, bucket, authenticated_link)
+
+
+@decorators.NoRaiseException(default_return_value=False)
+def exists(name, bucket):
+  bucket = _format_bucket_name(bucket)
+  gs_path = 'gs://%s/%s' % (bucket, name)
+
+  cmd = [_GSUTIL_PATH, '-q', 'stat', gs_path]
+  return_code = cmd_helper.RunCmd(cmd)
+  if return_code == 0:
+    return True
+  else:
+    return False
 
 
 def unique_name(basename, suffix='', timestamp=True, device=None):
@@ -94,9 +119,14 @@
   Returns:
     Web link to item to be uploaded to Google Storage bucket
   """
+  bucket = _format_bucket_name(bucket)
+  url_template = _AUTHENTICATED_URL if authenticated_link else _PUBLIC_URL
+  return os.path.join(url_template % bucket, name)
+
+
+def _format_bucket_name(bucket):
   if bucket.startswith('gs://'):
     bucket = bucket[len('gs://'):]
   if bucket.endswith('/'):
     bucket = bucket[:-1]
-  url_template = _AUTHENTICATED_URL if authenticated_link else _PUBLIC_URL
-  return os.path.join(url_template % bucket, name)
+  return bucket
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 901259911..21593cfd 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -403,7 +403,10 @@
     # merged.  See also https://crbug.com/663886
     # `linux_use_bundled_binutils` is to avoid breaking Linux distros which may
     # still have a buggy gold.
-    if (!is_android && linux_use_bundled_binutils) {
+    # The bug only affects x86 and x64, so we can still use ICF when targeting
+    # other architectures.
+    if ((!is_android && linux_use_bundled_binutils) ||
+        !(current_cpu == "x86" || current_cpu == "x64")) {
       ldflags += [ "-Wl,--icf=all" ]
     }
   }
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index f496d69..1b8d13c 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -771,17 +771,7 @@
   if (!layer_tree_host_)
     return;
 
-  PropertyTrees* property_trees = layer_tree_host_->property_trees();
-  if (scroll_tree_index() != ScrollTree::kInvalidNodeId && scrollable())
-    property_trees->scroll_tree.SetScrollOffset(id(), scroll_offset);
-
-  if (TransformNode* transform_node =
-          property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) {
-    DCHECK_EQ(transform_tree_index(), transform_node->id);
-    transform_node->scroll_offset = CurrentScrollOffset();
-    transform_node->needs_local_transform_update = true;
-    property_trees->transform_tree.set_needs_update(true);
-  }
+  UpdateScrollOffset(scroll_offset);
 
   SetNeedsCommit();
 }
@@ -797,17 +787,7 @@
   inputs_.scroll_offset = scroll_offset;
   SetNeedsPushProperties();
 
-  PropertyTrees* property_trees = layer_tree_host_->property_trees();
-  if (scroll_tree_index() != ScrollTree::kInvalidNodeId && scrollable())
-    property_trees->scroll_tree.SetScrollOffset(id(), scroll_offset);
-
-  if (TransformNode* transform_node =
-          property_trees->transform_tree.UpdateNodeFromOwningLayerId(id())) {
-    DCHECK_EQ(transform_tree_index(), transform_node->id);
-    transform_node->scroll_offset = CurrentScrollOffset();
-    transform_node->needs_local_transform_update = true;
-    property_trees->transform_tree.set_needs_update(true);
-  }
+  UpdateScrollOffset(scroll_offset);
 
   if (!inputs_.did_scroll_callback.is_null())
     inputs_.did_scroll_callback.Run(scroll_offset);
@@ -816,6 +796,28 @@
   // "this" may have been destroyed during the process.
 }
 
+void Layer::UpdateScrollOffset(const gfx::ScrollOffset& scroll_offset) {
+  DCHECK(scrollable());
+  if (scroll_tree_index() == ScrollTree::kInvalidNodeId) {
+    // Ensure the property trees just have not been built yet but are marked for
+    // being built which will set the correct scroll offset values.
+    DCHECK(layer_tree_host_->property_trees()->needs_rebuild);
+    return;
+  }
+
+  // If a scroll node exists, it should have an associated transform node.
+  DCHECK(transform_tree_index() != TransformTree::kInvalidNodeId);
+
+  auto& property_trees = *layer_tree_host_->property_trees();
+  property_trees.scroll_tree.SetScrollOffset(id(), scroll_offset);
+  auto* transform_node =
+      property_trees.transform_tree.Node(transform_tree_index());
+  DCHECK_EQ(transform_tree_index(), transform_node->id);
+  transform_node->scroll_offset = CurrentScrollOffset();
+  transform_node->needs_local_transform_update = true;
+  property_trees.transform_tree.set_needs_update(true);
+}
+
 void Layer::SetScrollClipLayerId(int clip_layer_id) {
   DCHECK(IsPropertyChangeAllowed());
   if (inputs_.scroll_clip_layer_id == clip_layer_id)
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 80f9647..52bd295 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -502,6 +502,12 @@
   // layer should own a property tree node or not.
   void SetPropertyTreesNeedRebuild();
 
+  // Fast-path for |SetScrollOffset| and |SetScrollOffsetFromImplSide| to
+  // directly update scroll offset values in the property tree without needing a
+  // full property tree update. If property trees do not exist yet, ensures
+  // they are marked as needing to be rebuilt.
+  void UpdateScrollOffset(const gfx::ScrollOffset&);
+
   // Encapsulates all data, callbacks or interfaces received from the embedder.
   // TODO(khushalsagar): This is only valid when PropertyTrees are built
   // internally in cc. Update this for the SPv2 path where blink generates
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index f490e41..35385f0 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -437,6 +437,7 @@
 
   // Over-scroll (thumb position should clamp on the far side).
   root_layer->SetScrollOffset(gfx::ScrollOffset(85, 0));
+  layer_tree_host_->UpdateLayers();
 
   UPDATE_AND_EXTRACT_LAYER_POINTERS();
   EXPECT_EQ(gfx::Rect(56, 0, 4, 10).ToString(),
@@ -909,6 +910,7 @@
                           int expected_deleted,
                           bool use_solid_color_scrollbar) {
     std::unique_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, false));
+    scoped_refptr<Layer> root_clip_layer = Layer::Create();
     scoped_refptr<Layer> layer_tree_root = Layer::Create();
     scoped_refptr<Layer> content_layer = Layer::Create();
     scoped_refptr<Layer> scrollbar_layer;
@@ -930,6 +932,7 @@
 
     scrollbar_layer->SetIsDrawable(true);
     scrollbar_layer->SetBounds(gfx::Size(100, 100));
+    layer_tree_root->SetScrollClipLayerId(root_clip_layer->id());
     layer_tree_root->SetScrollOffset(gfx::ScrollOffset(10, 20));
     layer_tree_root->SetBounds(gfx::Size(100, 200));
     content_layer->SetBounds(gfx::Size(100, 200));
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 999be132..4a364eef 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/location.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/threading/thread_task_runner_handle.h"
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 7402ea2..320dd01 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1278,10 +1278,16 @@
 void LayerTreeHost::SetElementOpacityMutated(ElementId element_id,
                                              ElementListType list_type,
                                              float opacity) {
-  Layer* layer = LayerByElementId(element_id);
-  DCHECK(layer);
   DCHECK_GE(opacity, 0.f);
   DCHECK_LE(opacity, 1.f);
+
+  if (settings_.use_layer_lists) {
+    property_trees_.effect_tree.OnOpacityAnimated(element_id, opacity);
+    return;
+  }
+
+  Layer* layer = LayerByElementId(element_id);
+  DCHECK(layer);
   layer->OnOpacityAnimated(opacity);
 
   if (EffectNode* node =
@@ -1302,6 +1308,11 @@
     ElementId element_id,
     ElementListType list_type,
     const gfx::Transform& transform) {
+  if (settings_.use_layer_lists) {
+    property_trees_.transform_tree.OnTransformAnimated(element_id, transform);
+    return;
+  }
+
   Layer* layer = LayerByElementId(element_id);
   DCHECK(layer);
   layer->OnTransformAnimated(transform);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 42c83bf..e176e9c 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -8379,7 +8379,7 @@
   LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
   root->test_properties()->AddChild(std::move(scoped_scrolling_layer));
 
-  gfx::Size content_layer_bounds(100000, 100);
+  gfx::Size content_layer_bounds(100001, 100);
   scoped_refptr<FakeRasterSource> raster_source(
       FakeRasterSource::CreateFilled(content_layer_bounds));
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index a08d658..b76093d 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1180,20 +1180,169 @@
 
 SINGLE_THREAD_TEST_F(LayerTreeHostTestPropertyTreesChangedSync);
 
-class LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists
-    : public LayerTreeHostTest {
+// Simple base class for tests that just need to mutate the layer tree
+// host and observe results without any impl thread, multi-layer, or
+// multi-frame antics.
+class LayerTreeHostTestLayerListsTest : public LayerTreeHostTest {
  public:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->use_layer_lists = false;
-  }
+  explicit LayerTreeHostTestLayerListsTest(bool use_layer_lists)
+      : use_layer_lists_(use_layer_lists) {}
 
  protected:
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->use_layer_lists = use_layer_lists_;
+  }
+
   void SetupTree() override {
     root_ = Layer::Create();
     layer_tree_host()->SetRootLayer(root_);
     LayerTreeHostTest::SetupTree();
   }
 
+  void AfterTest() override {}
+
+  scoped_refptr<Layer> root_;
+
+ private:
+  bool use_layer_lists_;
+};
+
+class LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists
+    : public LayerTreeHostTestLayerListsTest {
+ public:
+  LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(false) {}
+
+ protected:
+  void BeginTest() override {
+    EXPECT_EQ(1.0f, root_->opacity());
+    layer_tree_host()->SetElementOpacityMutated(root_->element_id(),
+                                                ElementListType::ACTIVE, 0.3f);
+    // When not using layer lists, opacity is stored on the layer.
+    EXPECT_EQ(0.3f, root_->opacity());
+    EndTest();
+  }
+};
+
+SINGLE_THREAD_TEST_F(
+    LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists);
+
+class LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists
+    : public LayerTreeHostTestLayerListsTest {
+ public:
+  LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(true) {}
+
+ protected:
+  void BeginTest() override {
+    // Insert a dummy effect node to observe its mutation. This would
+    // normally have been created by PaintArtifactCompositor.
+    int effect_node_id =
+        layer_tree_host()->property_trees()->effect_tree.Insert(
+            EffectNode(), EffectTree::kInvalidNodeId);
+    layer_tree_host()
+        ->property_trees()
+        ->element_id_to_effect_node_index[root_->element_id()] = effect_node_id;
+
+    EXPECT_EQ(1.0f, root_->opacity());
+    EXPECT_EQ(1.0f,
+              layer_tree_host()
+                  ->property_trees()
+                  ->effect_tree.FindNodeFromElementId(root_->element_id())
+                  ->opacity);
+
+    layer_tree_host()->SetElementOpacityMutated(root_->element_id(),
+                                                ElementListType::ACTIVE, 0.3f);
+
+    // When using layer lists, we don't have to store the opacity on the layer.
+    EXPECT_EQ(1.0f, root_->opacity());
+    // The opacity should have been set directly on the effect node instead.
+    EXPECT_EQ(0.3f,
+              layer_tree_host()
+                  ->property_trees()
+                  ->effect_tree.FindNodeFromElementId(root_->element_id())
+                  ->opacity);
+    EndTest();
+  }
+};
+
+SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists);
+
+class LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists
+    : public LayerTreeHostTestLayerListsTest {
+ public:
+  LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(false) {}
+
+ protected:
+  void BeginTest() override {
+    EXPECT_EQ(gfx::Transform(), root_->transform());
+    gfx::Transform expected_transform;
+    expected_transform.Translate(42, 42);
+    layer_tree_host()->SetElementTransformMutated(
+        root_->element_id(), ElementListType::ACTIVE, expected_transform);
+    // When not using layer lists, transform is stored on the layer.
+    EXPECT_EQ(expected_transform, root_->transform());
+    EndTest();
+  }
+};
+
+SINGLE_THREAD_TEST_F(
+    LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists);
+
+class LayerTreeHostTestAnimationTransformMutatedUsingLayerLists
+    : public LayerTreeHostTestLayerListsTest {
+ public:
+  LayerTreeHostTestAnimationTransformMutatedUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(true) {}
+
+ protected:
+  void BeginTest() override {
+    // Insert a dummy transform node to observe its mutation. This would
+    // normally have been created by PaintArtifactCompositor.
+    int transform_node_id =
+        layer_tree_host()->property_trees()->transform_tree.Insert(
+            TransformNode(), TransformTree::kInvalidNodeId);
+    layer_tree_host()
+        ->property_trees()
+        ->element_id_to_transform_node_index[root_->element_id()] =
+        transform_node_id;
+
+    EXPECT_EQ(gfx::Transform(), root_->transform());
+    EXPECT_EQ(gfx::Transform(),
+              layer_tree_host()
+                  ->property_trees()
+                  ->transform_tree.FindNodeFromElementId(root_->element_id())
+                  ->local);
+
+    gfx::Transform expected_transform;
+    expected_transform.Translate(42, 42);
+    layer_tree_host()->SetElementTransformMutated(
+        root_->element_id(), ElementListType::ACTIVE, expected_transform);
+
+    // When using layer lists, we don't have to store the transform on the
+    // layer.
+    EXPECT_EQ(gfx::Transform(), root_->transform());
+    // The transform should have been set directly on the transform node
+    // instead.
+    EXPECT_EQ(expected_transform,
+              layer_tree_host()
+                  ->property_trees()
+                  ->transform_tree.FindNodeFromElementId(root_->element_id())
+                  ->local);
+    EndTest();
+  }
+};
+
+SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationTransformMutatedUsingLayerLists);
+
+class LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists
+    : public LayerTreeHostTestLayerListsTest {
+ public:
+  LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(false) {}
+
+ protected:
   void BeginTest() override {
     FilterOperations filters;
     EXPECT_EQ(FilterOperations(), root_->filters());
@@ -1205,29 +1354,17 @@
     EXPECT_EQ(filters, root_->filters());
     EndTest();
   }
-
-  void AfterTest() override {}
-
- private:
-  scoped_refptr<Layer> root_;
 };
 
 SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists);
 
 class LayerTreeHostTestAnimationFilterMutatedUsingLayerLists
-    : public LayerTreeHostTest {
+    : public LayerTreeHostTestLayerListsTest {
  public:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->use_layer_lists = true;
-  }
+  LayerTreeHostTestAnimationFilterMutatedUsingLayerLists()
+      : LayerTreeHostTestLayerListsTest(true) {}
 
  protected:
-  void SetupTree() override {
-    root_ = Layer::Create();
-    layer_tree_host()->SetRootLayer(root_);
-    LayerTreeHostTest::SetupTree();
-  }
-
   void BeginTest() override {
     // Insert a dummy effect node to observe its mutation. This would
     // normally have been created by PaintArtifactCompositor.
@@ -1260,11 +1397,6 @@
                   ->filters);
     EndTest();
   }
-
-  void AfterTest() override {}
-
- private:
-  scoped_refptr<Layer> root_;
 };
 
 SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationFilterMutatedUsingLayerLists);
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index fbedc16..350a42997 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -352,24 +352,25 @@
     return gfx::Vector2dF();
   StickyPositionNodeData* sticky_data = tree->StickyPositionData(node->id);
   const LayerStickyPositionConstraint& constraint = sticky_data->constraints;
+  auto& property_trees = *tree->property_trees();
   ScrollNode* scroll_node =
-      tree->property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor);
-  gfx::ScrollOffset scroll_offset =
-      tree->property_trees()->scroll_tree.current_scroll_offset(
-          scroll_node->owning_layer_id);
+      property_trees.scroll_tree.Node(sticky_data->scroll_ancestor);
+  TransformNode* transform_node =
+      property_trees.transform_tree.Node(scroll_node->transform_id);
+  const auto& scroll_offset = transform_node->scroll_offset;
+  DCHECK(property_trees.scroll_tree.current_scroll_offset(
+             scroll_node->owning_layer_id) == scroll_offset);
   gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y());
-  TransformNode* scroll_ancestor_transform_node =
-      tree->Node(scroll_node->transform_id);
-  if (scroll_ancestor_transform_node->scrolls) {
+  if (transform_node->scrolls) {
     // The scroll position does not include snapping which shifts the scroll
     // offset to align to a pixel boundary, we need to manually include it here.
     // In this case, snapping is caused by a scroll.
-    scroll_position -= scroll_ancestor_transform_node->snap_amount;
+    scroll_position -= transform_node->snap_amount;
   }
 
   gfx::RectF clip(
       scroll_position,
-      gfx::SizeF(tree->property_trees()->scroll_tree.scroll_clip_layer_bounds(
+      gfx::SizeF(property_trees.scroll_tree.scroll_clip_layer_bounds(
           scroll_node->id)));
   gfx::Vector2dF layer_offset(sticky_data->main_thread_offset);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryItemWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryItemWrapper.java
index acba9d9..9cda42e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryItemWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryItemWrapper.java
@@ -153,9 +153,6 @@
     /** @return How much of the download has completed, or null if there is no progress. */
     abstract Progress getDownloadProgress();
 
-    /** @return Whether the download has an unknown file size. */
-    abstract boolean isIndeterminate();
-
     /** @return String indicating the status of the download. */
     abstract String getStatusString();
 
@@ -312,11 +309,6 @@
         }
 
         @Override
-        public boolean isIndeterminate() {
-            return mItem.isIndeterminate();
-        }
-
-        @Override
         public String getStatusString() {
             return DownloadUtils.getStatusString(mItem);
         }
@@ -497,12 +489,8 @@
         @Override
         public Progress getDownloadProgress() {
             // Only completed offline page downloads are shown.
-            return new Progress(100, 100L, OfflineItemProgressUnit.PERCENTAGE);
-        }
-
-        @Override
-        public boolean isIndeterminate() {
-            return true;
+            return isComplete() ? new Progress(100, 100L, OfflineItemProgressUnit.PERCENTAGE)
+                    : Progress.createIndeterminateProgress();
         }
 
         @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
index 903ce8c..161c62d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -82,6 +82,7 @@
 import org.chromium.printing.PrintingControllerImpl;
 import org.chromium.ui.PhotoPickerListener;
 import org.chromium.ui.UiUtils;
+import org.chromium.ui.base.SelectFileDialog;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -293,6 +294,8 @@
 
                 OfflinePageUtils.clearSharedOfflineFiles(application);
 
+                SelectFileDialog.clearCapturedCameraFiles();
+
                 if (ChannelsUpdater.getInstance().shouldUpdateChannels()) {
                     initChannelsAsync();
                 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderFactory.java
similarity index 96%
rename from content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderFactory.java
rename to chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderFactory.java
index 6eda1a3..e418113 100644
--- a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderFactory.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser.installedapp;
+package org.chromium.chrome.browser.installedapp;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.content.browser.framehost.RenderFrameHostImpl;
diff --git a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java
similarity index 99%
rename from content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java
rename to chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java
index 04047a8..d2fb077 100644
--- a/content/public/android/java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser.installedapp;
+package org.chromium.chrome.browser.installedapp;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
diff --git a/content/public/android/java/src/org/chromium/content/browser/installedapp/PackageHash.java b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/PackageHash.java
similarity index 98%
rename from content/public/android/java/src/org/chromium/content/browser/installedapp/PackageHash.java
rename to chrome/android/java/src/org/chromium/chrome/browser/installedapp/PackageHash.java
index fbb4fb2..0fe78ce4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/installedapp/PackageHash.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/installedapp/PackageHash.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser.installedapp;
+package org.chromium.chrome.browser.installedapp;
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.content.browser.crypto.ByteArrayGenerator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
index ab11fff..52f0be1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
@@ -5,11 +5,13 @@
 package org.chromium.chrome.browser.mojo;
 
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.browser.installedapp.InstalledAppProviderFactory;
 import org.chromium.chrome.browser.payments.PaymentRequestFactory;
 import org.chromium.chrome.browser.webshare.ShareServiceImplementationFactory;
 import org.chromium.content_public.browser.InterfaceRegistrar;
 import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.installedapp.mojom.InstalledAppProvider;
 import org.chromium.payments.mojom.PaymentRequest;
 import org.chromium.services.service_manager.InterfaceRegistry;
 import org.chromium.webshare.mojom.ShareService;
@@ -42,6 +44,8 @@
                 InterfaceRegistry registry, final RenderFrameHost renderFrameHost) {
             registry.addInterface(
                     PaymentRequest.MANAGER, new PaymentRequestFactory(renderFrameHost));
+            registry.addInterface(
+                    InstalledAppProvider.MANAGER, new InstalledAppProviderFactory(renderFrameHost));
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
index 7ec917a..edcadd12 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
@@ -201,19 +201,12 @@
         final long start = mLeftPosition;
         // Include up to the last second of the currently selected day.
         final long end = mRightPosition;
-        final long now = mCurrentTime;
         final Context context = getContext();
 
-        NetworkStatsHistory.Entry compressedEntry =
-                mReceivedNetworkStatsHistory.getValues(start, end, now, null);
-        // Only received bytes are tracked.
-        final long compressedTotalBytes = compressedEntry.rxBytes;
+        final long compressedTotalBytes = mReceivedNetworkStatsHistory.getTotalBytes();
         mReceivedTotalPhrase = Formatter.formatFileSize(context, compressedTotalBytes);
 
-        NetworkStatsHistory.Entry originalEntry =
-                mOriginalNetworkStatsHistory.getValues(start, end, now, null);
-        // Only received bytes are tracked.
-        final long originalTotalBytes = originalEntry.rxBytes;
+        final long originalTotalBytes = mOriginalNetworkStatsHistory.getTotalBytes();
         mOriginalTotalPhrase = Formatter.formatFileSize(context, originalTotalBytes);
         mSavingsTotalPhrase =
                 Formatter.formatFileSize(context, originalTotalBytes - compressedTotalBytes);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
index 86b6ba1..7f2c39d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.WindowDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
+import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.init.AsyncInitializationActivity;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.omnibox.AutocompleteController;
@@ -242,7 +243,7 @@
         String fixedUrl = UrlFormatter.fixupUrl(url);
         Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fixedUrl));
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-        intent.setPackage(getPackageName());
+        intent.setClass(this, ChromeLauncherActivity.class);
         IntentHandler.addTrustedIntentExtras(intent);
         IntentUtils.safeStartActivity(this, intent,
                 ActivityOptionsCompat
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 6ea8491..3140ea2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -37,6 +37,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -98,6 +99,7 @@
 
     private static VrShellDelegate sInstance;
     private static VrBroadcastReceiver sVrBroadcastReceiver;
+    private static boolean sRegisteredDaydreamHook = false;
 
     private ChromeActivity mActivity;
 
@@ -126,7 +128,7 @@
     private boolean mListeningForWebVrActivate;
     private boolean mListeningForWebVrActivateBeforePause;
 
-    private static class VrBroadcastReceiver extends BroadcastReceiver {
+    private static final class VrBroadcastReceiver extends BroadcastReceiver {
         private final WeakReference<ChromeActivity> mTargetActivity;
 
         public VrBroadcastReceiver(ChromeActivity activity) {
@@ -277,7 +279,7 @@
         // Daydream is not supported on pre-N devices.
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
         if (sInstance != null) return; // Will be handled in onPause.
-        if (!activitySupportsVrBrowsing(activity)) return;
+        if (!sRegisteredDaydreamHook) return;
         VrClassesWrapper wrapper = getVrClassesWrapper();
         if (wrapper == null) return;
         VrDaydreamApi api = wrapper.createVrDaydreamApi(activity);
@@ -340,7 +342,13 @@
     }
 
     private static PendingIntent getEnterVrPendingIntent(ChromeActivity activity) {
+        if (sVrBroadcastReceiver != null) sVrBroadcastReceiver.unregister();
+        IntentFilter filter = new IntentFilter(VR_ENTRY_RESULT_ACTION);
+        sVrBroadcastReceiver = new VrBroadcastReceiver(activity);
+        activity.registerReceiver(sVrBroadcastReceiver, filter);
+
         Intent vrIntent = new Intent(VR_ENTRY_RESULT_ACTION);
+        vrIntent.setPackage(activity.getPackageName());
         return PendingIntent.getBroadcast(activity, 0, vrIntent,
                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
     }
@@ -350,18 +358,18 @@
      */
     private static void registerDaydreamIntent(
             final VrDaydreamApi daydreamApi, final ChromeActivity activity) {
-        if (sVrBroadcastReceiver != null) sVrBroadcastReceiver.unregister();
+        if (sRegisteredDaydreamHook) return;
         if (!daydreamApi.registerDaydreamIntent(getEnterVrPendingIntent(activity))) return;
-        IntentFilter filter = new IntentFilter(VR_ENTRY_RESULT_ACTION);
-        sVrBroadcastReceiver = new VrBroadcastReceiver(activity);
-        activity.registerReceiver(sVrBroadcastReceiver, filter);
+        sRegisteredDaydreamHook = true;
     }
 
     /**
      * Unregisters the Intent which registered by this context if any.
      */
     private static void unregisterDaydreamIntent(VrDaydreamApi daydreamApi) {
+        if (!sRegisteredDaydreamHook) return;
         daydreamApi.unregisterDaydreamIntent();
+        sRegisteredDaydreamHook = false;
     }
 
     /**
@@ -470,6 +478,9 @@
         // in the vrdisplayactivate handler we will exit presentation later.
         enterVr(mListeningForWebVrActivateBeforePause && !mRequestedWebVr);
 
+        // The user has successfully completed a DON flow.
+        RecordUserAction.record("VR.DON");
+
         return true;
     }
 
@@ -670,20 +681,18 @@
 
     private void pauseVr() {
         mPaused = true;
+        unregisterDaydreamIntent(mVrDaydreamApi);
         if (mVrSupportLevel == VR_NOT_AVAILABLE) return;
 
-        if (mVrSupportLevel == VR_DAYDREAM) {
-            unregisterDaydreamIntent(mVrDaydreamApi);
+        // When the active web page has a vrdisplayactivate event handler,
+        // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
+        // should be fired once DON flow finished. However, DON flow will pause our activity,
+        // which makes the active page becomes invisible. And the event fires before the active
+        // page becomes visible again after DON finished. So here we remember the value of
+        // mListeningForWebVrActivity before pause and use this value to decide if
+        // vrdisplayactivate event should be dispatched in enterVRFromIntent.
+        mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate;
 
-            // When the active web page has a vrdisplayactivate event handler,
-            // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
-            // should be fired once DON flow finished. However, DON flow will pause our activity,
-            // which makes the active page becomes invisible. And the event fires before the active
-            // page becomes visible again after DON finished. So here we remember the value of
-            // mListeningForWebVrActivity before pause and use this value to decide if
-            // vrdisplayactivate event should be dispatched in enterVRFromIntent.
-            mListeningForWebVrActivateBeforePause = mListeningForWebVrActivate;
-        }
         if (mNativeVrShellDelegate != 0) nativeOnPause(mNativeVrShellDelegate);
 
         // TODO(mthiesse): When VR Shell lives in its own activity, and integrates with Daydream
@@ -755,6 +764,10 @@
             mVrClassesWrapper.setVrModeEnabled(mActivity, false);
             mLastVrExit = SystemClock.uptimeMillis();
         }
+
+        // The user has exited VR.
+        RecordUserAction.record("VR.DOFF");
+
         restoreWindowMode();
         mVrShell.pause();
         removeVrViews();
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 5b309cbe..f448b09f 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -490,6 +490,9 @@
   "java/src/org/chromium/chrome/browser/init/InvalidStartupDialog.java",
   "java/src/org/chromium/chrome/browser/init/NativeInitializationController.java",
   "java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java",
+  "java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderFactory.java",
+  "java/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderImpl.java",
+  "java/src/org/chromium/chrome/browser/installedapp/PackageHash.java",
   "java/src/org/chromium/chrome/browser/instantapps/AuthenticatedProxyActivity.java",
   "java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java",
   "java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java",
@@ -1539,6 +1542,8 @@
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java",
+  "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java",
+  "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java",
   "javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java",
   "javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java",
@@ -1676,6 +1681,8 @@
   "junit/src/org/chromium/chrome/browser/fullscreen/BrowserStateBrowserControlsVisibilityDelegateTest.java",
   "junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelperTest.java",
   "junit/src/org/chromium/chrome/browser/init/AsyncInitTaskRunnerTest.java",
+  "junit/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderTest.java",
+  "junit/src/org/chromium/chrome/browser/installedapp/PackageHashTest.java",
   "junit/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java",
   "junit/src/org/chromium/chrome/browser/media/remote/AbstractMediaRouteControllerTest.java",
   "junit/src/org/chromium/chrome/browser/media/remote/MediaUrlResolverTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenWebContentsActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenWebContentsActivityTest.java
index d8071cc..e829c4d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenWebContentsActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/FullscreenWebContentsActivityTest.java
@@ -19,6 +19,7 @@
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -137,6 +138,7 @@
 
     @Test
     @MediumTest
+    @FlakyTest(message = "https://crbug.com/721906")
     public void testExitOnBack() throws Throwable {
         final FullscreenWebContentsActivity fullscreenActivity = enterFullscreen();
         mUiThreadTestRule.runOnUiThread(new Runnable() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
index 3bf6a88..33fee62 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
@@ -41,8 +41,8 @@
     @Feature({"Payments"})
     public void testAbortBeforePayClicked() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickNodeAndWait("abort", mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickNodeAndWait("abort", getDismissed());
         expectResultContains(new String[] {"Aborted"});
     }
 
@@ -51,9 +51,9 @@
     @Feature({"Payments"})
     public void testAbortWhileUnmaskingCard() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        clickNodeAndWait("abort", mUnableToAbort);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        clickNodeAndWait("abort", getUnableToAbort());
         expectResultContains(new String[] {"Cannot abort"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
index 7e9844c..b89923c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
@@ -42,43 +42,43 @@
     @Feature({"Payments"})
     public void testCanPayWithBasicCard() throws InterruptedException,
             ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicCard", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicCard", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
 
-        clickNodeAndWait("buyBasicCard", mReadyForInput);
+        clickNodeAndWait("buyBasicCard", getReadyForInput());
     }
 
     @MediumTest
     @Feature({"Payments"})
     public void testIgnoreCardType() throws InterruptedException,
             ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicDebit", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicDebit", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
 
-        clickNodeAndWait("buyBasicDebit", mReadyForInput);
+        clickNodeAndWait("buyBasicDebit", getReadyForInput());
     }
 
     @MediumTest
     @Feature({"Payments"})
     public void testCannotMakeActivePaymentWithBasicMasterCard() throws InterruptedException,
             ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicMasterCard", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicMasterCard", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false"});
 
-        reTriggerUIAndWait("buyBasicMasterCard", mReadyForInput);
+        reTriggerUIAndWait("buyBasicMasterCard", getReadyForInput());
     }
 
     @MediumTest
     @Feature({"Payments"})
     public void testSupportedNetworksMustMatchForCanMakePayment()
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicVisa", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicVisa", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
 
-        clickNodeAndWait("checkBasicMasterCard", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("checkBasicMasterCard", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"Not allowed to check whether can make payment"});
 
-        clickNodeAndWait("checkBasicVisa", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("checkBasicVisa", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
     }
 
@@ -86,13 +86,13 @@
     @Feature({"Payments"})
     public void testSupportedTypesMustMatchForCanMakePayment()
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicVisa", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicVisa", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
 
-        clickNodeAndWait("checkBasicDebit", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("checkBasicDebit", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"Not allowed to check whether can make payment"});
 
-        clickNodeAndWait("checkBasicVisa", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("checkBasicVisa", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
     }
 
@@ -105,13 +105,13 @@
     @Feature({"Payments"})
     public void testPayWithBasicCard()  throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickNodeAndWait("checkBasicVisa", mCanMakePaymentQueryResponded);
+        openPageAndClickNodeAndWait("checkBasicVisa", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true"});
 
-        reTriggerUIAndWait("buy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        reTriggerUIAndWait("buy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050",
                 "basic-card", "123"});
     }
@@ -125,18 +125,18 @@
     @Feature({"Payments"})
     public void testAddMasterCard()  throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInCardEditorAndWait(new String[] {"5555-5555-5555-4444", "Jane Jones"},
-                mEditorTextUpdate);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInCardEditorAndWait(
+                new String[] {"5555-5555-5555-4444", "Jane Jones"}, getEditorTextUpdate());
         setSpinnerSelectionsInCardEditorAndWait(
                 new int[] {DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS},
-                mBillingAddressChangeProcessed);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                getBillingAddressChangeProcessed());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(
                 new String[] {"5555555555554444", "12", "Jane Jones", "123", "mastercard"});
     }
@@ -150,18 +150,18 @@
     @Feature({"Payments"})
     public void testAddBasicCard()  throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInCardEditorAndWait(new String[] {"4242-4242-4242-4242", "Jane Jones"},
-                mEditorTextUpdate);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInCardEditorAndWait(
+                new String[] {"4242-4242-4242-4242", "Jane Jones"}, getEditorTextUpdate());
         setSpinnerSelectionsInCardEditorAndWait(
                 new int[] {DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS},
-                mBillingAddressChangeProcessed);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                getBillingAddressChangeProcessed());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(
                 new String[] {"4242424242424242", "12", "Jane Jones", "123", "basic-card"});
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
index 5ce7257b..70db97b9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
@@ -96,13 +96,14 @@
     @Feature({"Payments"})
     public void testNewCardBillingAddressFormat()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInCardEditorAndWait(new String[] {"5454-5454-5454-5454", "Bob"}, mEditorTextUpdate);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInCardEditorAndWait(
+                new String[] {"5454-5454-5454-5454", "Bob"}, getEditorTextUpdate());
         setSpinnerSelectionsInCardEditorAndWait(
                 new int[] {DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS},
-                mBillingAddressChangeProcessed);
+                getBillingAddressChangeProcessed());
         // The billing address suggestions should include only the name, address, city, state and
         // zip code of the profile.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -117,9 +118,9 @@
     @Feature({"Payments"})
     public void testNumberOfBillingAddressSuggestions()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // There should only be 8 suggestions, the 7 saved addresses and the option to add a new
         // address.
@@ -135,16 +136,16 @@
     public void testNumberOfBillingAddressSuggestions_AfterCancellingNewBillingAddress()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Add a payment method and add a new billing address.
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Select the "+ ADD ADDRESS" option for the billing address.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, mReadyToEdit);
+                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, getReadyToEdit());
 
         // Cancel the creation of a new billing address.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToEdit);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToEdit());
 
         // There should still only be 8 suggestions, the 7 saved addresses and the option to add a
         // new address.
@@ -158,10 +159,10 @@
     @Feature({"Payments"})
     public void testAddBillingAddressOnCardAndCancel_MaintainsPreviousSelection()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
         // Edit the only card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Jon Doe is selected as the billing address.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -169,10 +170,10 @@
 
         // Select the "+ ADD ADDRESS" option for the billing address.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, mReadyToEdit);
+                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, getReadyToEdit());
 
         // Cancel the creation of a new billing address.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToEdit);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToEdit());
 
         // Jon Doe is STILL selected as the billing address.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -187,10 +188,10 @@
     @Feature({"Payments"})
     public void testAddBillingAddressOnCardWithNoBillingAndCancel_MaintainsPreviousSelection()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
         // Edit the second card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickOnPaymentMethodSuggestionOptionAndWait(1, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickOnPaymentMethodSuggestionOptionAndWait(1, getReadyToEdit());
 
         // Now in Card Editor to add a billing address. "Select" is selected in the dropdown.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -198,10 +199,10 @@
 
         // Select the "+ ADD ADDRESS" option for the billing address.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, mReadyToEdit);
+                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, getReadyToEdit());
 
         // Cancel the creation of a new billing address.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToEdit);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToEdit());
 
         // "Select" is STILL selected as the billing address.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -216,9 +217,9 @@
     public void testBillingAddressSortedByFrecency()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Add a payment method.
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // There should be 8 suggestions, the 7 saved addresses and the option to add a new address.
         assertEquals(8, getSpinnerItemCountInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX));
@@ -243,16 +244,18 @@
     public void testBillingAddressSortedByFrecency_AddNewAddress()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Add a payment method.
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Add a new billing address.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"Seb Doe", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToEdit);
+                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {
+                "Seb Doe", "Google", "340 Main St", "Los Angeles", "CA", "90291",
+                "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToEdit());
 
         // There should be 9 suggestions, the 7 initial addresses, the newly added address and the
         // option to add a new address.
@@ -281,18 +284,19 @@
     @Feature({"Payments"})
     public void testNewShippingAddressSuggestedFirst()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Add a shipping address.
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Seb Doe", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                "CA", "90291", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Navigate to the card editor UI.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // There should be 9 suggestions, the 7 initial addresses, the newly added address and the
         // option to add a new address.
@@ -307,10 +311,10 @@
     @Feature({"Payments"})
     public void testSelectIncompleteBillingAddress_EditComplete()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
         // Edit the second card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickOnPaymentMethodSuggestionOptionAndWait(1, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickOnPaymentMethodSuggestionOptionAndWait(1, getReadyToEdit());
 
         // Now "Select" is selected in the dropdown.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -326,10 +330,12 @@
 
         // Selects the fourth billing addresss that misses recipient name brings up the address
         // editor.
-        setSpinnerSelectionsInCardEditorAndWait(new int[] {DECEMBER, NEXT_YEAR, 4}, mReadyToEdit);
+        setSpinnerSelectionsInCardEditorAndWait(
+                new int[] {DECEMBER, NEXT_YEAR, 4}, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Lisa Doh", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToEdit);
+                "CA", "90291", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToEdit());
 
         // The newly completed address must be selected and put at the top of the dropdown.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -342,10 +348,10 @@
     @Feature({"Payments"})
     public void testSelectIncompleteBillingAddress_EditCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
         // Edit the only complete card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Jon Doe is selected as the billing address.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
@@ -361,8 +367,9 @@
 
         // Selects the fifth billing addresss that misses recipient name brings up the address
         // editor.
-        setSpinnerSelectionsInCardEditorAndWait(new int[] {DECEMBER, NEXT_YEAR, 4}, mReadyToEdit);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToEdit);
+        setSpinnerSelectionsInCardEditorAndWait(
+                new int[] {DECEMBER, NEXT_YEAR, 4}, getReadyToEdit());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToEdit());
 
         // The previous selected address should be selected after canceling out from edit.
         assertTrue(getSpinnerSelectionTextInCardEditor(BILLING_ADDRESS_DROPDOWN_INDEX)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
index e5fa9dc..72e0543 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
@@ -56,10 +56,10 @@
     @Feature({"Payments"})
     public void testCanPayWithBillingNoPhone()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon NoPhone"});
     }
 
@@ -67,11 +67,11 @@
     @Feature({"Payments"})
     public void testCanSelectBillingAddressWithoutPhone()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Go edit the credit card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickOnPaymentMethodSuggestionEditIconAndWait(0, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickOnPaymentMethodSuggestionEditIconAndWait(0, getReadyToEdit());
 
         // Make sure that the currently selected address is valid and can be selected (does not
         // include error messages).
@@ -88,8 +88,8 @@
     @Feature({"Payments"})
     public void testCantSelectShippingAddressWithoutPhone()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // The first suggestion should be the address with a phone.
         assertTrue(getShippingAddressSuggestionLabel(0).contains("Rob Phone"));
@@ -105,18 +105,18 @@
     @Feature({"Payments"})
     public void testCantAddNewBillingAddressWithoutPhone()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Add a new billing address without a phone.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, mReadyToEdit);
+                new int[] {DECEMBER, NEXT_YEAR, ADD_BILLING_ADDRESS}, getReadyToEdit());
         setTextInEditorAndWait(
                 new String[] {"Seb Doe", "Google", "340 Main St", "Los Angeles", "CA", "90291", ""},
-                mEditorTextUpdate);
+                getEditorTextUpdate());
 
         // Trying to add the address without a phone number should fail.
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
index f664079..053815c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
@@ -44,17 +44,17 @@
     public void testCannotMakePayment_Abort()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Initiate a payment request.
-        triggerUIAndWait("queryShow", mReadyForInput);
+        triggerUIAndWait("queryShow", getReadyForInput());
 
         // Press the back button.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
         expectResultContains(new String[] {"Request cancelled"});
 
         // CanMakePayment was queried.
@@ -86,19 +86,20 @@
     @Feature({"Payments"})
     public void testCannotMakePayment_Complete()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait("queryShow", mReadyForInput);
+        triggerUIAndWait("queryShow", getReadyForInput());
 
         // Add a new credit card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyToEdit());
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {11, 1, 0}, mBillingAddressChangeProcessed);
-        setTextInCardEditorAndWait(new String[] {"4111111111111111", "Jon Doe"}, mEditorTextUpdate);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                new int[] {11, 1, 0}, getBillingAddressChangeProcessed());
+        setTextInCardEditorAndWait(
+                new String[] {"4111111111111111", "Jon Doe"}, getEditorTextUpdate());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Complete the transaction.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // CanMakePayment was queried.
         assertEquals(1,
@@ -133,17 +134,17 @@
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
 
         // Initiate a payment request.
-        triggerUIAndWait("queryShow", mReadyForInput);
+        triggerUIAndWait("queryShow", getReadyForInput());
 
         // Press the back button.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
         expectResultContains(new String[] {"Request cancelled"});
 
         // CanMakePayment was queried.
@@ -180,8 +181,8 @@
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
 
         // Initiate an complete a payment request.
-        triggerUIAndWait("queryShow", mReadyForInput);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait("queryShow", getReadyForInput());
+        clickAndWait(R.id.button_primary, getDismissed());
 
         // CanMakePayment was queried.
         assertEquals(1,
@@ -213,17 +214,17 @@
     public void testNoQuery_Abort()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Initiate a payment request.
-        triggerUIAndWait("noQueryShow", mReadyForInput);
+        triggerUIAndWait("noQueryShow", getReadyForInput());
 
         // Press the back button.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
         expectResultContains(new String[] {"Request cancelled"});
 
         // CanMakePayment was not queried.
@@ -252,8 +253,8 @@
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
 
         // Initiate a payment request.
-        triggerUIAndWait("noQueryShow", mReadyForInput);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait("noQueryShow", getReadyForInput());
+        clickAndWait(R.id.button_primary, getDismissed());
 
         // CanMakePayment was not queried.
         assertEquals(1,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
index 40b9056..13b70ce 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
@@ -37,7 +37,7 @@
     @Feature({"Payments"})
     public void testNoBobPayInstalled() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"false"});
     }
 
@@ -46,7 +46,7 @@
     public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"false"});
     }
 
@@ -55,7 +55,7 @@
     public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"false"});
     }
 
@@ -64,7 +64,7 @@
     public void testPayViaFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 
@@ -73,7 +73,7 @@
     public void testPayViaSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
index 6c8b204..20dc0a4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
@@ -37,7 +37,7 @@
     @Feature({"Payments"})
     public void testNoBobPayInstalled() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 
@@ -46,7 +46,7 @@
     public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 
@@ -55,7 +55,7 @@
     public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 
@@ -64,7 +64,7 @@
     public void testPayViaFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 
@@ -73,7 +73,7 @@
     public void testPayViaSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
index 2a2fd4d..8a28d2a5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
@@ -46,22 +46,22 @@
     @Feature({"Payments"})
     public void test14DigitsCreditCard()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Diners credit card.
         final View focusedChildView = getCardEditorFocusedView();
-        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 0"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 0"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '3056 9309 0259 00' is an invalid 14 digits card number.
-        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 00"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 00"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '3056 9309 0259 04' is a valid 14 digits card number.
-        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 04"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 04"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() != focusedChildView);
 
         // Request focus to card number field after auto advancing above.
@@ -71,7 +71,7 @@
                 focusedChildView.requestFocus();
             }
         });
-        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 041"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3056 9309 0259 041"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
     }
 
@@ -79,22 +79,22 @@
     @Feature({"Payments"})
     public void test15DigitsCreditCard()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // American Express credit card.
         final View focusedChildView = getCardEditorFocusedView();
-        setTextInCardEditorAndWait(new String[] {"3782 822463 1000"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3782 822463 1000"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '3782 822463 10000' is an invalid 15 digits card number.
-        setTextInCardEditorAndWait(new String[] {"3782 822463 10000"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3782 822463 10000"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '3782 822463 10005' is a valid 15 digits card number.
-        setTextInCardEditorAndWait(new String[] {"3782 822463 10005"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3782 822463 10005"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() != focusedChildView);
 
         // Request focus to card number field after auto advancing above.
@@ -104,7 +104,7 @@
                 focusedChildView.requestFocus();
             }
         });
-        setTextInCardEditorAndWait(new String[] {"3782 822463 10005 1"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"3782 822463 10005 1"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
     }
 
@@ -112,30 +112,30 @@
     @Feature({"Payments"})
     public void test16DigitsCreditCard()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // DISCOVER, JCB, MASTERCARD, MIR and VISA cards have 16 digits. Takes VISA as test input
         // which has 13 digits valid card.
         final View focusedChildView = getCardEditorFocusedView();
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 "}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 "}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '4012 8888 8888 1' is a valid 13 digits card number.
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 188"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 188"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '4012 8888 8888 1880' is an invalid 16 digits card number.
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1880"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1880"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '4012 8888 8888 1881' is a valid 16 digits card number.
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1881"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1881"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() != focusedChildView);
 
         // Request focus to card number field after auto advancing above.
@@ -145,7 +145,7 @@
                 focusedChildView.requestFocus();
             }
         });
-        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1881 1"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"4012 8888 8888 1881 1"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
     }
 
@@ -153,29 +153,29 @@
     @Feature({"Payments"})
     public void test19DigitsCreditCard()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // UNIONPAY credit card.
         final View focusedChildView = getCardEditorFocusedView();
-        setTextInCardEditorAndWait(new String[] {"6250 9410 0652 859"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"6250 9410 0652 859"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '6250 9410 0652 8599' is a valid 16 digits card number.
-        setTextInCardEditorAndWait(new String[] {"6250 9410 0652 8599"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"6250 9410 0652 8599"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
-        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 00"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 00"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '6212 3456 7890 0000 001' is an invalid 19 digits card number.
-        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 001"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 001"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
 
         // '6212 3456 7890 0000 003' is a valid 19 digits card number.
-        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 003"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 003"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() != focusedChildView);
 
         // Request focus to card number field after auto advancing above.
@@ -185,7 +185,8 @@
                 focusedChildView.requestFocus();
             }
         });
-        setTextInCardEditorAndWait(new String[] {"6212 3456 7890 0000 0031"}, mEditorTextUpdate);
+        setTextInCardEditorAndWait(
+                new String[] {"6212 3456 7890 0000 0031"}, getEditorTextUpdate());
         assertTrue(getCardEditorFocusedView() == focusedChildView);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
index 2f18085..65e7b99d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
@@ -37,7 +37,7 @@
     @Feature({"Payments"})
     public void testCannotMakePayment() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"false"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
index bba3fb5..c52f299 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
@@ -38,22 +38,22 @@
     @Feature({"Payments"})
     public void testCanMakePayment() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
 
         // Repeating a query does not count against the quota.
-        clickNodeAndWait("buy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("buy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
 
-        clickNodeAndWait("buy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("buy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
 
         // Different queries are throttled for a period of time.
-        clickNodeAndWait("other-buy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("other-buy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"Not allowed to check whether can make payment"});
 
         // Repeating the same query again does not count against the quota.
-        clickNodeAndWait("buy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("buy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[]{"true"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
index 15547a8..2a06e94 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -49,10 +49,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "jon.doe@google.com", "+15555555555",
                 "Jon Doe", "4111111111111111", "12", "2050", "visa", "123", "Google", "340 Main St",
                 "CA", "Los Angeles", "90291", "US", "en", "freeShippingOption"});
@@ -68,7 +68,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
index b2fe942..92d772f9f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
@@ -61,8 +61,8 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "+15555555555", "jon.doe@google.com"});
     }
 
@@ -71,13 +71,13 @@
     @Feature({"Payments"})
     public void testAddInvalidContactAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"", "+++", "jane.jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"", "+++", "jane.jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -86,14 +86,14 @@
     @Feature({"Payments"})
     public void testAddContactAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Jane Jones", "999-999-9999", "jane.jones@google.com"},
-                mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"Jane Jones", "+19999999999", "jane.jones@google.com"});
     }
 
@@ -102,23 +102,28 @@
     @Feature({"Payments"})
     public void testQuickAddContactAndCloseShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add contact info" and then [X].
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getContactDetailsSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
+                getPaymentRequestUI()
+                        .getContactDetailsSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -127,20 +132,25 @@
     @Feature({"Payments"})
     public void testQuickCloseAndAddContactShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on [X] and then "add contact info."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
-                mUI.getContactDetailsSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getContactDetailsSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -150,13 +160,13 @@
     @Feature({"Payments"})
     public void testEditContactAndCancelEditorShouldKeepContactSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         expectContactDetailsRowIsSelected(0);
-        clickInContactInfoAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInContactInfoAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Cancel the editor.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the row to still be selected in the Contact Details section.
         expectContactDetailsRowIsSelected(0);
@@ -167,13 +177,13 @@
     @Feature({"Payments"})
     public void testAddContactAndCancelEditorShouldKeepContactSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         expectContactDetailsRowIsSelected(0);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Cancel the editor.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the existing row to still be selected in the Contact Details section.
         expectContactDetailsRowIsSelected(0);
@@ -184,23 +194,28 @@
     @Feature({"Payments"})
     public void testQuickAddContactAndCancelShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add contact info" and then "cancel."
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getContactDetailsSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
+                getPaymentRequestUI()
+                        .getContactDetailsSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -209,20 +224,25 @@
     @Feature({"Payments"})
     public void testQuickCancelAndAddContactShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "cancel" and then "add contact info."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
-                mUI.getContactDetailsSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getContactDetailsSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -235,8 +255,8 @@
     @Feature({"Payments"})
     public void testSuggestionsDeduped()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
     }
 
@@ -250,7 +270,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
index 5214517..cae5627 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
@@ -100,8 +100,8 @@
         mCountsToSet = new int[] {20, 15, 10, 5, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 5000, 1};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(4, getNumberOfShippingAddressSuggestions());
         assertTrue(getShippingAddressSuggestionLabel(0).contains("Lisa Simpson"));
         assertTrue(getShippingAddressSuggestionLabel(1).contains("Maggie Simpson"));
@@ -123,8 +123,8 @@
         mCountsToSet = new int[] {20, 15, 10, 5, 2, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 5000, 2, 1};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         // Only four profiles should be suggested to the user.
         assertEquals(4, getNumberOfShippingAddressSuggestions());
         assertTrue(getShippingAddressSuggestionLabel(0).contains("Lisa Simpson"));
@@ -148,8 +148,8 @@
         mCountsToSet = new int[] {15, 10, 5, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 1};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         // Only 3 profiles should be suggested, the two complete ones and the incomplete one that
         // has a street address.
         assertEquals(3, getNumberOfShippingAddressSuggestions());
@@ -172,11 +172,11 @@
         mDatesToSet = new int[] {5000};
 
         // Click on the unacceptable shipping address.
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         assertTrue(getShippingAddressSuggestionLabel(0).contains(
                 AUTOFILL_PROFILES[3].getFullName()));
-        clickOnShippingAddressSuggestionOptionAndWait(0, mSelectionChecked);
+        clickOnShippingAddressSuggestionOptionAndWait(0, getSelectionChecked());
 
         // The string should reflect the error sent from the merchant.
         CharSequence actualString = getShippingAddressOptionRowAtIndex(0).getLabelText();
@@ -197,8 +197,8 @@
         mCountsToSet = new int[] {15, 10, 5, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 1};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         assertEquals(4, getNumberOfShippingAddressSuggestions());
         assertTrue(getShippingAddressSuggestionLabel(0).contains("Phone number required"));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
index 5d41fec..14cff02 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -47,7 +47,7 @@
     @Feature({"Payments"})
     public void testAddressNotSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getSummarySectionButtonState());
     }
 
@@ -56,15 +56,15 @@
     @Feature({"Payments"})
     public void testSelectValidAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Shipping Address).
         expectPaymentMethodRowIsSelected(0);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_first_radio_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_first_radio_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "+16502530000", "US",
                 "en", "californiaShippingOption"});
@@ -75,21 +75,21 @@
     @Feature({"Payments"})
     public void testSelectValidAddressEditItAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Shipping Address).
         expectPaymentMethodRowIsSelected(0);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_first_radio_button, mReadyToPay);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_first_radio_button, getReadyToPay());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"Jane Doe"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"Jane Doe"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
         expectShippingAddressRowIsSelected(0);
 
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jane Doe", "4111111111111111", "12", "2050", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "+16502530000", "US",
                 "en", "californiaShippingOption"});
@@ -100,22 +100,22 @@
     @Feature({"Payments"})
     public void testSelectValidAddressEditItAndCancelAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Shipping Address).
         expectPaymentMethodRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_first_radio_button, mReadyToPay);
+        clickInShippingAddressAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_first_radio_button, getReadyToPay());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"Jane Doe"}, mEditorTextUpdate);
+        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"Jane Doe"}, getEditorTextUpdate());
         // Cancel the edit.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
         expectShippingAddressRowIsSelected(0);
 
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "+16502530000", "US",
                 "en", "californiaShippingOption"});
@@ -126,16 +126,16 @@
     @Feature({"Payments"})
     public void testAddInvalidAddressAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Shipping Address).
         expectPaymentMethodRowIsSelected(0);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -148,15 +148,16 @@
     @Feature({"Payments"})
     public void testAddAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Bob", "Google", "1600 Amphitheatre Pkwy",
-                "Mountain View", "CA", "94043", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                "Mountain View", "CA", "94043", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Bob", "Google", "1600 Amphitheatre Pkwy",
                 "Mountain View", "CA", "94043", "+16502530000"});
     }
@@ -166,23 +167,28 @@
     @Feature({"Payments"})
     public void testQuickAddAddressAndCloseShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press "add address" and then [X].
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -191,20 +197,25 @@
     @Feature({"Payments"})
     public void testQuickCloseAndAddAddressShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press [X] and then "add address."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -214,23 +225,28 @@
     @Feature({"Payments"})
     public void testQuickAddAddressAndCancelShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press "add address" and then "cancel."
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -239,20 +255,25 @@
     @Feature({"Payments"})
     public void testQuickCancelAndAddAddressShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "cancel" and then "add address."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
index e33ba5d3..a8344960 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -44,10 +44,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"jon.doe@google.com", "Jon Doe", "4111111111111111",
                 "12", "2050", "visa", "123", "Google", "340 Main St", "CA", "Los Angeles", "90291",
                 "US", "en", "freeShippingOption"});
@@ -63,7 +63,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
index 82fade3..b6c0d52f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
@@ -60,8 +60,8 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"+15555555555", "jon.doe@google.com"});
     }
 
@@ -70,13 +70,13 @@
     @Feature({"Payments"})
     public void testAddInvalidEmailAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"-1-", "jane.jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"-1-", "jane.jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -85,13 +85,13 @@
     @Feature({"Payments"})
     public void testAddEmailAndPhoneAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(
-                new String[] {"555-555-5555", "jane.jones@google.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+                new String[] {"555-555-5555", "jane.jones@google.com"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"+15555555555", "jane.jones@google.com"});
     }
 
@@ -103,8 +103,8 @@
     @Feature({"Payments"})
     public void testSuggestionsDeduped()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
     }
 
@@ -117,7 +117,7 @@
     public void testRequestedInformationMetric()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         int appropriateEnumValue = PaymentRequestMetrics.REQUESTED_INFORMATION_EMAIL
                 | PaymentRequestMetrics.REQUESTED_INFORMATION_PHONE;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
index 282dcc8..afa3fab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
@@ -60,8 +60,8 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"jon.doe@google.com"});
     }
 
@@ -70,13 +70,13 @@
     @Feature({"Payments"})
     public void testAddInvalidEmailAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"jane.jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"jane.jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -85,13 +85,13 @@
     @Feature({"Payments"})
     public void testAddEmailAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"jane.jones@google.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"jane.jones@google.com"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"jane.jones@google.com"});
     }
 
@@ -103,8 +103,8 @@
     @Feature({"Payments"})
     public void testSuggestionsDeduped()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
     }
 
@@ -117,7 +117,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
index fa1ed17..79e5154 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
@@ -52,12 +52,12 @@
     @Feature({"Payments"})
     public void testPayWithExpiredCard_ValidExpiration()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"11", "26", "123"}, mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                new String[] {"11", "26", "123"}, getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "11", "2026", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "US", "en",
                 "freeShippingOption"});
@@ -71,12 +71,12 @@
     @Feature({"Payments"})
     public void testPayWithExpiredCard_NewExpirationSaved()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"11", "26", "123"}, mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                new String[] {"11", "26", "123"}, getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the new expiration date was saved.
         CreditCard storedCard = mHelper.getCreditCard(mCreditCardId);
@@ -96,22 +96,23 @@
         Calendar now = Calendar.getInstance();
         if (now.get(Calendar.MONTH) == 0) return;
 
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Try to add an expired card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
         // Set the expiration date to past month of the current year.
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {now.get(Calendar.MONTH) - 1, 0, 0}, mBillingAddressChangeProcessed);
-        setTextInCardEditorAndWait(new String[] {"4111111111111111", "Jon Doe"}, mEditorTextUpdate);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+                new int[] {now.get(Calendar.MONTH) - 1, 0, 0}, getBillingAddressChangeProcessed());
+        setTextInCardEditorAndWait(
+                new String[] {"4111111111111111", "Jon Doe"}, getEditorTextUpdate());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
 
         // Set the expiration date to the current month of the current year.
-        setSpinnerSelectionsInCardEditorAndWait(new int[] {now.get(Calendar.MONTH), 0, 0},
-                mExpirationMonthChange);
+        setSpinnerSelectionsInCardEditorAndWait(
+                new int[] {now.get(Calendar.MONTH), 0, 0}, getExpirationMonthChange());
 
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
     }
 
     /**
@@ -124,26 +125,26 @@
     public void testPromptErrorMessages()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Click pay to get to the card unmask prompt.
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
 
         // Set valid arguments.
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"10", "26", "123"}, mUnmaskValidationDone);
+                new String[] {"10", "26", "123"}, getUnmaskValidationDone());
         assertTrue(getUnmaskPromptErrorMessage().equals(""));
 
         // Set an invalid expiration month.
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"99", "25", "123"}, mUnmaskValidationDone);
+                new String[] {"99", "25", "123"}, getUnmaskValidationDone());
         assertTrue(getUnmaskPromptErrorMessage().equals(
                 "Check your expiration month and try again"));
 
         // Set an invalid expiration year.
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"10", "14", "123"}, mUnmaskValidationDone);
+                new String[] {"10", "14", "123"}, getUnmaskValidationDone());
         assertTrue(getUnmaskPromptErrorMessage().equals(
                 "Check your expiration year and try again"));
 
@@ -156,8 +157,9 @@
             // Set an invalid expiration year.
             setTextInExpiredCardUnmaskDialogAndWait(
                     new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                    new String[] {Integer.toString(now.get(Calendar.MONTH) - 1), twoDigitsYear,
-                            "123"}, mUnmaskValidationDone);
+                    new String[] {
+                            Integer.toString(now.get(Calendar.MONTH) - 1), twoDigitsYear, "123"},
+                    getUnmaskValidationDone());
             assertTrue(getUnmaskPromptErrorMessage().equals(
                     "Check your expiration date and try again"));
         }
@@ -165,7 +167,7 @@
         // Set valid arguments again.
         setTextInExpiredCardUnmaskDialogAndWait(
                 new int[] {R.id.expiration_month, R.id.expiration_year, R.id.card_unmask_input},
-                new String[] {"10", "26", "123"}, mUnmaskValidationDone);
+                new String[] {"10", "26", "123"}, getUnmaskValidationDone());
         assertTrue(getUnmaskPromptErrorMessage().equals(""));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
index a94337b..e92bfa7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
@@ -45,10 +45,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "US", "en"});
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
index 36572a4..b025e68 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
@@ -39,11 +39,11 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mResultReady);
-        clickAndWait(R.id.ok_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getResultReady());
+        clickAndWait(R.id.ok_button, getDismissed());
         expectResultContains(new String[] {"Transaction failed"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
index 4fcf1899..055856c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
@@ -42,7 +42,7 @@
     @CommandLineFlags.Add("enable-features=NoCreditCardAbort")
     public void testAbortIfNoCard_Enabled_NoApp()
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         expectResultContains(new String[] {"The payment method is not supported"});
     }
 
@@ -56,7 +56,7 @@
     public void testAbortIfNoCard_Enabled_WithApp()
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
     }
 
     /**
@@ -69,6 +69,6 @@
     public void testAbortIfNoCard_Disabled()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Check that the Payment Request UI is shown.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
index 68f5dfe..f494f4f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -45,10 +45,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "US", "en",
                 "freeShippingOption"});
@@ -60,12 +60,12 @@
     @Feature({"Payments"})
     public void testAddInvalidAddressAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -74,15 +74,16 @@
     @Feature({"Payments"})
     public void testAddAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Bob", "Google", "1600 Amphitheatre Pkwy",
-                "Mountain View", "CA", "94043", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                "Mountain View", "CA", "94043", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Bob", "Google", "1600 Amphitheatre Pkwy",
                 "Mountain View", "CA", "94043", "+16502530000"});
     }
@@ -92,16 +93,17 @@
     @Feature({"Payments"})
     public void testChangeCountryAddAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setSpinnerSelectionInEditorAndWait(0 /* Afghanistan */, mReadyToEdit);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setSpinnerSelectionInEditorAndWait(0 /* Afghanistan */, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Alice", "Supreme Court", "Airport Road", "Kabul",
-                "1043", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                "1043", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {
                 "Alice", "Supreme Court", "Airport Road", "Kabul", "1043", "+16502530000"});
     }
@@ -111,23 +113,28 @@
     @Feature({"Payments"})
     public void testQuickAddAddressAndCloseShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add address" and then [X].
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -136,20 +143,25 @@
     @Feature({"Payments"})
     public void testQuickCloseAndAddAddressShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on [X] and then "add address."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -160,23 +172,28 @@
     @Feature({"Payments"})
     public void testQuickAddAddressAndCancelShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add address" and then "cancel."
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -185,20 +202,25 @@
     @Feature({"Payments"})
     public void testQuickCancelAndAddAddressShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "cancel" and then "add address."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
-                mUI.getShippingAddressSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getShippingAddressSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -212,7 +234,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
index fe63e2f..6e45b0acd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
@@ -45,10 +45,10 @@
     @Feature({"Payments"})
     public void testPaymentResponse()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"my_payment_id"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
index 3d50986..a7b40bde 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
@@ -45,25 +45,26 @@
     @Feature({"Payments"})
     public void testEditIncompleteShippingAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         assertEquals("Jon Doe\njon.doe@google.com\nPhone number required",
                 getContactDetailsSuggestionLabel(0));
 
         assertTrue(getShippingAddressSuggestionLabel(0).contains("Phone number required"));
-        clickInShippingAddressAndWait(R.id.payments_first_radio_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_first_radio_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Jon Doe", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
+                "CA", "90291", "650-253-0000"},
+                getEditorTextUpdate());
         // The contact is now complete, but not selected.
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyForInput);
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyForInput());
         // We select it.
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals("Jon Doe\n+1 650-253-0000\njon.doe@google.com",
                 getContactDetailsSuggestionLabel(0));
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToPay);
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToPay());
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "+16502530000", "jon.doe@google.com"});
     }
 
@@ -72,31 +73,32 @@
     @Feature({"Payments"})
     public void testEditIncompleteShippingAndContactAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // There is an incomplete contact.
         assertEquals("Jon Doe\njon.doe@google.com\nPhone number required",
                 getContactDetailsSuggestionLabel(0));
 
         // Add a new Shipping Address and see that the contact section updates.
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Jane Doe", "Edge Corp.", "111 Wall St.", "New York",
-                "NY", "10110", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyForInput);
+                "NY", "10110", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyForInput());
         assertEquals("Jon Doe\njon.doe@google.com\nPhone number required",
                 getContactDetailsSuggestionLabel(0));
         assertEquals(
                 "Jane Doe\n+1 650-253-0000\nEmail required", getContactDetailsSuggestionLabel(1));
 
         // Now edit the first contact and pay.
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(
-                new String[] {"Jon Doe", "650-253-0000", "jon.doe@google.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"Jon Doe", "650-253-0000", "jon.doe@google.com"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "+16502530000", "jon.doe@google.com"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
index 52e7055..b9aa2df 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
@@ -44,21 +44,21 @@
     public void testEditIncompleteContactAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact email is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Updating contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"", "---", "jane.jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"", "---", "jane.jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
         // The section collapses and the [CHOOSE] button is active.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -68,21 +68,21 @@
     public void testAddIncompleteContactAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact email is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Adding contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"", "---", "jane.jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"", "---", "jane.jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
         // The section collapses and the [CHOOSE] button is active.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -91,13 +91,13 @@
     @Feature({"Payments"})
     public void testEditIncompleteContactAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Jon Doe", "555-555-5555", "jon.doe@google.com"},
-                mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "+15555555555", "jon.doe@google.com"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
index 33d3c3e..7167818 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
@@ -44,20 +44,20 @@
     public void testEditIncompleteEmailAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact email is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Updating contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"gmail.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"gmail.com"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -67,21 +67,21 @@
     public void testAddIncompleteEmailAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact email is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Updating contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"gmail.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"gmail.com"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
         // The section collapses and the [CHOOSE] button is active.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -90,12 +90,12 @@
     @Feature({"Payments"})
     public void testEditIncompleteEmailAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"jon.doe@google.com"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"jon.doe@google.com"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"jon.doe@google.com"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
index a22c8b99..1b123ef6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
@@ -44,20 +44,20 @@
     public void testEditIncompletePhoneAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact phone is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Updating contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"---"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"---"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -67,21 +67,21 @@
     public void testAddIncompletePhoneAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Not ready to pay since Contact phone is invalid.
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // Check that there is a selected payment method (makes sure we are not ready to pay because
         // of the Contact Details).
         expectPaymentMethodRowIsSelected(0);
         // Updating contact with an invalid value and cancelling means we're still not
         // ready to pay (the value is still the original value).
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"---"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"---"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
         // The section collapses and the [CHOOSE] button is active.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
         assertEquals(PaymentRequestSection.EDIT_BUTTON_CHOOSE, getContactDetailsButtonState());
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -90,12 +90,12 @@
     @Feature({"Payments"})
     public void testEditIncompletePhoneAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"514-555-5555"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"514-555-5555"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"+15145555555"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
index 032a1dd..de2141f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
@@ -42,16 +42,16 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPayAndDontUnmask() throws InterruptedException, ExecutionException,
-           TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_first_radio_button, mReadyToEdit);
-        setSpinnerSelectionsInCardEditorAndWait(new int[] {FIRST_BILLING_ADDRESS},
-                mBillingAddressChangeProcessed);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, mReadyToPay);
-        clickAndWait(R.id.button_secondary, mDismissed);
+            TimeoutException {
+        triggerUIAndWait(getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_first_radio_button, getReadyToEdit());
+        setSpinnerSelectionsInCardEditorAndWait(
+                new int[] {FIRST_BILLING_ADDRESS}, getBillingAddressChangeProcessed());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, getReadyToPay());
+        clickAndWait(R.id.button_secondary, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
index e007e41..58abf0d2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -53,10 +53,10 @@
     public void testNumberOfSuggestionsShown_ShippingAddress_Completed()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the right number of suggestions were logged.
         assertEquals(
@@ -83,8 +83,8 @@
     public void testNumberOfSuggestionsShown_ShippingAddress_AbortedByUser()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Cancel the payment request.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
 
         // Wait for the histograms to be logged.
         Thread.sleep(200);
@@ -114,18 +114,18 @@
     public void testNumberOfSelectionEdits_ShippingAddress_Completed()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Select the incomplete address and edit it.
-        clickOnShippingAddressSuggestionOptionAndWait(1, mReadyToEdit);
+        clickOnShippingAddressSuggestionOptionAndWait(1, getReadyToEdit());
         setTextInEditorAndWait(
                 new String[] {"In Complete", "Google", "344 Main St", "CA", "Los Angeles"},
-                mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the edit was logged.
         assertEquals(
@@ -151,20 +151,21 @@
     public void testNumberOfSelectionAdds_ShippingAddress_Completed()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Add a new shipping address.
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setSpinnerSelectionInEditorAndWait(0 /* Afghanistan */, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setSpinnerSelectionInEditorAndWait(0 /* Afghanistan */, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Alice", "Supreme Court", "Airport Road", "Kabul",
-                "1043", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                "1043", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Complete the transaction.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the add was logged.
         assertEquals(
@@ -188,10 +189,10 @@
     public void testNumberOfSuggestionsShown_CreditCards_Completed()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the right number of suggestions were logged.
         assertEquals(
@@ -216,8 +217,8 @@
     public void testNumberOfSuggestionsShown_CreditCards_AbortedByUser()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Cancel the payment request.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
 
         // Wait for the histograms to be logged.
         Thread.sleep(200);
@@ -246,20 +247,21 @@
     public void testNumberOfSelectionAdds_CreditCards_Completed()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
+        triggerUIAndWait("ccBuy", getReadyToPay());
 
         // Add a new credit card.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {11, 1, 0}, mBillingAddressChangeProcessed);
-        setTextInCardEditorAndWait(new String[] {"4111111111111111", "Jon Doe"}, mEditorTextUpdate);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                new int[] {11, 1, 0}, getBillingAddressChangeProcessed());
+        setTextInCardEditorAndWait(
+                new String[] {"4111111111111111", "Jon Doe"}, getEditorTextUpdate());
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Complete the transaction.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the add was logged.
         assertEquals(1, RecordHistogram.getHistogramValueCountForTesting(
@@ -281,10 +283,10 @@
     public void testNoContactInfoHistogram()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure nothing was logged for contact info.
         assertEquals(
@@ -307,10 +309,10 @@
     @Feature({"Payments"})
     public void testTwoTimes() throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the right number of suggestions were logged.
         assertEquals(
@@ -329,10 +331,10 @@
                            "PaymentRequest.NumberOfSelectionEdits.ShippingAddress.Completed", 0));
 
         // Complete a second Payment Request with a credit card.
-        reTriggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        reTriggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure the right number of suggestions were logged.
         assertEquals(
@@ -359,7 +361,7 @@
     public void testNoShow() throws InterruptedException, ExecutionException, TimeoutException {
         // Android Pay is supported but no instruments are present.
         installPaymentApp("https://android.com/pay", NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickNodeAndWait("androidPayBuy", mShowFailed);
+        openPageAndClickNodeAndWait("androidPayBuy", getShowFailed());
         expectResultContains(new String[] {"The payment method is not supported"});
 
         // Make sure that no journey metrics were logged.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
index 56b3db2..80a1d21 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -50,7 +50,7 @@
     public void testSuccessCheckoutFunnel() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Initiate a payment request.
-        triggerUIAndWait("ccBuy", mReadyToPay);
+        triggerUIAndWait("ccBuy", getReadyToPay());
 
         // Make sure sure that the "Initiated" and "Shown" events were logged.
         assertEquals(1, RecordHistogram.getHistogramValueCountForTesting(
@@ -59,15 +59,15 @@
                 "PaymentRequest.CheckoutFunnel.Shown", 1));
 
         // Click the pay button.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
 
         // Make sure sure that the "PayClicked" event was logged.
         assertEquals(1, RecordHistogram.getHistogramValueCountForTesting(
                 "PaymentRequest.CheckoutFunnel.PayClicked", 1));
 
         // Unmask the credit card,
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Make sure sure that the "ReceivedInstrumentDetails" and "Completed" events were logged.
         assertEquals(1, RecordHistogram.getHistogramValueCountForTesting(
@@ -84,18 +84,21 @@
     @Feature({"Payments"})
     public void testAbortMetrics_AbortedByUser_CancelButton() throws InterruptedException,
             ExecutionException, TimeoutException {
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Cancel the Payment Request.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
         expectResultContains(new String[] {"Request cancelled"});
 
         assertOnlySpecificAbortMetricLogged(
@@ -110,11 +113,11 @@
     @Feature({"Payments"})
     public void testAbortMetrics_AbortedByUser_XButton() throws InterruptedException,
             ExecutionException, TimeoutException {
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Press the [X] button.
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
 
         assertOnlySpecificAbortMetricLogged(
@@ -129,18 +132,18 @@
     @Feature({"Payments"})
     public void testAbortMetrics_AbortedByUser_BackButton() throws InterruptedException,
             ExecutionException, TimeoutException {
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Press the back button.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
         expectResultContains(new String[] {"Request cancelled"});
 
         assertOnlySpecificAbortMetricLogged(
@@ -155,8 +158,8 @@
     @Feature({"Payments"})
     public void testAbortMetrics_AbortedByUser_TabClosed() throws InterruptedException,
             ExecutionException, TimeoutException {
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Press the back button.
         ChromeTabUtils.closeCurrentTab(getInstrumentation(), getActivity());
@@ -173,10 +176,10 @@
     @Feature({"Payments"})
     public void testAbortMetrics_AbortedByMerchant() throws InterruptedException,
             ExecutionException, TimeoutException {
-        triggerUIAndWait("ccBuy", mReadyToPay);
+        triggerUIAndWait("ccBuy", getReadyToPay());
 
         // Simulate an abort by the merchant.
-        clickNodeAndWait("abort", mDismissed);
+        clickNodeAndWait("abort", getDismissed());
         expectResultContains(new String[] {"Abort"});
 
         assertOnlySpecificAbortMetricLogged(
@@ -196,7 +199,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         // Android Pay is supported but no instruments are present.
         installPaymentApp("https://android.com/pay", NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickNodeAndWait("androidPayBuy", mShowFailed);
+        openPageAndClickNodeAndWait("androidPayBuy", getShowFailed());
         expectResultContains(new String[] {"The payment method is not supported"});
 
         // Make sure that it is not logged as an abort.
@@ -217,7 +220,7 @@
     @Feature({"Payments"})
     public void testMetrics_NoSupportedPaymentMethod()
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("noSupported", mShowFailed);
+        openPageAndClickNodeAndWait("noSupported", getShowFailed());
         expectResultContains(new String[] {"The payment method is not supported"});
 
         // Make sure that it is not logged as an abort.
@@ -237,10 +240,10 @@
     public void testSelectedPaymentMethod_CreditCard() throws InterruptedException,
             ExecutionException, TimeoutException {
         // Complete a Payment Request with a credit card.
-        triggerUIAndWait("ccBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait("ccBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         assertOnlySpecificSelectedPaymentMethodMetricLogged(
                 PaymentRequestMetrics.SELECTED_METHOD_CREDIT_CARD);
@@ -256,8 +259,8 @@
             ExecutionException, TimeoutException {
         // Complete a Payment Request with Android Pay.
         installPaymentApp("https://android.com/pay", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        triggerUIAndWait("androidPayBuy", mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait("androidPayBuy", getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
 
         assertOnlySpecificSelectedPaymentMethodMetricLogged(
                 PaymentRequestMetrics.SELECTED_METHOD_ANDROID_PAY);
@@ -273,7 +276,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with Android Pay.
         installPaymentApp("https://android.com/pay", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        triggerUIAndWait("androidPaySkipUiBuy", mResultReady);
+        triggerUIAndWait("androidPaySkipUiBuy", getResultReady());
 
         assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
@@ -294,7 +297,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         // Complete a Payment Request with Android Pay.
         installPaymentApp("https://android.com/pay", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        triggerUIAndWait("androidPaySkipUiBuy", mReadyToPay);
+        triggerUIAndWait("androidPaySkipUiBuy", getReadyToPay());
 
         assertEquals(1,
                 RecordHistogram.getHistogramValueCountForTesting(
@@ -312,7 +315,7 @@
     public void testShownLoggedOnlyOnce()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Initiate a payment request.
-        triggerUIAndWait("ccBuy", mReadyToPay);
+        triggerUIAndWait("ccBuy", getReadyToPay());
 
         // Make sure sure that the "Shown" event was logged.
         assertEquals(1,
@@ -320,11 +323,12 @@
                         "PaymentRequest.CheckoutFunnel.Shown", 1));
 
         // Add a shipping address, which triggers a second "Show".
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Seb Doe", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                "CA", "90291", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Make sure "Shown" is still logged only once.
         assertEquals(1,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
index ad53450..db3c743 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
@@ -131,8 +131,8 @@
         mCountsToSet = new int[] {20, 15, 10, 5, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 5000, 1};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(4, getNumberOfContactDetailSuggestions());
         assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com",
                 getContactDetailsSuggestionLabel(0));
@@ -157,8 +157,8 @@
         mCountsToSet = new int[] {15, 10, 5, 1};
         mDatesToSet = new int[] {5000, 5000, 5000, 5000};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(4, getNumberOfContactDetailSuggestions());
         assertEquals("Bart Simpson\nbart@simpson.com\nPhone number required",
                 getContactDetailsSuggestionLabel(0));
@@ -187,8 +187,8 @@
         mCountsToSet = new int[] {1, 20, 15, 10, 5};
         mDatesToSet = new int[] {1000, 4000, 3000, 2000, 1000};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
 
         // Only the original profile with all the fields should be suggested.
         assertEquals(1, getNumberOfContactDetailSuggestions());
@@ -210,8 +210,8 @@
         mCountsToSet = new int[] {15, 5};
         mDatesToSet = new int[] {5000, 2000};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
         assertEquals("Lisa Simpson\n555 123-4567\nlisa@simpson.com",
                 getContactDetailsSuggestionLabel(0));
@@ -232,8 +232,8 @@
         mCountsToSet = new int[] {15, 25};
         mDatesToSet = new int[] {5000, 7000};
 
-        triggerUIAndWait(mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(2, getNumberOfContactDetailSuggestions());
         assertEquals("Lisa Simpson\n555 123-4567\nfakelisa@simpson.com",
                 getContactDetailsSuggestionLabel(0));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
index d8ea66e..e36b025c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -44,10 +44,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "Jon Doe", "4111111111111111", "12",
                 "2050", "visa", "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "US",
                 "en", "freeShippingOption"});
@@ -63,7 +63,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
index cc92694..bb731fe0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -63,10 +63,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe"});
     }
 
@@ -75,13 +75,13 @@
     @Feature({"Payments"})
     public void testAddInvalidNameAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {""}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {""}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -90,14 +90,14 @@
     @Feature({"Payments"})
     public void testAddNameAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"Jane Jones"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"Jane Jones"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jane Jones"});
     }
 
@@ -109,8 +109,8 @@
     @Feature({"Payments"})
     public void testSuggestionsDeduped()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
     }
 
@@ -123,7 +123,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
index 017fc2c..78d7e3f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -45,8 +45,8 @@
     @Feature({"Payments"})
     public void testCloseDialog() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -55,9 +55,9 @@
     @Feature({"Payments"})
     public void testEditAndCloseDialog() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickAndWait(R.id.button_secondary, mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickAndWait(R.id.button_secondary, getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -66,9 +66,9 @@
     @Feature({"Payments"})
     public void testEditAndCancelDialog() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        clickAndWait(R.id.button_secondary, mReadyForInput);
-        clickAndWait(R.id.button_secondary, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickAndWait(R.id.button_secondary, getReadyForInput());
+        clickAndWait(R.id.button_secondary, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -76,10 +76,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123"});
     }
@@ -89,12 +89,12 @@
     @Feature({"Payments"})
     public void testCancelUnmaskAndRetry()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                 "123"});
     }
@@ -107,9 +107,9 @@
         // Attempting to add an invalid card and cancelling out of the flow will result in the user
         // still being ready to pay with the previously selected credit card.
         fillNewCardForm("123", "Bob", DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -120,9 +120,9 @@
     public void testAddEmptyNameOnCardAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
         fillNewCardForm("5454-5454-5454-5454", "", DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -132,10 +132,10 @@
     public void testSaveNewCardAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         fillNewCardForm("5454-5454-5454-5454", "Bob", DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS);
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"5454545454545454", "12", "Bob"});
     }
 
@@ -147,23 +147,23 @@
         fillNewCardForm("5454-5454-5454-5454", "Bob", DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS);
 
         // Uncheck the "Save this card on this device" checkbox, so the card is temporary.
-        selectCheckboxAndWait(R.id.payments_edit_checkbox, false, mReadyToEdit);
+        selectCheckboxAndWait(R.id.payments_edit_checkbox, false, getReadyToEdit());
 
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"5454545454545454", "12", "Bob"});
     }
 
     private void fillNewCardForm(String cardNumber, String nameOnCard, int month, int year,
             int billingAddress) throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInCardEditorAndWait(new String[] {cardNumber, nameOnCard}, mEditorTextUpdate);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInCardEditorAndWait(new String[] {cardNumber, nameOnCard}, getEditorTextUpdate());
         setSpinnerSelectionsInCardEditorAndWait(
-                new int[] {month, year, billingAddress}, mBillingAddressChangeProcessed);
+                new int[] {month, year, billingAddress}, getBillingAddressChangeProcessed());
     }
 
     /** Add a new card together with a new billing address and pay. */
@@ -171,25 +171,27 @@
     @Feature({"Payments"})
     public void testSaveNewCardAndNewBillingAddressAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInCardEditorAndWait(new String[] {"5454 5454 5454 5454", "Bob"}, mEditorTextUpdate);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInCardEditorAndWait(
+                new String[] {"5454 5454 5454 5454", "Bob"}, getEditorTextUpdate());
 
         // Select December of next year for expiration and [Add address] in the billing address
         // dropdown.
         int addBillingAddress = 1;
-        setSpinnerSelectionsInCardEditorAndWait(new int[] {DECEMBER, NEXT_YEAR, addBillingAddress},
-                mReadyToEdit);
+        setSpinnerSelectionsInCardEditorAndWait(
+                new int[] {DECEMBER, NEXT_YEAR, addBillingAddress}, getReadyToEdit());
 
         setTextInEditorAndWait(new String[] {"Bob", "Google", "1600 Amphitheatre Pkwy",
-                "Mountain View", "CA", "94043", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToEdit);
+                "Mountain View", "CA", "94043", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToEdit());
 
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"5454545454545454", "12", "Bob", "Google",
                 "1600 Amphitheatre Pkwy", "Mountain View", "CA", "94043", "+16502530000"});
     }
@@ -199,23 +201,28 @@
     @Feature({"Payments"})
     public void testQuickAddCardAndCloseShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add card" and then [X].
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getPaymentMethodSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
+                getPaymentRequestUI()
+                        .getPaymentMethodSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -224,20 +231,25 @@
     @Feature({"Payments"})
     public void testQuickCloseAndAddCardShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on [X] and then "add card."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
-                mUI.getPaymentMethodSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getPaymentMethodSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -247,23 +259,28 @@
     @Feature({"Payments"})
     public void testQuickAddCardAndCancelShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "add card" and then "cancel."
-        int callCount = mReadyToEdit.getCallCount();
+        int callCount = getReadyToEdit().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getPaymentMethodSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
+                getPaymentRequestUI()
+                        .getPaymentMethodSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
             }
         });
-        mReadyToEdit.waitForCallback(callCount);
+        getReadyToEdit().waitForCallback(callCount);
 
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -272,20 +289,25 @@
     @Feature({"Payments"})
     public void testQuickCancelAndAddCardShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Quickly press on "cancel" and then "add card."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.button_secondary).performClick();
-                mUI.getPaymentMethodSectionForTest().findViewById(
-                        R.id.payments_add_option_button).performClick();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_secondary)
+                        .performClick();
+                getPaymentRequestUI()
+                        .getPaymentMethodSectionForTest()
+                        .findViewById(R.id.payments_add_option_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -298,18 +320,21 @@
     @Feature({"Payments"})
     public void testQuickDismissAndPayShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Quickly dismiss and then press on "pay."
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
-                mUI.getDialogForTest().findViewById(R.id.button_primary).performClick();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.button_primary)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -322,18 +347,21 @@
     @Feature({"Payments"})
     public void testQuickDismissAndCloseShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Quickly dismiss and then press on [X].
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().onBackPressed();
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -346,18 +374,21 @@
     @Feature({"Payments"})
     public void testQuickCloseAndDismissShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Quickly press on [X] and then dismiss.
-        int callCount = mDismissed.getCallCount();
+        int callCount = getDismissed().getCallCount();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mUI.getDialogForTest().findViewById(R.id.close_button).performClick();
-                mUI.getDialogForTest().onBackPressed();
+                getPaymentRequestUI()
+                        .getDialogForTest()
+                        .findViewById(R.id.close_button)
+                        .performClick();
+                getPaymentRequestUI().getDialogForTest().onBackPressed();
             }
         });
-        mDismissed.waitForCallback(callCount);
+        getDismissed().waitForCallback(callCount);
 
         expectResultContains(new String[] {"Request cancelled"});
     }
@@ -372,7 +403,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
index 774e844..b83292ab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
@@ -90,13 +90,13 @@
     @Feature({"Payments"})
     public void testEditPaymentMethodAndCancelEditorShouldKeepCardSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
         expectPaymentMethodRowIsSelected(0);
-        clickInPaymentMethodAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Cancel the editor.
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the existing row to still be selected in the Shipping Address section.
         expectPaymentMethodRowIsSelected(0);
@@ -107,13 +107,13 @@
     @Feature({"Payments"})
     public void testAddPaymentMethodAndCancelEditorShouldKeepExistingCardSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
         expectPaymentMethodRowIsSelected(0);
-        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Cancel the editor.
-        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInCardEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the row to still be selected in the Shipping Address section.
         expectPaymentMethodRowIsSelected(0);
@@ -122,8 +122,8 @@
     private void runTest(int instrumentPresence, int responseSpeed) throws InterruptedException,
             ExecutionException, TimeoutException  {
         installPaymentApp(instrumentPresence, responseSpeed);
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Check the number of instruments.
         assertEquals(
@@ -145,12 +145,12 @@
 
         // Check the output of the selected instrument.
         if (instrumentPresence == HAVE_INSTRUMENTS) {
-            clickAndWait(R.id.button_primary, mDismissed);
+            clickAndWait(R.id.button_primary, getDismissed());
             expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
         } else {
-            clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-            setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-            clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+            clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+            setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+            clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
             expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
                     "123"});
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
index e4081910..9fcc02a2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
@@ -28,10 +28,10 @@
     @Feature({"Payments"})
     public void testNoBobPayInstalled() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, false"});
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, NotAllowedError"});
     }
 
@@ -39,12 +39,12 @@
     @Feature({"Payments"})
     public void testBobPayInstalledLater()
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, false"});
 
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true, NotAllowedError"});
     }
 
@@ -53,10 +53,10 @@
     public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, false"});
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, NotAllowedError"});
     }
 
@@ -65,10 +65,10 @@
     public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, false"});
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"false, NotAllowedError"});
     }
 
@@ -77,10 +77,10 @@
     public void testPayViaFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true, true"});
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true, NotAllowedError"});
     }
 
@@ -89,10 +89,10 @@
     public void testPayViaSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mCanMakePaymentQueryResponded);
+        openPageAndClickBuyAndWait(getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true, true"});
 
-        clickNodeAndWait("otherBuy", mCanMakePaymentQueryResponded);
+        clickNodeAndWait("otherBuy", getCanMakePaymentQueryResponded());
         expectResultContains(new String[] {"true, NotAllowedError"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
index 85124172..e7a9c23 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
@@ -11,6 +11,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback;
 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
+import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay;
 import org.chromium.content_public.browser.WebContents;
 
 import java.util.Arrays;
@@ -35,7 +36,7 @@
     @Feature({"Payments"})
     public void testNoSupportedPaymentMethods() throws InterruptedException, ExecutionException,
             TimeoutException {
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
     }
@@ -49,7 +50,7 @@
     public void testNoInstrumentsInFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
     }
@@ -63,7 +64,7 @@
     public void testNoInstrumentsInSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(NO_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
     }
@@ -86,8 +87,8 @@
                 callback.onAllPaymentAppsCreated();
             }
         });
-        triggerUIAndWait(mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -114,7 +115,7 @@
                 callback.onAllPaymentAppsCreated();
             }
         });
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -134,8 +135,8 @@
     public void testPayViaFastBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -148,8 +149,8 @@
     public void testPayViaSlowBobPay() throws InterruptedException, ExecutionException,
             TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[]{"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -163,8 +164,8 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE, DELAYED_CREATION);
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -178,8 +179,8 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, DELAYED_RESPONSE, DELAYED_CREATION);
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
index c1f37493..aee032c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
@@ -34,7 +34,7 @@
     public void testPayViaFastBobPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -47,7 +47,7 @@
     public void testPayViaSlowBobPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -61,7 +61,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE, DELAYED_CREATION);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -75,7 +75,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, DELAYED_RESPONSE, DELAYED_CREATION);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
index a158a26..74f778c1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
@@ -33,7 +33,7 @@
     public void testPayViaFastBobPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -46,7 +46,7 @@
     public void testPayViaSlowBobPay()
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(HAVE_INSTRUMENTS, DELAYED_RESPONSE);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -60,7 +60,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE, DELAYED_CREATION);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 
@@ -74,7 +74,7 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         installPaymentApp(
                 "https://bobpay.com", HAVE_INSTRUMENTS, DELAYED_RESPONSE, DELAYED_CREATION);
-        openPageAndClickBuyAndWait(mDismissed);
+        openPageAndClickBuyAndWait(getDismissed());
         expectResultContains(new String[] {"https://bobpay.com", "\"transaction\"", "1337"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
index 4a4e4f4..8857866e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback;
 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
+import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay;
 import org.chromium.content_public.browser.WebContents;
 
 import java.util.Arrays;
@@ -81,8 +82,8 @@
         PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appBCharliePayId, 15);
         PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appBCharliePayId, 15);
 
-        triggerUIAndWait(mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Checks Charlie Pay is listed at the first position.
         assertEquals(4, getNumberOfPaymentInstruments());
@@ -94,7 +95,7 @@
                 getPaymentInstrumentLabel(3));
 
         // Cancel the Payment Request.
-        clickAndWait(R.id.button_secondary, mDismissed);
+        clickAndWait(R.id.button_secondary, getDismissed());
 
         // Checks the records for all payment instruments haven't been changed.
         assertEquals(5, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appAAlicePayId));
@@ -108,8 +109,8 @@
         PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appAAlicePayId, 20);
         PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appAAlicePayId, 20);
 
-        reTriggerUIAndWait("buy", mReadyToPay);
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        reTriggerUIAndWait("buy", getReadyToPay());
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Checks Alice Pay is listed at the first position. Checks Bob Pay is listed at the second
         // position together with Alice Pay since they come from the same app.
@@ -121,7 +122,7 @@
                 "Visa\u0020\u0020\u2022\u2006\u2022\u2006\u2022\u2006\u2022\u20061111\nJon Doe",
                 getPaymentInstrumentLabel(3));
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         // Checks Alice Pay is selected as the default payment method.
         expectResultContains(new String[] {"https://alicepay.com", "\"transaction\"", "1337"});
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
index b17aaa0..6730a12 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -44,10 +44,10 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"+15555555555", "Jon Doe", "4111111111111111", "12",
                 "2050", "visa", "123", "Google", "340 Main St", "CA", "Los Angeles", "90291", "US",
                 "en", "freeShippingOption"});
@@ -63,7 +63,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
index f8f90ae..253ed69b4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
@@ -60,8 +60,8 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPay() throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"+15555555555"});
     }
 
@@ -70,13 +70,13 @@
     @Feature({"Payments"})
     public void testAddInvalidPhoneAndCancel()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"+++"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"+++"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 
@@ -85,13 +85,13 @@
     @Feature({"Payments"})
     public void testAddPhoneAndPay()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
-        clickInContactInfoAndWait(R.id.payments_add_option_button, mReadyToEdit);
-        setTextInEditorAndWait(new String[] {"999-999-9999"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
+        clickInContactInfoAndWait(R.id.payments_add_option_button, getReadyToEdit());
+        setTextInEditorAndWait(new String[] {"999-999-9999"}, getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
-        clickAndWait(R.id.button_primary, mDismissed);
+        clickAndWait(R.id.button_primary, getDismissed());
         expectResultContains(new String[] {"+19999999999"});
     }
 
@@ -103,8 +103,8 @@
     @Feature({"Payments"})
     public void testSuggestionsDeduped()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInContactInfoAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInContactInfoAndWait(R.id.payments_section, getReadyForInput());
         assertEquals(1, getNumberOfContactDetailSuggestions());
     }
 
@@ -117,7 +117,7 @@
     public void testRequestedInformationMetric() throws InterruptedException, ExecutionException,
             TimeoutException {
         // Start the Payment Request.
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that only the appropriate enum value was logged.
         for (int i = 0; i < PaymentRequestMetrics.REQUESTED_INFORMATION_MAX; ++i) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
index ae242573..1d234c5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
@@ -48,30 +48,30 @@
     @Feature({"Payments"})
     public void testPayWithCard()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
 
         // Expand the payment section.
-        clickInPaymentMethodAndWait(R.id.payments_section, mReadyForInput);
+        clickInPaymentMethodAndWait(R.id.payments_section, getReadyForInput());
 
         // Selecting the credit card should bring up the editor.
-        clickInPaymentMethodAndWait(R.id.payments_first_radio_button, mReadyToEdit);
+        clickInPaymentMethodAndWait(R.id.payments_first_radio_button, getReadyToEdit());
 
         // Tapping "save" in the editor should trigger a validation error.
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mEditorValidationError);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getEditorValidationError());
 
         // Fix the validation error by selecting a billing address.
         setSpinnerSelectionsInCardEditorAndWait(
                 new int[] {DECEMBER, NEXT_YEAR, FIRST_BILLING_ADDRESS},
-                mBillingAddressChangeProcessed);
+                getBillingAddressChangeProcessed());
 
         // Tapping "save" in the editor now should close the editor dialog and enable the "pay"
         // button.
-        clickInCardEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+        clickInCardEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Pay with this card.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
         expectResultContains(new String[] {"4111111111111111", "Alice", "12", "123", "Jane Smith",
                 "Google", "1600 Amphitheatre Pkwy", "CA", "Mountain View", "94043", "US",
                 "+15555555555", "en-US"});
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
index 80e5a81..34ce490 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
@@ -41,11 +41,11 @@
     @MediumTest
     @Feature({"Payments"})
     public void testPayAndDontUnmask() throws InterruptedException, ExecutionException,
-           TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, mReadyToPay);
-        clickAndWait(R.id.close_button, mDismissed);
+            TimeoutException {
+        triggerUIAndWait(getReadyToPay());
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, getReadyToPay());
+        clickAndWait(R.id.close_button, getDismissed());
         expectResultContains(new String[] {"Request cancelled"});
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
index 6a4b475..9ec7ac82 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -84,7 +84,7 @@
     public void testNoOptions() throws InterruptedException, ExecutionException,
             TimeoutException {
         installMockServiceWorkerPaymentApp(NO_OPTIONS);
-        openPageAndClickBuyAndWait(mShowFailed);
+        openPageAndClickBuyAndWait(getShowFailed());
         expectResultContains(
                 new String[]{"show() rejected", "The payment method is not supported"});
     }
@@ -94,7 +94,7 @@
     public void testOneOption() throws InterruptedException, ExecutionException,
             TimeoutException {
         installMockServiceWorkerPaymentApp(ONE_OPTION);
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // TODO(tommyt): crbug.com/669876. Expand this test as we implement more
         // service worker based payment app functionality.
     }
@@ -104,7 +104,7 @@
     public void testTwoOptions() throws InterruptedException, ExecutionException,
             TimeoutException {
         installMockServiceWorkerPaymentApp(TWO_OPTIONS);
-        triggerUIAndWait(mReadyForInput);
+        triggerUIAndWait(getReadyForInput());
         // TODO(tommyt): crbug.com/669876. Expand this test as we implement more
         // service worker based payment app functionality.
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
index 4491c2c..e5bbe2b24 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
@@ -48,10 +48,10 @@
     public void testShippingAddressChangeFormat()
             throws InterruptedException, ExecutionException, TimeoutException {
         // Select a shipping address and cancel out.
-        triggerUIAndWait(mReadyForInput);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickOnShippingAddressSuggestionOptionAndWait(0, mReadyForInput);
-        clickAndWait(R.id.close_button, mDismissed);
+        triggerUIAndWait(getReadyForInput());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickOnShippingAddressSuggestionOptionAndWait(0, getReadyForInput());
+        clickAndWait(R.id.close_button, getDismissed());
 
         // The phone number should be formatted to the internation format.
         expectResultContains(new String[] {"Jon Doe", "Google", "340 Main St", "CA", "Los Angeles",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
index c2b4a5a..e044e11 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
@@ -50,7 +50,7 @@
     @Feature({"Payments"})
     public void testShippingAddressFormat_BottomSheet()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Make sure that the shipping label on the bottomsheet does not include the country.
         assertTrue(getShippingAddressOptionRowAtIndex(0).getLabelText().toString().equals(
@@ -62,10 +62,10 @@
     @Feature({"Payments"})
     public void testShippingAddressFormat_FullSheet()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Focus on a section other that shipping addresses to enter fullsheet mode.
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
 
         // Make sure that the shipping label on the fullsheet does not include the country.
         assertTrue(getShippingAddressOptionRowAtIndex(0).getLabelText().toString().equals(
@@ -77,10 +77,10 @@
     @Feature({"Payments"})
     public void testShippingAddressFormat_Expanded()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Focus on the shipping addresses section to enter expanded mode.
-        clickInShippingAddressAndWait(R.id.payments_section, mReadyForInput);
+        clickInShippingAddressAndWait(R.id.payments_section, getReadyForInput());
 
         // Make sure that the shipping label in expanded mode includes the country.
         assertTrue(getShippingAddressOptionRowAtIndex(0).getLabelText().toString().equals(
@@ -100,14 +100,15 @@
     @Feature({"Payments"})
     public void testShippingAddressFormat_NewAddress()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Add a shipping address.
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
         setTextInEditorAndWait(new String[] {"Seb Doe", "Google", "340 Main St", "Los Angeles",
-                "CA", "90291", "650-253-0000"}, mEditorTextUpdate);
-        clickInEditorAndWait(R.id.payments_edit_done_button, mReadyToPay);
+                "CA", "90291", "650-253-0000"},
+                getEditorTextUpdate());
+        clickInEditorAndWait(R.id.payments_edit_done_button, getReadyToPay());
 
         // Make sure that the shipping label does not include the country.
         assertTrue(getShippingAddressOptionRowAtIndex(0).getLabelText().toString().equals(
@@ -122,13 +123,13 @@
     @Feature({"Payments"})
     public void testEditShippingAddressAndCancelEditorShouldKeepAddressSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Cancel the editor by clicking 'CANCEL' button in the editor view.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the row to still be selected in the Shipping Address section.
         expectShippingAddressRowIsSelected(0);
@@ -142,13 +143,13 @@
     @Feature({"Payments"})
     public void testEditShippingAddressAndClickAndroidBackButtonShouldKeepAddressSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_open_editor_pencil_button, getReadyToEdit());
 
         // Cancel the editor by clicking Android back button.
-        clickAndroidBackButtonInEditorAndWait(mReadyToPay);
+        clickAndroidBackButtonInEditorAndWait(getReadyToPay());
 
         // Expect the row to still be selected in the Shipping Address section.
         expectShippingAddressRowIsSelected(0);
@@ -162,13 +163,13 @@
     @Feature({"Payments"})
     public void testAddShippingAddressAndCancelEditorShouldKeepAddressSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Cancel the editor by clicking 'CANCEL' button in the editor view.
-        clickInEditorAndWait(R.id.payments_edit_cancel_button, mReadyToPay);
+        clickInEditorAndWait(R.id.payments_edit_cancel_button, getReadyToPay());
 
         // Expect the existing row to still be selected in the Shipping Address section.
         expectShippingAddressRowIsSelected(0);
@@ -182,13 +183,13 @@
     @Feature({"Payments"})
     public void testAddShippingAddressAndClickAndroidBackButtonShouldKeepAddressSelected()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
-        clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput);
+        triggerUIAndWait(getReadyToPay());
+        clickInShippingSummaryAndWait(R.id.payments_section, getReadyForInput());
         expectShippingAddressRowIsSelected(0);
-        clickInShippingAddressAndWait(R.id.payments_add_option_button, mReadyToEdit);
+        clickInShippingAddressAndWait(R.id.payments_add_option_button, getReadyToEdit());
 
         // Cancel the editor by clicking Android back button.
-        clickAndroidBackButtonInEditorAndWait(mReadyToPay);
+        clickAndroidBackButtonInEditorAndWait(getReadyToPay());
 
         // Expect the existing row to still be selected in the Shipping Address section.
         expectShippingAddressRowIsSelected(0);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index a265a3a..db168cc47 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -40,7 +40,7 @@
     @Feature({"Payments"})
     public void testSecondShowRequestCancelled()
             throws InterruptedException, ExecutionException, TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
         expectResultContains(new String[] {"Second request: AbortError: Request cancelled"});
 
         // The web payments UI was not aborted.
@@ -52,6 +52,6 @@
                         "PaymentRequest.CheckoutFunnel.NoShow",
                         PaymentRequestMetrics.NO_SHOW_CONCURRENT_REQUESTS));
 
-        clickAndWait(R.id.close_button, mDismissed);
+        clickAndWait(R.id.close_button, getDismissed());
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
index bf57d7c..3250176 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
@@ -47,8 +47,8 @@
     @Feature({"Payments"})
     public void testDismissOnTabSwitch() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        assertEquals(0, mDismissed.getCallCount());
+        triggerUIAndWait(getReadyForInput());
+        assertEquals(0, getDismissed().getCallCount());
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -56,7 +56,7 @@
                         new LoadUrlParams("about:blank"), TabLaunchType.FROM_CHROME_UI, null);
             }
         });
-        mDismissed.waitForCallback(0);
+        getDismissed().waitForCallback(0);
     }
 
     /** If the user closes the tab, the dialog is dismissed. */
@@ -66,8 +66,8 @@
     @DisabledTest
     public void testDismissOnTabClose() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        assertEquals(0, mDismissed.getCallCount());
+        triggerUIAndWait(getReadyForInput());
+        assertEquals(0, getDismissed().getCallCount());
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -75,7 +75,7 @@
                 TabModelUtils.closeCurrentTab(currentModel);
             }
         });
-        mDismissed.waitForCallback(0);
+        getDismissed().waitForCallback(0);
     }
 
     /** If the user navigates anywhere, the dialog is dismissed. */
@@ -83,8 +83,8 @@
     @Feature({"Payments"})
     public void testDismissOnTabNavigate() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyForInput);
-        assertEquals(0, mDismissed.getCallCount());
+        triggerUIAndWait(getReadyForInput());
+        assertEquals(0, getDismissed().getCallCount());
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -92,6 +92,6 @@
                 TabModelUtils.getCurrentTab(currentModel).loadUrl(new LoadUrlParams("about:blank"));
             }
         });
-        mDismissed.waitForCallback(0);
+        getDismissed().waitForCallback(0);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
index 7a2df3ee..6e4d27c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
@@ -4,214 +4,164 @@
 
 package org.chromium.chrome.browser.payments;
 
-import static java.util.Arrays.asList;
-
-import android.os.Handler;
-import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.Spinner;
 
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.base.test.util.UrlUtils;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.CardUnmaskPrompt;
-import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest;
-import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
-import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest;
-import org.chromium.chrome.browser.payments.ui.EditorTextField;
-import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection;
+import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.PaymentsCallbackHelper;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.OptionRow;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
-import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
-import org.chromium.content.browser.ContentViewCore;
-import org.chromium.content.browser.test.util.Criteria;
-import org.chromium.content.browser.test.util.CriteriaHelper;
-import org.chromium.content.browser.test.util.DOMUtils;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.payments.mojom.PaymentDetailsModifier;
-import org.chromium.payments.mojom.PaymentItem;
-import org.chromium.payments.mojom.PaymentMethodData;
 
-import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * A base integration test for payments.
  */
 @RetryOnFailure
 abstract class PaymentRequestTestBase extends ChromeActivityTestCaseBase<ChromeTabbedActivity>
-        implements PaymentRequestObserverForTest, PaymentRequestServiceObserverForTest,
-        CardUnmaskObserverForTest {
+        implements PaymentRequestTestCommon.PaymentRequestTestCommonCallback {
     /** Flag for installing a payment app without instruments. */
-    protected static final int NO_INSTRUMENTS = 0;
+    protected static final int NO_INSTRUMENTS = PaymentRequestTestCommon.NO_INSTRUMENTS;
 
     /** Flag for installing a payment app with instruments. */
-    protected static final int HAVE_INSTRUMENTS = 1;
+    protected static final int HAVE_INSTRUMENTS = PaymentRequestTestCommon.HAVE_INSTRUMENTS;
 
     /** Flag for installing a fast payment app. */
-    protected static final int IMMEDIATE_RESPONSE = 0;
+    protected static final int IMMEDIATE_RESPONSE = PaymentRequestTestCommon.IMMEDIATE_RESPONSE;
 
     /** Flag for installing a slow payment app. */
-    protected static final int DELAYED_RESPONSE = 1;
+    protected static final int DELAYED_RESPONSE = PaymentRequestTestCommon.DELAYED_RESPONSE;
 
     /** Flag for immediately installing a payment app. */
-    protected static final int IMMEDIATE_CREATION = 0;
+    protected static final int IMMEDIATE_CREATION = PaymentRequestTestCommon.IMMEDIATE_CREATION;
 
     /** Flag for installing a payment app with a delay. */
-    protected static final int DELAYED_CREATION = 1;
+    protected static final int DELAYED_CREATION = PaymentRequestTestCommon.DELAYED_CREATION;
 
     /** The expiration month dropdown index for December. */
-    protected static final int DECEMBER = 11;
+    protected static final int DECEMBER = PaymentRequestTestCommon.DECEMBER;
 
     /** The expiration year dropdown index for the next year. */
-    protected static final int NEXT_YEAR = 1;
+    protected static final int NEXT_YEAR = PaymentRequestTestCommon.NEXT_YEAR;
 
     /** The billing address dropdown index for the first billing address. */
-    protected static final int FIRST_BILLING_ADDRESS = 0;
+    protected static final int FIRST_BILLING_ADDRESS =
+            PaymentRequestTestCommon.FIRST_BILLING_ADDRESS;
 
-    protected final PaymentsCallbackHelper<PaymentRequestUI> mReadyForInput;
-    protected final PaymentsCallbackHelper<PaymentRequestUI> mReadyToPay;
-    protected final PaymentsCallbackHelper<PaymentRequestUI> mSelectionChecked;
-    protected final PaymentsCallbackHelper<PaymentRequestUI> mResultReady;
-    protected final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyForUnmaskInput;
-    protected final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyToUnmask;
-    protected final PaymentsCallbackHelper<CardUnmaskPrompt> mUnmaskValidationDone;
-    protected final CallbackHelper mReadyToEdit;
-    protected final CallbackHelper mEditorValidationError;
-    protected final CallbackHelper mEditorTextUpdate;
-    protected final CallbackHelper mDismissed;
-    protected final CallbackHelper mUnableToAbort;
-    protected final CallbackHelper mBillingAddressChangeProcessed;
-    protected final CallbackHelper mShowFailed;
-    protected final CallbackHelper mCanMakePaymentQueryResponded;
-    protected final CallbackHelper mExpirationMonthChange;
-    protected PaymentRequestUI mUI;
-
-    private final AtomicReference<ContentViewCore> mViewCoreRef;
-    private final AtomicReference<WebContents> mWebContentsRef;
-    private final String mTestFilePath;
-    private CardUnmaskPrompt mCardUnmaskPrompt;
+    private final PaymentRequestTestCommon mTestCommon;
 
     protected PaymentRequestTestBase(String testFileName) {
         super(ChromeTabbedActivity.class);
-        mReadyForInput = new PaymentsCallbackHelper<>();
-        mReadyToPay = new PaymentsCallbackHelper<>();
-        mSelectionChecked = new PaymentsCallbackHelper<>();
-        mResultReady = new PaymentsCallbackHelper<>();
-        mReadyForUnmaskInput = new PaymentsCallbackHelper<>();
-        mReadyToUnmask = new PaymentsCallbackHelper<>();
-        mUnmaskValidationDone = new PaymentsCallbackHelper<>();
-        mReadyToEdit = new CallbackHelper();
-        mEditorValidationError = new CallbackHelper();
-        mEditorTextUpdate = new CallbackHelper();
-        mDismissed = new CallbackHelper();
-        mUnableToAbort = new CallbackHelper();
-        mBillingAddressChangeProcessed = new CallbackHelper();
-        mExpirationMonthChange = new CallbackHelper();
-        mShowFailed = new CallbackHelper();
-        mCanMakePaymentQueryResponded = new CallbackHelper();
-        mViewCoreRef = new AtomicReference<>();
-        mWebContentsRef = new AtomicReference<>();
-        mTestFilePath = testFileName.startsWith("data:")
-                ? testFileName
-                : UrlUtils.getIsolatedTestFilePath(
-                          String.format("chrome/test/data/payments/%s", testFileName));
+        mTestCommon = new PaymentRequestTestCommon(this, testFileName);
+    }
+
+    public PaymentsCallbackHelper<PaymentRequestUI> getReadyForInput() {
+        return mTestCommon.mReadyForInput;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getReadyToPay() {
+        return mTestCommon.mReadyToPay;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getSelectionChecked() {
+        return mTestCommon.mSelectionChecked;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getResultReady() {
+        return mTestCommon.mResultReady;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getReadyForUnmaskInput() {
+        return mTestCommon.mReadyForUnmaskInput;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getReadyToUnmask() {
+        return mTestCommon.mReadyToUnmask;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getUnmaskValidationDone() {
+        return mTestCommon.mUnmaskValidationDone;
+    }
+    public CallbackHelper getReadyToEdit() {
+        return mTestCommon.mReadyToEdit;
+    }
+    public CallbackHelper getEditorValidationError() {
+        return mTestCommon.mEditorValidationError;
+    }
+    public CallbackHelper getEditorTextUpdate() {
+        return mTestCommon.mEditorTextUpdate;
+    }
+    public CallbackHelper getDismissed() {
+        return mTestCommon.mDismissed;
+    }
+    public CallbackHelper getUnableToAbort() {
+        return mTestCommon.mUnableToAbort;
+    }
+    public CallbackHelper getBillingAddressChangeProcessed() {
+        return mTestCommon.mBillingAddressChangeProcessed;
+    }
+    public CallbackHelper getShowFailed() {
+        return mTestCommon.mShowFailed;
+    }
+    public CallbackHelper getCanMakePaymentQueryResponded() {
+        return mTestCommon.mCanMakePaymentQueryResponded;
+    }
+    public CallbackHelper getExpirationMonthChange() {
+        return mTestCommon.mExpirationMonthChange;
+    }
+    public PaymentRequestUI getPaymentRequestUI() {
+        return mTestCommon.mUI;
     }
 
     @Override
     public void startMainActivity() throws InterruptedException {
-        startMainActivityWithURL(mTestFilePath);
+        mTestCommon.startMainActivity();
     }
 
-    protected abstract void onMainActivityStarted()
+    @Override
+    public abstract void onMainActivityStarted()
             throws InterruptedException, ExecutionException, TimeoutException;
 
     protected void triggerUIAndWait(PaymentsCallbackHelper<PaymentRequestUI> helper)
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("buy", helper);
-        mUI = helper.getTarget();
+        mTestCommon.triggerUIAndWait(helper);
     }
 
     protected void openPageAndClickBuyAndWait(CallbackHelper helper)
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait("buy", helper);
+        mTestCommon.openPageAndClickBuyAndWait(helper);
     }
 
     protected void triggerUIAndWait(String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPageAndClickNodeAndWait(nodeId, helper);
-        mUI = helper.getTarget();
+        mTestCommon.triggerUIAndWait(nodeId, helper);
     }
 
     protected void openPageAndClickNodeAndWait(String nodeId, CallbackHelper helper)
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPage();
-        clickNodeAndWait(nodeId, helper);
+        mTestCommon.openPageAndClickNodeAndWait(nodeId, helper);
     }
 
     protected void openPageAndClickNode(String nodeId)
             throws InterruptedException, ExecutionException, TimeoutException {
-        openPage();
-        DOMUtils.clickNode(mViewCoreRef.get(), nodeId);
-    }
-
-    private void openPage() throws InterruptedException, ExecutionException, TimeoutException {
-        onMainActivityStarted();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mViewCoreRef.set(getActivity().getCurrentContentViewCore());
-                mWebContentsRef.set(mViewCoreRef.get().getWebContents());
-                PaymentRequestUI.setObserverForTest(PaymentRequestTestBase.this);
-                PaymentRequestImpl.setObserverForTest(PaymentRequestTestBase.this);
-                CardUnmaskPrompt.setObserverForTest(PaymentRequestTestBase.this);
-            }
-        });
-        assertWaitForPageScaleFactorMatch(1);
+        mTestCommon.openPageAndClickNode(nodeId);
     }
 
     protected void reTriggerUIAndWait(
             String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
-            throws InterruptedException, ExecutionException, TimeoutException {
-        clickNodeAndWait(nodeId, helper);
-        mUI = helper.getTarget();
+            throws InterruptedException, TimeoutException {
+        mTestCommon.reTriggerUIAndWait(nodeId, helper);
     }
 
     /** Clicks on an HTML node. */
     protected void clickNodeAndWait(String nodeId, CallbackHelper helper)
-            throws InterruptedException, ExecutionException, TimeoutException {
-        int callCount = helper.getCallCount();
-        DOMUtils.clickNode(mViewCoreRef.get(), nodeId);
-        helper.waitForCallback(callCount);
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickNodeAndWait(nodeId, helper);
     }
 
     /** Clicks on an element in the payments UI. */
     protected void clickAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getDialogForTest().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickAndWait(resourceId, helper);
     }
 
     /**
@@ -221,138 +171,63 @@
      */
     protected void clickInShippingSummaryAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getShippingSummarySectionForTest().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInShippingSummaryAndWait(resourceId, helper);
     }
 
     /** Clicks on an element in the "Shipping address" section of the payments UI. */
     protected void clickInShippingAddressAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getShippingAddressSectionForTest().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInShippingAddressAndWait(resourceId, helper);
     }
 
     /** Clicks on an element in the "Payment" section of the payments UI. */
     protected void clickInPaymentMethodAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getPaymentMethodSectionForTest().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInPaymentMethodAndWait(resourceId, helper);
     }
 
     /** Clicks on an element in the "Contact Info" section of the payments UI. */
     protected void clickInContactInfoAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getContactDetailsSectionForTest().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInContactInfoAndWait(resourceId, helper);
     }
 
     /** Clicks on an element in the editor UI for credit cards. */
     protected void clickInCardEditorAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getCardEditorView().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInCardEditorAndWait(resourceId, helper);
     }
 
     /** Clicks on an element in the editor UI. */
     protected void clickInEditorAndWait(final int resourceId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getEditorView().findViewById(resourceId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickInEditorAndWait(resourceId, helper);
     }
 
     protected void clickAndroidBackButtonInEditorAndWait(CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mUI.getEditorView().dispatchKeyEvent(
-                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
-                mUI.getEditorView().dispatchKeyEvent(
-                        new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickAndroidBackButtonInEditorAndWait(helper);
     }
 
     /** Clicks on a button in the card unmask UI. */
     protected void clickCardUnmaskButtonAndWait(final int dialogButtonId, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                mCardUnmaskPrompt.getDialogForTest().getButton(dialogButtonId).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickCardUnmaskButtonAndWait(dialogButtonId, helper);
     }
 
     /** Gets the button state for the shipping summary section. */
     protected int getSummarySectionButtonState() throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return mUI.getShippingSummarySectionForTest().getEditButtonState();
-            }
-        });
+        return mTestCommon.getSummarySectionButtonState();
     }
 
     /** Gets the button state for the contact details section. */
     protected int getContactDetailsButtonState() throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return mUI.getContactDetailsSectionForTest().getEditButtonState();
-            }
-        });
+        return mTestCommon.getContactDetailsButtonState();
     }
 
     /**  Returns the label corresponding to the payment instrument at the specified |index|. */
     protected String getPaymentInstrumentLabel(final int index) throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
-            @Override
-            public String call() {
-                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
-                        .getOptionLabelsForTest(index).getText().toString();
-            }
-        });
+        return mTestCommon.getPaymentInstrumentLabel(index);
     }
 
     /**
@@ -361,35 +236,17 @@
      */
     protected String getContactDetailsSuggestionLabel(final int suggestionIndex)
             throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
-            @Override
-            public String call() {
-                return ((OptionSection) mUI.getContactDetailsSectionForTest())
-                        .getOptionLabelsForTest(suggestionIndex).getText().toString();
-            }
-        });
+        return mTestCommon.getContactDetailsSuggestionLabel(suggestionIndex);
     }
 
     /**  Returns the number of payment instruments. */
     protected int getNumberOfPaymentInstruments() throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
-                        .getNumberOfOptionLabelsForTest();
-            }
-        });
+        return mTestCommon.getNumberOfPaymentInstruments();
     }
 
     /**  Returns the number of contact detail suggestions. */
     protected int getNumberOfContactDetailSuggestions() throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return ((OptionSection) mUI.getContactDetailsSectionForTest())
-                        .getNumberOfOptionLabelsForTest();
-            }
-        });
+        return mTestCommon.getNumberOfContactDetailSuggestions();
     }
 
     /**
@@ -398,20 +255,12 @@
      */
     protected String getShippingAddressSuggestionLabel(final int suggestionIndex)
             throws ExecutionException {
-        assert (suggestionIndex < getNumberOfShippingAddressSuggestions());
-
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
-            @Override
-            public String call() {
-                return ((OptionSection) mUI.getShippingAddressSectionForTest())
-                        .getOptionLabelsForTest(suggestionIndex).getText().toString();
-            }
-        });
+        return mTestCommon.getShippingAddressSuggestionLabel(suggestionIndex);
     }
 
     /** Returns the focused view in the card editor view. */
     protected View getCardEditorFocusedView() {
-        return mUI.getCardEditorView().getCurrentFocus();
+        return mTestCommon.getCardEditorFocusedView();
     }
 
     /**
@@ -422,17 +271,7 @@
     protected void clickOnShippingAddressSuggestionOptionAndWait(
             final int suggestionIndex, CallbackHelper helper)
                     throws ExecutionException, TimeoutException, InterruptedException {
-        assert (suggestionIndex < getNumberOfShippingAddressSuggestions());
-
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ((OptionSection) mUI.getShippingAddressSectionForTest())
-                        .getOptionLabelsForTest(suggestionIndex).performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickOnShippingAddressSuggestionOptionAndWait(suggestionIndex, helper);
     }
 
     /**
@@ -443,18 +282,7 @@
     protected void clickOnPaymentMethodSuggestionOptionAndWait(
             final int suggestionIndex, CallbackHelper helper)
             throws ExecutionException, TimeoutException, InterruptedException {
-        assert (suggestionIndex < getNumberOfPaymentInstruments());
-
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ((OptionSection) mUI.getPaymentMethodSectionForTest())
-                        .getOptionLabelsForTest(suggestionIndex)
-                        .performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickOnPaymentMethodSuggestionOptionAndWait(suggestionIndex, helper);
     }
 
     /**
@@ -464,281 +292,106 @@
     protected void clickOnPaymentMethodSuggestionEditIconAndWait(
             final int suggestionIndex, CallbackHelper helper)
             throws ExecutionException, TimeoutException, InterruptedException {
-        assert (suggestionIndex < getNumberOfPaymentInstruments());
-
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ((OptionSection) mUI.getPaymentMethodSectionForTest())
-                        .getOptionRowAtIndex(suggestionIndex)
-                        .getEditIconForTest()
-                        .performClick();
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.clickOnPaymentMethodSuggestionEditIconAndWait(suggestionIndex, helper);
     }
 
     /**
      *  Returns the the number of shipping address suggestions.
      */
     protected int getNumberOfShippingAddressSuggestions() throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return ((OptionSection) mUI.getShippingAddressSectionForTest())
-                        .getNumberOfOptionLabelsForTest();
-            }
-        });
+        return mTestCommon.getNumberOfShippingAddressSuggestions();
     }
 
     /** Returns the {@link OptionRow} at the given index for the shipping address section. */
     protected OptionRow getShippingAddressOptionRowAtIndex(final int index)
             throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<OptionRow>() {
-            @Override
-            public OptionRow call() {
-                return ((OptionSection) mUI.getShippingAddressSectionForTest())
-                        .getOptionRowAtIndex(index);
-            }
-        });
+        return mTestCommon.getShippingAddressOptionRowAtIndex(index);
     }
 
     /** Returns the selected spinner value in the editor UI for credit cards. */
     protected String getSpinnerSelectionTextInCardEditor(final int dropdownIndex)
              throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
-            @Override
-            public String call() {
-                return mUI.getCardEditorView().getDropdownFieldsForTest().get(dropdownIndex)
-                        .getSelectedItem().toString();
-            }
-        });
+        return mTestCommon.getSpinnerSelectionTextInCardEditor(dropdownIndex);
     }
 
     /** Returns the spinner value at the specified position in the editor UI for credit cards. */
     protected String getSpinnerTextAtPositionInCardEditor(
             final int dropdownIndex, final int itemPosition) throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
-            @Override
-            public String call() {
-                return mUI.getCardEditorView()
-                        .getDropdownFieldsForTest()
-                        .get(dropdownIndex)
-                        .getItemAtPosition(itemPosition)
-                        .toString();
-            }
-        });
+        return mTestCommon.getSpinnerTextAtPositionInCardEditor(dropdownIndex, itemPosition);
     }
 
     /** Returns the number of items offered by the spinner in the editor UI for credit cards. */
     protected int getSpinnerItemCountInCardEditor(final int dropdownIndex)
             throws ExecutionException {
-        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
-            @Override
-            public Integer call() {
-                return mUI.getCardEditorView().getDropdownFieldsForTest().get(dropdownIndex)
-                        .getCount();
-            }
-        });
+        return mTestCommon.getSpinnerItemCountInCardEditor(dropdownIndex);
     }
 
     /** Returns the error message visible to the user in the credit card unmask prompt. */
     protected String getUnmaskPromptErrorMessage() {
-        return mCardUnmaskPrompt.getErrorMessage();
+        return mTestCommon.getUnmaskPromptErrorMessage();
     }
 
     /** Selects the spinner value in the editor UI for credit cards. */
     protected void setSpinnerSelectionsInCardEditorAndWait(final int[] selections,
             CallbackHelper helper) throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                List<Spinner> fields = mUI.getCardEditorView().getDropdownFieldsForTest();
-                for (int i = 0; i < selections.length && i < fields.size(); i++) {
-                    fields.get(i).setSelection(selections[i]);
-                }
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setSpinnerSelectionsInCardEditorAndWait(selections, helper);
     }
 
     /** Selects the spinner value in the editor UI. */
     protected void setSpinnerSelectionInEditorAndWait(final int selection, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ((Spinner) mUI.getEditorView().findViewById(R.id.spinner)).setSelection(selection);
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setSpinnerSelectionInEditorAndWait(selection, helper);
     }
 
     /** Directly sets the text in the editor UI for credit cards. */
     protected void setTextInCardEditorAndWait(final String[] values, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ViewGroup contents = (ViewGroup)
-                        mUI.getCardEditorView().findViewById(R.id.contents);
-                assertNotNull(contents);
-                for (int i = 0, j = 0; i < contents.getChildCount() && j < values.length; i++) {
-                    View view = contents.getChildAt(i);
-                    if (view instanceof EditorTextField) {
-                        ((EditorTextField) view).getEditText().setText(values[j++]);
-                    }
-                }
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setTextInCardEditorAndWait(values, helper);
     }
 
     /** Directly sets the text in the editor UI. */
     protected void setTextInEditorAndWait(final String[] values, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                List<EditText> fields = mUI.getEditorView().getEditableTextFieldsForTest();
-                for (int i = 0; i < values.length; i++) {
-                    fields.get(i).setText(values[i]);
-                }
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setTextInEditorAndWait(values, helper);
     }
 
     /** Directly sets the checkbox selection in the editor UI for credit cards. */
     protected void selectCheckboxAndWait(final int resourceId, final boolean isChecked,
             CallbackHelper helper) throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                ((CheckBox) mUI.getCardEditorView().findViewById(resourceId)).setChecked(isChecked);
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.selectCheckboxAndWait(resourceId, isChecked, helper);
     }
 
     /** Directly sets the text in the card unmask UI. */
     protected void setTextInCardUnmaskDialogAndWait(final int resourceId, final String input,
             CallbackHelper helper) throws InterruptedException, TimeoutException {
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                EditText editText =
-                        ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId));
-                editText.setText(input);
-                editText.getOnFocusChangeListener().onFocusChange(null, false);
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setTextInCardUnmaskDialogAndWait(resourceId, input, helper);
     }
 
     /** Directly sets the text in the expired card unmask UI. */
     protected void setTextInExpiredCardUnmaskDialogAndWait(
             final int[] resourceIds, final String[] values, CallbackHelper helper)
             throws InterruptedException, TimeoutException {
-        assert resourceIds.length == values.length;
-        int callCount = helper.getCallCount();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                for (int i = 0; i < resourceIds.length; ++i) {
-                    EditText editText = ((EditText) mCardUnmaskPrompt.getDialogForTest()
-                            .findViewById(resourceIds[i]));
-                    editText.setText(values[i]);
-                    editText.getOnFocusChangeListener().onFocusChange(null, false);
-                }
-            }
-        });
-        helper.waitForCallback(callCount);
+        mTestCommon.setTextInExpiredCardUnmaskDialogAndWait(resourceIds, values, helper);
     }
 
     /** Verifies the contents of the test webpage. */
     protected void expectResultContains(final String[] contents) {
-        CriteriaHelper.pollInstrumentationThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                try {
-                    String result = DOMUtils.getNodeContents(mWebContentsRef.get(), "result");
-                    if (result == null) {
-                        updateFailureReason("Cannot find 'result' node on test page");
-                        return false;
-                    }
-                    for (int i = 0; i < contents.length; i++) {
-                        if (!result.contains(contents[i])) {
-                            updateFailureReason(
-                                    String.format("Result should contain '%s'", contents[i]));
-                            return false;
-                        }
-                    }
-                    return true;
-                } catch (InterruptedException e1) {
-                    updateFailureReason(e1.getMessage());
-                    return false;
-                } catch (TimeoutException e2) {
-                    updateFailureReason(e2.getMessage());
-                    return false;
-                }
-            }
-        });
+        mTestCommon.expectResultContains(contents);
     }
 
     /**  Will fail if the OptionRow at |index| is not selected in Contact Details.*/
     protected void expectContactDetailsRowIsSelected(final int index) {
-        CriteriaHelper.pollInstrumentationThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                boolean isSelected = ((OptionSection) mUI.getContactDetailsSectionForTest())
-                                             .getOptionRowAtIndex(index)
-                                             .isChecked();
-                if (!isSelected) {
-                    updateFailureReason("Contact Details row at " + index + " was not selected.");
-                }
-                return isSelected;
-            }
-        });
+        mTestCommon.expectContactDetailsRowIsSelected(index);
     }
 
     /**  Will fail if the OptionRow at |index| is not selected in Shipping Address section.*/
     protected void expectShippingAddressRowIsSelected(final int index) {
-        CriteriaHelper.pollInstrumentationThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                boolean isSelected = ((OptionSection) mUI.getShippingAddressSectionForTest())
-                                             .getOptionRowAtIndex(index)
-                                             .isChecked();
-                if (!isSelected) {
-                    updateFailureReason("Shipping Address row at " + index + " was not selected.");
-                }
-                return isSelected;
-            }
-        });
+        mTestCommon.expectShippingAddressRowIsSelected(index);
     }
 
     /**  Will fail if the OptionRow at |index| is not selected in PaymentMethod section.*/
     protected void expectPaymentMethodRowIsSelected(final int index) {
-        CriteriaHelper.pollInstrumentationThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                boolean isSelected = ((OptionSection) mUI.getPaymentMethodSectionForTest())
-                                             .getOptionRowAtIndex(index)
-                                             .isChecked();
-                if (!isSelected) {
-                    updateFailureReason("Payment Method row at " + index + " was not selected.");
-                }
-                return isSelected;
-            }
-        });
+        mTestCommon.expectPaymentMethodRowIsSelected(index);
     }
 
     /**
@@ -747,138 +400,73 @@
      * @param abortReason The only bucket in the abort histogram that should have a record.
      */
     protected void assertOnlySpecificAbortMetricLogged(int abortReason) {
-        for (int i = 0; i < PaymentRequestMetrics.ABORT_REASON_MAX; ++i) {
-            assertEquals(
-                    String.format(Locale.getDefault(), "Found %d instead of %d", i, abortReason),
-                    (i == abortReason ? 1 : 0),
-                    RecordHistogram.getHistogramValueCountForTesting(
-                            "PaymentRequest.CheckoutFunnel.Aborted", i));
-        }
+        mTestCommon.assertOnlySpecificAbortMetricLogged(abortReason);
     }
 
-    @Override
     public void onPaymentRequestReadyForInput(PaymentRequestUI ui) {
-        ThreadUtils.assertOnUiThread();
-        mReadyForInput.notifyCalled(ui);
+        mTestCommon.onPaymentRequestReadyForInput(ui);
     }
 
-    @Override
     public void onPaymentRequestReadyToEdit() {
-        ThreadUtils.assertOnUiThread();
-        mReadyToEdit.notifyCalled();
+        mTestCommon.onPaymentRequestReadyToEdit();
     }
 
-    @Override
     public void onPaymentRequestEditorValidationError() {
-        ThreadUtils.assertOnUiThread();
-        mEditorValidationError.notifyCalled();
+        mTestCommon.onPaymentRequestEditorValidationError();
     }
 
-    @Override
     public void onPaymentRequestEditorTextUpdate() {
-        ThreadUtils.assertOnUiThread();
-        mEditorTextUpdate.notifyCalled();
+        mTestCommon.onPaymentRequestEditorTextUpdate();
     }
 
-    @Override
     public void onPaymentRequestReadyToPay(PaymentRequestUI ui) {
-        ThreadUtils.assertOnUiThread();
-        mReadyToPay.notifyCalled(ui);
+        mTestCommon.onPaymentRequestReadyToPay(ui);
     }
 
-    @Override
     public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {
-        ThreadUtils.assertOnUiThread();
-        mSelectionChecked.notifyCalled(ui);
+        mTestCommon.onPaymentRequestSelectionChecked(ui);
     }
 
-    @Override
     public void onPaymentRequestResultReady(PaymentRequestUI ui) {
-        ThreadUtils.assertOnUiThread();
-        mResultReady.notifyCalled(ui);
+        mTestCommon.onPaymentRequestResultReady(ui);
     }
 
-    @Override
     public void onPaymentRequestDismiss() {
-        ThreadUtils.assertOnUiThread();
-        mDismissed.notifyCalled();
+        mTestCommon.onPaymentRequestDismiss();
     }
 
-    @Override
     public void onPaymentRequestServiceUnableToAbort() {
-        ThreadUtils.assertOnUiThread();
-        mUnableToAbort.notifyCalled();
+        mTestCommon.onPaymentRequestServiceUnableToAbort();
     }
 
-    @Override
     public void onPaymentRequestServiceBillingAddressChangeProcessed() {
-        ThreadUtils.assertOnUiThread();
-        mBillingAddressChangeProcessed.notifyCalled();
+        mTestCommon.onPaymentRequestServiceBillingAddressChangeProcessed();
     }
 
-    @Override
     public void onPaymentRequestServiceExpirationMonthChange() {
-        ThreadUtils.assertOnUiThread();
-        mExpirationMonthChange.notifyCalled();
+        mTestCommon.onPaymentRequestServiceExpirationMonthChange();
     }
 
-    @Override
     public void onPaymentRequestServiceShowFailed() {
-        ThreadUtils.assertOnUiThread();
-        mShowFailed.notifyCalled();
+        mTestCommon.onPaymentRequestServiceShowFailed();
     }
 
-    @Override
     public void onPaymentRequestServiceCanMakePaymentQueryResponded() {
-        ThreadUtils.assertOnUiThread();
-        mCanMakePaymentQueryResponded.notifyCalled();
+        mTestCommon.onPaymentRequestServiceCanMakePaymentQueryResponded();
     }
 
-    @Override
     public void onCardUnmaskPromptReadyForInput(CardUnmaskPrompt prompt) {
-        ThreadUtils.assertOnUiThread();
-        mReadyForUnmaskInput.notifyCalled(prompt);
-        mCardUnmaskPrompt = prompt;
+        mTestCommon.onCardUnmaskPromptReadyForInput(prompt);
     }
 
-    @Override
     public void onCardUnmaskPromptReadyToUnmask(CardUnmaskPrompt prompt) {
-        ThreadUtils.assertOnUiThread();
-        mReadyToUnmask.notifyCalled(prompt);
+        mTestCommon.onCardUnmaskPromptReadyToUnmask(prompt);
     }
 
-    @Override
     public void onCardUnmaskPromptValidationDone(CardUnmaskPrompt prompt) {
-        ThreadUtils.assertOnUiThread();
-        mUnmaskValidationDone.notifyCalled(prompt);
+        mTestCommon.onCardUnmaskPromptValidationDone(prompt);
     }
 
-    /**
-     * Listens for UI notifications.
-     */
-    protected static class PaymentsCallbackHelper<T> extends CallbackHelper {
-        private T mTarget;
-
-        /**
-         * Returns the UI that is ready for input.
-         *
-         * @return The UI that is ready for input.
-         */
-        public T getTarget() {
-            return mTarget;
-        }
-
-        /**
-         * Called when the UI is ready for input.
-         *
-         * @param target The UI that is ready for input.
-         */
-        public void notifyCalled(T target) {
-            ThreadUtils.assertOnUiThread();
-            mTarget = target;
-            notifyCalled();
-        }
-    }
 
     /**
      * Installs a payment app for testing.
@@ -889,7 +477,7 @@
      *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
      */
     protected void installPaymentApp(int instrumentPresence, int responseSpeed) {
-        installPaymentApp("https://bobpay.com", instrumentPresence, responseSpeed);
+        mTestCommon.installPaymentApp(instrumentPresence, responseSpeed);
     }
 
     /**
@@ -902,7 +490,7 @@
      *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
      */
     protected void installPaymentApp(String methodName, int instrumentPresence, int responseSpeed) {
-        installPaymentApp(methodName, instrumentPresence, responseSpeed, IMMEDIATE_CREATION);
+        mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed);
     }
 
     /**
@@ -918,123 +506,22 @@
      */
     protected void installPaymentApp(
             String methodName, int instrumentPresence, int responseSpeed, int creationSpeed) {
-        installPaymentApp(asList(methodName), instrumentPresence, responseSpeed, creationSpeed);
+        mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed, creationSpeed);
     }
 
     protected void installPaymentApp(final List<String> appMethodNames,
             final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
-        PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
-            @Override
-            public void create(WebContents webContents, Set<String> methodNames,
-                    final PaymentAppFactory.PaymentAppCreatedCallback callback) {
-                final TestPay app = new TestPay(appMethodNames, instrumentPresence, responseSpeed);
-                if (creationSpeed == IMMEDIATE_CREATION) {
-                    callback.onPaymentAppCreated(app);
-                    callback.onAllPaymentAppsCreated();
-                } else {
-                    new Handler().postDelayed(new Runnable() {
-                        @Override
-                        public void run() {
-                            callback.onPaymentAppCreated(app);
-                            callback.onAllPaymentAppsCreated();
-                        }
-                    }, 100);
-                }
-            }
-        });
+        mTestCommon.installPaymentApp(
+                appMethodNames, instrumentPresence, responseSpeed, creationSpeed);
     }
 
-    /** A payment app implementation for test. */
-    protected static class TestPay implements PaymentApp {
-        private final List<String> mMethodNames;
-        private final int mInstrumentPresence;
-        private final int mResponseSpeed;
-        private InstrumentsCallback mCallback;
-
-        TestPay(List<String> methodNames, int instrumentPresence, int responseSpeed) {
-            mMethodNames = methodNames;
-            mInstrumentPresence = instrumentPresence;
-            mResponseSpeed = responseSpeed;
-        }
-
-        @Override
-        public void getInstruments(Map<String, PaymentMethodData> methodData, String origin,
-                String iframeOrigin, byte[][] certificateChain, PaymentItem total,
-                InstrumentsCallback instrumentsCallback) {
-            mCallback = instrumentsCallback;
-            respond();
-        }
-
-        void respond() {
-            final List<PaymentInstrument> instruments = new ArrayList<>();
-            if (mInstrumentPresence == HAVE_INSTRUMENTS) {
-                for (String methodName : mMethodNames) {
-                    instruments.add(
-                            new TestPayInstrument(getAppIdentifier(), methodName, methodName));
-                }
-            }
-            Runnable instrumentsReady = new Runnable() {
-                @Override
-                public void run() {
-                    ThreadUtils.assertOnUiThread();
-                    mCallback.onInstrumentsReady(TestPay.this, instruments);
-                }
-            };
-            if (mResponseSpeed == IMMEDIATE_RESPONSE) {
-                instrumentsReady.run();
-            } else if (mResponseSpeed == DELAYED_RESPONSE) {
-                new Handler().postDelayed(instrumentsReady, 100);
-            }
-        }
-
-        @Override
-        public Set<String> getAppMethodNames() {
-            Set<String> methodNames = new HashSet<>();
-            methodNames.addAll(mMethodNames);
-            return methodNames;
-        }
-
-        @Override
-        public boolean supportsMethodsAndData(Map<String, PaymentMethodData> methodsAndData) {
-            assert methodsAndData != null;
-            Set<String> methodNames = new HashSet<>(methodsAndData.keySet());
-            methodNames.retainAll(getAppMethodNames());
-            return !methodNames.isEmpty();
-        }
-
-        @Override
-        public String getAppIdentifier() {
-            return TestPay.this.toString();
-        }
+    @Override
+    public void startMainActivityWithURL(String url) throws InterruptedException {
+        super.startMainActivityWithURL(url);
     }
 
-    /** A payment instrument implementation for test. */
-    private static class TestPayInstrument extends PaymentInstrument {
-        private final String mMethodName;
-
-        TestPayInstrument(String appId, String methodName, String label) {
-            super(appId + methodName, label, null, null);
-            mMethodName = methodName;
-        }
-
-        @Override
-        public Set<String> getInstrumentMethodNames() {
-            Set<String> result = new HashSet<>();
-            result.add(mMethodName);
-            return result;
-        }
-
-        @Override
-        public void invokePaymentApp(String id, String merchantName, String origin,
-                String iframeOrigin, byte[][] certificateChain,
-                Map<String, PaymentMethodData> methodData, PaymentItem total,
-                List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers,
-                InstrumentDetailsCallback detailsCallback) {
-            detailsCallback.onInstrumentDetailsReady(
-                    mMethodName, "{\"transaction\": 1337}");
-        }
-
-        @Override
-        public void dismissInstrument() {}
+    @Override
+    public void assertWaitForPageScaleFactorMatch(float expectedScale) {
+        super.assertWaitForPageScaleFactorMatch(expectedScale);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
new file mode 100644
index 0000000..56a1603
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
@@ -0,0 +1,965 @@
+// 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.
+
+package org.chromium.chrome.browser.payments;
+
+import static java.util.Arrays.asList;
+
+import android.os.Handler;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.Spinner;
+
+import org.junit.Assert;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.UrlUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.autofill.CardUnmaskPrompt;
+import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest;
+import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppFactoryAddition;
+import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest;
+import org.chromium.chrome.browser.payments.ui.EditorTextField;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.OptionRow;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+import org.chromium.content.browser.test.util.DOMUtils;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.payments.mojom.PaymentDetailsModifier;
+import org.chromium.payments.mojom.PaymentItem;
+import org.chromium.payments.mojom.PaymentMethodData;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+// TODO(yolandyan): move this class to its test rule once JUnit4 migration is over
+final class PaymentRequestTestCommon implements PaymentRequestObserverForTest,
+                                                PaymentRequestServiceObserverForTest,
+                                                CardUnmaskObserverForTest {
+    /** Flag for installing a payment app without instruments. */
+    static final int NO_INSTRUMENTS = 0;
+
+    /** Flag for installing a payment app with instruments. */
+    static final int HAVE_INSTRUMENTS = 1;
+
+    /** Flag for installing a fast payment app. */
+    static final int IMMEDIATE_RESPONSE = 0;
+
+    /** Flag for installing a slow payment app. */
+    static final int DELAYED_RESPONSE = 1;
+
+    /** Flag for immediately installing a payment app. */
+    static final int IMMEDIATE_CREATION = 0;
+
+    /** Flag for installing a payment app with a delay. */
+    static final int DELAYED_CREATION = 1;
+
+    /** The expiration month dropdown index for December. */
+    static final int DECEMBER = 11;
+
+    /** The expiration year dropdown index for the next year. */
+    static final int NEXT_YEAR = 1;
+
+    /** The billing address dropdown index for the first billing address. */
+    static final int FIRST_BILLING_ADDRESS = 0;
+
+    final PaymentsCallbackHelper<PaymentRequestUI> mReadyForInput;
+    final PaymentsCallbackHelper<PaymentRequestUI> mReadyToPay;
+    final PaymentsCallbackHelper<PaymentRequestUI> mSelectionChecked;
+    final PaymentsCallbackHelper<PaymentRequestUI> mResultReady;
+    final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyForUnmaskInput;
+    final PaymentsCallbackHelper<CardUnmaskPrompt> mReadyToUnmask;
+    final PaymentsCallbackHelper<CardUnmaskPrompt> mUnmaskValidationDone;
+    final CallbackHelper mReadyToEdit;
+    final CallbackHelper mEditorValidationError;
+    final CallbackHelper mEditorTextUpdate;
+    final CallbackHelper mDismissed;
+    final CallbackHelper mUnableToAbort;
+    final CallbackHelper mBillingAddressChangeProcessed;
+    final CallbackHelper mShowFailed;
+    final CallbackHelper mCanMakePaymentQueryResponded;
+    final CallbackHelper mExpirationMonthChange;
+    PaymentRequestUI mUI;
+
+    private final AtomicReference<ContentViewCore> mViewCoreRef;
+
+    private final AtomicReference<WebContents> mWebContentsRef;
+
+    private final String mTestFilePath;
+
+    private CardUnmaskPrompt mCardUnmaskPrompt;
+
+    private final PaymentRequestTestCommonCallback mCallback;
+
+    PaymentRequestTestCommon(PaymentRequestTestCommonCallback callback, String testFileName) {
+        mCallback = callback;
+        mReadyForInput = new PaymentsCallbackHelper<>();
+        mReadyToPay = new PaymentsCallbackHelper<>();
+        mSelectionChecked = new PaymentsCallbackHelper<>();
+        mResultReady = new PaymentsCallbackHelper<>();
+        mReadyForUnmaskInput = new PaymentsCallbackHelper<>();
+        mReadyToUnmask = new PaymentsCallbackHelper<>();
+        mUnmaskValidationDone = new PaymentsCallbackHelper<>();
+        mReadyToEdit = new CallbackHelper();
+        mEditorValidationError = new CallbackHelper();
+        mEditorTextUpdate = new CallbackHelper();
+        mDismissed = new CallbackHelper();
+        mUnableToAbort = new CallbackHelper();
+        mBillingAddressChangeProcessed = new CallbackHelper();
+        mExpirationMonthChange = new CallbackHelper();
+        mShowFailed = new CallbackHelper();
+        mCanMakePaymentQueryResponded = new CallbackHelper();
+        mViewCoreRef = new AtomicReference<>();
+        mWebContentsRef = new AtomicReference<>();
+        mTestFilePath = testFileName.startsWith("data:")
+                ? testFileName : UrlUtils.getIsolatedTestFilePath(
+                        String.format("chrome/test/data/payments/%s", testFileName));
+    }
+
+    public void startMainActivity() throws InterruptedException {
+        mCallback.startMainActivityWithURL(mTestFilePath);
+    }
+
+    private void openPage() throws InterruptedException, ExecutionException, TimeoutException {
+        mCallback.onMainActivityStarted();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mViewCoreRef.set(mCallback.getActivity().getCurrentContentViewCore());
+                mWebContentsRef.set(mViewCoreRef.get().getWebContents());
+                PaymentRequestUI.setObserverForTest(PaymentRequestTestCommon.this);
+                PaymentRequestImpl.setObserverForTest(PaymentRequestTestCommon.this);
+                CardUnmaskPrompt.setObserverForTest(PaymentRequestTestCommon.this);
+            }
+        });
+        mCallback.assertWaitForPageScaleFactorMatch(1);
+    }
+
+    protected void triggerUIAndWait(PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        openPageAndClickNodeAndWait("buy", helper);
+        mUI = helper.getTarget();
+    }
+
+    protected void openPageAndClickNodeAndWait(String nodeId, CallbackHelper helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        openPage();
+        clickNodeAndWait(nodeId, helper);
+    }
+
+    protected void openPageAndClickBuyAndWait(CallbackHelper helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        openPageAndClickNodeAndWait("buy", helper);
+    }
+
+    protected void openPageAndClickNode(String nodeId)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        openPage();
+        DOMUtils.clickNode(mViewCoreRef.get(), nodeId);
+    }
+
+    protected void triggerUIAndWait(String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        openPageAndClickNodeAndWait(nodeId, helper);
+        mUI = helper.getTarget();
+    }
+
+    protected void reTriggerUIAndWait(
+            String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, TimeoutException {
+        clickNodeAndWait(nodeId, helper);
+        mUI = helper.getTarget();
+    }
+
+    protected void clickNodeAndWait(String nodeId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        DOMUtils.clickNode(mViewCoreRef.get(), nodeId);
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getDialogForTest().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInShippingSummaryAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getShippingSummarySectionForTest().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInShippingAddressAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getShippingAddressSectionForTest().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInPaymentMethodAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getPaymentMethodSectionForTest().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInContactInfoAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getContactDetailsSectionForTest().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInCardEditorAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getCardEditorView().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickInEditorAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getEditorView().findViewById(resourceId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickAndroidBackButtonInEditorAndWait(CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUI.getEditorView().dispatchKeyEvent(
+                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
+                mUI.getEditorView().dispatchKeyEvent(
+                        new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickCardUnmaskButtonAndWait(final int dialogButtonId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mCardUnmaskPrompt.getDialogForTest().getButton(dialogButtonId).performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected int getSummarySectionButtonState() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return mUI.getShippingSummarySectionForTest().getEditButtonState();
+            }
+        });
+    }
+
+    protected int getContactDetailsButtonState() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return mUI.getContactDetailsSectionForTest().getEditButtonState();
+            }
+        });
+    }
+
+    protected String getPaymentInstrumentLabel(final int index) throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
+            @Override
+            public String call() {
+                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getOptionLabelsForTest(index)
+                        .getText()
+                        .toString();
+            }
+        });
+    }
+
+    protected String getContactDetailsSuggestionLabel(final int suggestionIndex)
+            throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
+            @Override
+            public String call() {
+                return ((OptionSection) mUI.getContactDetailsSectionForTest())
+                        .getOptionLabelsForTest(suggestionIndex)
+                        .getText()
+                        .toString();
+            }
+        });
+    }
+
+    protected int getNumberOfPaymentInstruments() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getNumberOfOptionLabelsForTest();
+            }
+        });
+    }
+
+    protected int getNumberOfContactDetailSuggestions() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return ((OptionSection) mUI.getContactDetailsSectionForTest())
+                        .getNumberOfOptionLabelsForTest();
+            }
+        });
+    }
+
+    protected String getShippingAddressSuggestionLabel(final int suggestionIndex)
+            throws ExecutionException {
+        Assert.assertTrue(suggestionIndex < getNumberOfShippingAddressSuggestions());
+
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
+            @Override
+            public String call() {
+                return ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getOptionLabelsForTest(suggestionIndex)
+                        .getText()
+                        .toString();
+            }
+        });
+    }
+
+    protected View getCardEditorFocusedView() {
+        return mUI.getCardEditorView().getCurrentFocus();
+    }
+
+    protected void clickOnShippingAddressSuggestionOptionAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        Assert.assertTrue(suggestionIndex < getNumberOfShippingAddressSuggestions());
+
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getOptionLabelsForTest(suggestionIndex)
+                        .performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickOnPaymentMethodSuggestionOptionAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        Assert.assertTrue(suggestionIndex < getNumberOfPaymentInstruments());
+
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getOptionLabelsForTest(suggestionIndex)
+                        .performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void clickOnPaymentMethodSuggestionEditIconAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        Assert.assertTrue(suggestionIndex < getNumberOfPaymentInstruments());
+
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                        .getOptionRowAtIndex(suggestionIndex)
+                        .getEditIconForTest()
+                        .performClick();
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected int getNumberOfShippingAddressSuggestions() throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getNumberOfOptionLabelsForTest();
+            }
+        });
+    }
+
+    protected OptionRow getShippingAddressOptionRowAtIndex(final int index)
+            throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<OptionRow>() {
+            @Override
+            public OptionRow call() {
+                return ((OptionSection) mUI.getShippingAddressSectionForTest())
+                        .getOptionRowAtIndex(index);
+            }
+        });
+    }
+
+    protected String getSpinnerSelectionTextInCardEditor(final int dropdownIndex)
+            throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
+            @Override
+            public String call() {
+                return mUI.getCardEditorView()
+                        .getDropdownFieldsForTest()
+                        .get(dropdownIndex)
+                        .getSelectedItem()
+                        .toString();
+            }
+        });
+    }
+
+    protected String getSpinnerTextAtPositionInCardEditor(
+            final int dropdownIndex, final int itemPosition) throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
+            @Override
+            public String call() {
+                return mUI.getCardEditorView()
+                        .getDropdownFieldsForTest()
+                        .get(dropdownIndex)
+                        .getItemAtPosition(itemPosition)
+                        .toString();
+            }
+        });
+    }
+
+    protected int getSpinnerItemCountInCardEditor(final int dropdownIndex)
+            throws ExecutionException {
+        return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() {
+            @Override
+            public Integer call() {
+                return mUI.getCardEditorView()
+                        .getDropdownFieldsForTest()
+                        .get(dropdownIndex)
+                        .getCount();
+            }
+        });
+    }
+
+    protected String getUnmaskPromptErrorMessage() {
+        return mCardUnmaskPrompt.getErrorMessage();
+    }
+
+    protected void setSpinnerSelectionsInCardEditorAndWait(final int[] selections,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                List<Spinner> fields = mUI.getCardEditorView().getDropdownFieldsForTest();
+                for (int i = 0; i < selections.length && i < fields.size(); i++) {
+                    fields.get(i).setSelection(selections[i]);
+                }
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void setSpinnerSelectionInEditorAndWait(final int selection, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((Spinner) mUI.getEditorView().findViewById(R.id.spinner)).setSelection(selection);
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void setTextInCardEditorAndWait(final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ViewGroup contents =
+                        (ViewGroup) mUI.getCardEditorView().findViewById(R.id.contents);
+                Assert.assertNotNull(contents);
+                for (int i = 0, j = 0; i < contents.getChildCount() && j < values.length; i++) {
+                    View view = contents.getChildAt(i);
+                    if (view instanceof EditorTextField) {
+                        ((EditorTextField) view).getEditText().setText(values[j++]);
+                    }
+                }
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void setTextInEditorAndWait(final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                List<EditText> fields = mUI.getEditorView().getEditableTextFieldsForTest();
+                for (int i = 0; i < values.length; i++) {
+                    fields.get(i).setText(values[i]);
+                }
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void selectCheckboxAndWait(final int resourceId, final boolean isChecked,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                ((CheckBox) mUI.getCardEditorView().findViewById(resourceId)).setChecked(isChecked);
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void setTextInCardUnmaskDialogAndWait(final int resourceId, final String input,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                EditText editText =
+                        ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(resourceId));
+                editText.setText(input);
+                editText.getOnFocusChangeListener().onFocusChange(null, false);
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void setTextInExpiredCardUnmaskDialogAndWait(
+            final int[] resourceIds, final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        assert resourceIds.length == values.length;
+        int callCount = helper.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                for (int i = 0; i < resourceIds.length; ++i) {
+                    EditText editText =
+                            ((EditText) mCardUnmaskPrompt.getDialogForTest().findViewById(
+                                    resourceIds[i]));
+                    editText.setText(values[i]);
+                    editText.getOnFocusChangeListener().onFocusChange(null, false);
+                }
+            }
+        });
+        helper.waitForCallback(callCount);
+    }
+
+    protected void expectResultContains(final String[] contents) {
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                try {
+                    String result = DOMUtils.getNodeContents(mWebContentsRef.get(), "result");
+                    if (result == null) {
+                        updateFailureReason("Cannot find 'result' node on test page");
+                        return false;
+                    }
+                    for (int i = 0; i < contents.length; i++) {
+                        if (!result.contains(contents[i])) {
+                            updateFailureReason(
+                                    String.format("Result should contain '%s'", contents[i]));
+                            return false;
+                        }
+                    }
+                    return true;
+                } catch (InterruptedException e1) {
+                    updateFailureReason(e1.getMessage());
+                    return false;
+                } catch (TimeoutException e2) {
+                    updateFailureReason(e2.getMessage());
+                    return false;
+                }
+            }
+        });
+    }
+
+    protected void expectContactDetailsRowIsSelected(final int index) {
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                boolean isSelected = ((OptionSection) mUI.getContactDetailsSectionForTest())
+                                             .getOptionRowAtIndex(index)
+                                             .isChecked();
+                if (!isSelected) {
+                    updateFailureReason("Contact Details row at " + index + " was not selected.");
+                }
+                return isSelected;
+            }
+        });
+    }
+
+    protected void expectShippingAddressRowIsSelected(final int index) {
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                boolean isSelected = ((OptionSection) mUI.getShippingAddressSectionForTest())
+                                             .getOptionRowAtIndex(index)
+                                             .isChecked();
+                if (!isSelected) {
+                    updateFailureReason("Shipping Address row at " + index + " was not selected.");
+                }
+                return isSelected;
+            }
+        });
+    }
+
+    protected void expectPaymentMethodRowIsSelected(final int index) {
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                boolean isSelected = ((OptionSection) mUI.getPaymentMethodSectionForTest())
+                                             .getOptionRowAtIndex(index)
+                                             .isChecked();
+                if (!isSelected) {
+                    updateFailureReason("Payment Method row at " + index + " was not selected.");
+                }
+                return isSelected;
+            }
+        });
+    }
+
+    protected void assertOnlySpecificAbortMetricLogged(int abortReason) {
+        for (int i = 0; i < PaymentRequestMetrics.ABORT_REASON_MAX; ++i) {
+            Assert.assertEquals(
+                    String.format(Locale.getDefault(), "Found %d instead of %d", i, abortReason),
+                    (i == abortReason ? 1 : 0),
+                    RecordHistogram.getHistogramValueCountForTesting(
+                            "PaymentRequest.CheckoutFunnel.Aborted", i));
+        }
+    }
+
+    @Override
+    public void onPaymentRequestReadyForInput(PaymentRequestUI ui) {
+        ThreadUtils.assertOnUiThread();
+        mReadyForInput.notifyCalled(ui);
+    }
+
+    @Override
+    public void onPaymentRequestReadyToEdit() {
+        ThreadUtils.assertOnUiThread();
+        mReadyToEdit.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestEditorValidationError() {
+        ThreadUtils.assertOnUiThread();
+        mEditorValidationError.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestEditorTextUpdate() {
+        ThreadUtils.assertOnUiThread();
+        mEditorTextUpdate.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestReadyToPay(PaymentRequestUI ui) {
+        ThreadUtils.assertOnUiThread();
+        mReadyToPay.notifyCalled(ui);
+    }
+
+    @Override
+    public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {
+        ThreadUtils.assertOnUiThread();
+        mSelectionChecked.notifyCalled(ui);
+    }
+
+    @Override
+    public void onPaymentRequestResultReady(PaymentRequestUI ui) {
+        ThreadUtils.assertOnUiThread();
+        mResultReady.notifyCalled(ui);
+    }
+
+    @Override
+    public void onPaymentRequestDismiss() {
+        ThreadUtils.assertOnUiThread();
+        mDismissed.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestServiceUnableToAbort() {
+        ThreadUtils.assertOnUiThread();
+        mUnableToAbort.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestServiceBillingAddressChangeProcessed() {
+        ThreadUtils.assertOnUiThread();
+        mBillingAddressChangeProcessed.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestServiceExpirationMonthChange() {
+        ThreadUtils.assertOnUiThread();
+        mExpirationMonthChange.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestServiceShowFailed() {
+        ThreadUtils.assertOnUiThread();
+        mShowFailed.notifyCalled();
+    }
+
+    @Override
+    public void onPaymentRequestServiceCanMakePaymentQueryResponded() {
+        ThreadUtils.assertOnUiThread();
+        mCanMakePaymentQueryResponded.notifyCalled();
+    }
+
+    @Override
+    public void onCardUnmaskPromptReadyForInput(CardUnmaskPrompt prompt) {
+        ThreadUtils.assertOnUiThread();
+        mReadyForUnmaskInput.notifyCalled(prompt);
+        mCardUnmaskPrompt = prompt;
+    }
+
+    @Override
+    public void onCardUnmaskPromptReadyToUnmask(CardUnmaskPrompt prompt) {
+        ThreadUtils.assertOnUiThread();
+        mReadyToUnmask.notifyCalled(prompt);
+    }
+
+    @Override
+    public void onCardUnmaskPromptValidationDone(CardUnmaskPrompt prompt) {
+        ThreadUtils.assertOnUiThread();
+        mUnmaskValidationDone.notifyCalled(prompt);
+    }
+
+    /**
+     * Listens for UI notifications.
+     */
+    static class PaymentsCallbackHelper<T> extends CallbackHelper {
+        private T mTarget;
+
+        /**
+         * Returns the UI that is ready for input.
+         *
+         * @return The UI that is ready for input.
+         */
+        public T getTarget() {
+            return mTarget;
+        }
+
+        /**
+         * Called when the UI is ready for input.
+         *
+         * @param target The UI that is ready for input.
+         */
+        public void notifyCalled(T target) {
+            ThreadUtils.assertOnUiThread();
+            mTarget = target;
+            notifyCalled();
+        }
+    }
+
+    void installPaymentApp(int instrumentPresence, int responseSpeed) {
+        installPaymentApp("https://bobpay.com", instrumentPresence, responseSpeed);
+    }
+
+    void installPaymentApp(String methodName, int instrumentPresence, int responseSpeed) {
+        installPaymentApp(methodName, instrumentPresence, responseSpeed, IMMEDIATE_CREATION);
+    }
+
+    void installPaymentApp(
+            String methodName, int instrumentPresence, int responseSpeed, int creationSpeed) {
+        installPaymentApp(asList(methodName), instrumentPresence, responseSpeed, creationSpeed);
+    }
+
+    void installPaymentApp(final List<String> appMethodNames,
+            final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
+        PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
+            @Override
+            public void create(WebContents webContents, Set<String> methodNames,
+                    final PaymentAppFactory.PaymentAppCreatedCallback callback) {
+                final TestPay app = new TestPay(appMethodNames, instrumentPresence, responseSpeed);
+                if (creationSpeed == IMMEDIATE_CREATION) {
+                    callback.onPaymentAppCreated(app);
+                    callback.onAllPaymentAppsCreated();
+                } else {
+                    new Handler().postDelayed(new Runnable() {
+                        @Override
+                        public void run() {
+                            callback.onPaymentAppCreated(app);
+                            callback.onAllPaymentAppsCreated();
+                        }
+                    }, 100);
+                }
+            }
+        });
+    }
+
+    /** A payment app implementation for test. */
+    static class TestPay implements PaymentApp {
+        private final List<String> mMethodNames;
+        private final int mInstrumentPresence;
+        private final int mResponseSpeed;
+        private InstrumentsCallback mCallback;
+
+        TestPay(List<String> methodNames, int instrumentPresence, int responseSpeed) {
+            mMethodNames = methodNames;
+            mInstrumentPresence = instrumentPresence;
+            mResponseSpeed = responseSpeed;
+        }
+
+        @Override
+        public void getInstruments(Map<String, PaymentMethodData> methodData, String origin,
+                String iframeOrigin, byte[][] certificateChain, PaymentItem total,
+                InstrumentsCallback instrumentsCallback) {
+            mCallback = instrumentsCallback;
+            respond();
+        }
+
+        void respond() {
+            final List<PaymentInstrument> instruments = new ArrayList<>();
+            if (mInstrumentPresence == HAVE_INSTRUMENTS) {
+                for (String methodName : mMethodNames) {
+                    instruments.add(
+                            new TestPayInstrument(getAppIdentifier(), methodName, methodName));
+                }
+            }
+            Runnable instrumentsReady = new Runnable() {
+                @Override
+                public void run() {
+                    ThreadUtils.assertOnUiThread();
+                    mCallback.onInstrumentsReady(TestPay.this, instruments);
+                }
+            };
+            if (mResponseSpeed == IMMEDIATE_RESPONSE) {
+                instrumentsReady.run();
+            } else if (mResponseSpeed == DELAYED_RESPONSE) {
+                new Handler().postDelayed(instrumentsReady, 100);
+            }
+        }
+
+        @Override
+        public Set<String> getAppMethodNames() {
+            Set<String> methodNames = new HashSet<>();
+            methodNames.addAll(mMethodNames);
+            return methodNames;
+        }
+
+        @Override
+        public boolean supportsMethodsAndData(Map<String, PaymentMethodData> methodsAndData) {
+            assert methodsAndData != null;
+            Set<String> methodNames = new HashSet<>(methodsAndData.keySet());
+            methodNames.retainAll(getAppMethodNames());
+            return !methodNames.isEmpty();
+        }
+
+        @Override
+        public String getAppIdentifier() {
+            return TestPay.this.toString();
+        }
+    }
+
+    /** A payment instrument implementation for test. */
+    private static class TestPayInstrument extends PaymentInstrument {
+        private final String mMethodName;
+
+        TestPayInstrument(String appId, String methodName, String label) {
+            super(appId + methodName, label, null, null);
+            mMethodName = methodName;
+        }
+
+        @Override
+        public Set<String> getInstrumentMethodNames() {
+            Set<String> result = new HashSet<>();
+            result.add(mMethodName);
+            return result;
+        }
+
+        @Override
+        public void invokePaymentApp(String id, String merchantName, String origin,
+                String iframeOrigin, byte[][] certificateChain,
+                Map<String, PaymentMethodData> methodData, PaymentItem total,
+                List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers,
+                InstrumentDetailsCallback detailsCallback) {
+            detailsCallback.onInstrumentDetailsReady(
+                    mMethodName, "{\"transaction\": 1337}");
+        }
+
+        @Override
+        public void dismissInstrument() {}
+    }
+
+    public interface PaymentRequestTestCommonCallback {
+        ChromeTabbedActivity getActivity();
+        void onMainActivityStarted()
+                throws InterruptedException, ExecutionException, TimeoutException;
+        void startMainActivityWithURL(String url) throws InterruptedException;
+        void assertWaitForPageScaleFactorMatch(float expectedScale);
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
new file mode 100644
index 0000000..64adedc
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -0,0 +1,542 @@
+// 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.
+
+package org.chromium.chrome.browser.payments;
+
+import android.view.View;
+
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.autofill.CardUnmaskPrompt;
+import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.PaymentRequestTestCommonCallback;
+import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.PaymentsCallbackHelper;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.OptionRow;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
+import org.chromium.chrome.test.ChromeActivityTestRule;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Custom ActivityTestRule for integration test for payments.
+ */
+public class PaymentRequestTestRule extends ChromeActivityTestRule<ChromeTabbedActivity>
+        implements PaymentRequestTestCommonCallback {
+    /** Flag for installing a payment app without instruments. */
+    public static final int NO_INSTRUMENTS = PaymentRequestTestCommon.NO_INSTRUMENTS;
+
+    /** Flag for installing a payment app with instruments. */
+    public static final int HAVE_INSTRUMENTS = PaymentRequestTestCommon.HAVE_INSTRUMENTS;
+
+    /** Flag for installing a fast payment app. */
+    public static final int IMMEDIATE_RESPONSE = PaymentRequestTestCommon.IMMEDIATE_RESPONSE;
+
+    /** Flag for installing a slow payment app. */
+    public static final int DELAYED_RESPONSE = PaymentRequestTestCommon.DELAYED_RESPONSE;
+
+    /** Flag for immediately installing a payment app. */
+    public static final int IMMEDIATE_CREATION = PaymentRequestTestCommon.IMMEDIATE_CREATION;
+
+    /** Flag for installing a payment app with a delay. */
+    public static final int DELAYED_CREATION = PaymentRequestTestCommon.DELAYED_CREATION;
+
+    /** The expiration month dropdown index for December. */
+    public static final int DECEMBER = PaymentRequestTestCommon.DECEMBER;
+
+    /** The expiration year dropdown index for the next year. */
+    public static final int NEXT_YEAR = PaymentRequestTestCommon.NEXT_YEAR;
+
+    /** The billing address dropdown index for the first billing address. */
+    public static final int FIRST_BILLING_ADDRESS = PaymentRequestTestCommon.FIRST_BILLING_ADDRESS;
+
+    private final PaymentRequestTestCommon mTestCommon;
+    private final MainActivityStartCallback mCallback;
+
+    public PaymentRequestTestRule(String testFileName, MainActivityStartCallback callback) {
+        super(ChromeTabbedActivity.class);
+        mTestCommon = new PaymentRequestTestCommon(this, testFileName);
+        mCallback = callback;
+    }
+
+    public PaymentRequestTestRule(String testFileName) {
+        this(testFileName, null);
+    }
+
+    public PaymentsCallbackHelper<PaymentRequestUI> getReadyForInput() {
+        return mTestCommon.mReadyForInput;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getReadyToPay() {
+        return mTestCommon.mReadyToPay;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getSelectionChecked() {
+        return mTestCommon.mSelectionChecked;
+    }
+    public PaymentsCallbackHelper<PaymentRequestUI> getResultReady() {
+        return mTestCommon.mResultReady;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getReadyForUnmaskInput() {
+        return mTestCommon.mReadyForUnmaskInput;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getReadyToUnmask() {
+        return mTestCommon.mReadyToUnmask;
+    }
+    public PaymentsCallbackHelper<CardUnmaskPrompt> getUnmaskValidationDone() {
+        return mTestCommon.mUnmaskValidationDone;
+    }
+    public CallbackHelper getReadyToEdit() {
+        return mTestCommon.mReadyToEdit;
+    }
+    public CallbackHelper getEditorValidationError() {
+        return mTestCommon.mEditorValidationError;
+    }
+    public CallbackHelper getEditorTextUpdate() {
+        return mTestCommon.mEditorTextUpdate;
+    }
+    public CallbackHelper getDismissed() {
+        return mTestCommon.mDismissed;
+    }
+    public CallbackHelper getUnableToAbort() {
+        return mTestCommon.mUnableToAbort;
+    }
+    public CallbackHelper getBillingAddressChangeProcessed() {
+        return mTestCommon.mBillingAddressChangeProcessed;
+    }
+    public CallbackHelper getShowFailed() {
+        return mTestCommon.mShowFailed;
+    }
+    public CallbackHelper getCanMakePaymentQueryResponded() {
+        return mTestCommon.mCanMakePaymentQueryResponded;
+    }
+    public CallbackHelper getExpirationMonthChange() {
+        return mTestCommon.mExpirationMonthChange;
+    }
+    public PaymentRequestUI getPaymentRequestUI() {
+        return mTestCommon.mUI;
+    }
+
+    public void startMainActivity() throws InterruptedException {
+        mTestCommon.startMainActivity();
+    }
+
+    protected void triggerUIAndWait(PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        mTestCommon.triggerUIAndWait(helper);
+    }
+
+    protected void openPageAndClickBuyAndWait(CallbackHelper helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        mTestCommon.openPageAndClickBuyAndWait(helper);
+    }
+
+    protected void triggerUIAndWait(String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        mTestCommon.triggerUIAndWait(nodeId, helper);
+    }
+
+    protected void openPageAndClickNodeAndWait(String nodeId, CallbackHelper helper)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        mTestCommon.openPageAndClickNodeAndWait(nodeId, helper);
+    }
+
+    protected void openPageAndClickNode(String nodeId)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        mTestCommon.openPageAndClickNode(nodeId);
+    }
+
+    protected void reTriggerUIAndWait(
+            String nodeId, PaymentsCallbackHelper<PaymentRequestUI> helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.reTriggerUIAndWait(nodeId, helper);
+    }
+
+    /** Clicks on an HTML node. */
+    protected void clickNodeAndWait(String nodeId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickNodeAndWait(nodeId, helper);
+    }
+
+    /** Clicks on an element in the payments UI. */
+    protected void clickAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickAndWait(resourceId, helper);
+    }
+
+    /**
+     * Clicks on an element in the "Shipping summary" section of the payments UI. This section
+     * combines both shipping address and shipping option. It is replaced by "Shipping address" and
+     * "Shipping option" sections upon expanding the payments UI.
+     */
+    protected void clickInShippingSummaryAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInShippingSummaryAndWait(resourceId, helper);
+    }
+
+    /** Clicks on an element in the "Shipping address" section of the payments UI. */
+    protected void clickInShippingAddressAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInShippingAddressAndWait(resourceId, helper);
+    }
+
+    /** Clicks on an element in the "Payment" section of the payments UI. */
+    protected void clickInPaymentMethodAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInPaymentMethodAndWait(resourceId, helper);
+    }
+
+    /** Clicks on an element in the "Contact Info" section of the payments UI. */
+    protected void clickInContactInfoAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInContactInfoAndWait(resourceId, helper);
+    }
+
+    /** Clicks on an element in the editor UI for credit cards. */
+    protected void clickInCardEditorAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInCardEditorAndWait(resourceId, helper);
+    }
+
+    /** Clicks on an element in the editor UI. */
+    protected void clickInEditorAndWait(final int resourceId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickInEditorAndWait(resourceId, helper);
+    }
+
+    protected void clickAndroidBackButtonInEditorAndWait(CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickAndroidBackButtonInEditorAndWait(helper);
+    }
+
+    /** Clicks on a button in the card unmask UI. */
+    protected void clickCardUnmaskButtonAndWait(final int dialogButtonId, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.clickCardUnmaskButtonAndWait(dialogButtonId, helper);
+    }
+
+    /** Gets the button state for the shipping summary section. */
+    protected int getSummarySectionButtonState() throws ExecutionException {
+        return mTestCommon.getSummarySectionButtonState();
+    }
+
+    /** Gets the button state for the contact details section. */
+    protected int getContactDetailsButtonState() throws ExecutionException {
+        return mTestCommon.getContactDetailsButtonState();
+    }
+
+    /**  Returns the label corresponding to the payment instrument at the specified |index|. */
+    protected String getPaymentInstrumentLabel(final int index) throws ExecutionException {
+        return mTestCommon.getPaymentInstrumentLabel(index);
+    }
+
+    /**
+     *  Returns the label corresponding to the contact detail suggestion at the specified
+     *  |suggestionIndex|.
+     */
+    protected String getContactDetailsSuggestionLabel(final int suggestionIndex)
+            throws ExecutionException {
+        return mTestCommon.getContactDetailsSuggestionLabel(suggestionIndex);
+    }
+
+    /**  Returns the number of payment instruments. */
+    protected int getNumberOfPaymentInstruments() throws ExecutionException {
+        return mTestCommon.getNumberOfPaymentInstruments();
+    }
+
+    /**  Returns the number of contact detail suggestions. */
+    protected int getNumberOfContactDetailSuggestions() throws ExecutionException {
+        return mTestCommon.getNumberOfContactDetailSuggestions();
+    }
+
+    /**
+     *  Returns the label corresponding to the shipping address suggestion at the specified
+     *  |suggestionIndex|.
+     */
+    protected String getShippingAddressSuggestionLabel(final int suggestionIndex)
+            throws ExecutionException {
+        return mTestCommon.getShippingAddressSuggestionLabel(suggestionIndex);
+    }
+
+    /** Returns the focused view in the card editor view. */
+    protected View getCardEditorFocusedView() {
+        return mTestCommon.getCardEditorFocusedView();
+    }
+
+    /**
+     *  Clicks on the label corresponding to the shipping address suggestion at the specified
+     *  |suggestionIndex|.
+     * @throws InterruptedException
+     */
+    protected void clickOnShippingAddressSuggestionOptionAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        mTestCommon.clickOnShippingAddressSuggestionOptionAndWait(suggestionIndex, helper);
+    }
+
+    /**
+     *  Clicks on the label corresponding to the payment method suggestion at the specified
+     *  |suggestionIndex|.
+     * @throws InterruptedException
+     */
+    protected void clickOnPaymentMethodSuggestionOptionAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        mTestCommon.clickOnPaymentMethodSuggestionOptionAndWait(suggestionIndex, helper);
+    }
+
+    /**
+     *  Clicks on the edit icon corresponding to the payment method suggestion at the specified
+     *  |suggestionIndex|.
+     */
+    protected void clickOnPaymentMethodSuggestionEditIconAndWait(
+            final int suggestionIndex, CallbackHelper helper)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        mTestCommon.clickOnPaymentMethodSuggestionEditIconAndWait(suggestionIndex, helper);
+    }
+
+    /**
+     *  Returns the the number of shipping address suggestions.
+     */
+    protected int getNumberOfShippingAddressSuggestions() throws ExecutionException {
+        return mTestCommon.getNumberOfShippingAddressSuggestions();
+    }
+
+    /** Returns the {@link OptionRow} at the given index for the shipping address section. */
+    protected OptionRow getShippingAddressOptionRowAtIndex(final int index)
+            throws ExecutionException {
+        return mTestCommon.getShippingAddressOptionRowAtIndex(index);
+    }
+
+    /** Returns the selected spinner value in the editor UI for credit cards. */
+    protected String getSpinnerSelectionTextInCardEditor(final int dropdownIndex)
+            throws ExecutionException {
+        return mTestCommon.getSpinnerSelectionTextInCardEditor(dropdownIndex);
+    }
+
+    /** Returns the spinner value at the specified position in the editor UI for credit cards. */
+    protected String getSpinnerTextAtPositionInCardEditor(
+            final int dropdownIndex, final int itemPosition) throws ExecutionException {
+        return mTestCommon.getSpinnerTextAtPositionInCardEditor(dropdownIndex, itemPosition);
+    }
+
+    /** Returns the number of items offered by the spinner in the editor UI for credit cards. */
+    protected int getSpinnerItemCountInCardEditor(final int dropdownIndex)
+            throws ExecutionException {
+        return mTestCommon.getSpinnerItemCountInCardEditor(dropdownIndex);
+    }
+
+    /** Returns the error message visible to the user in the credit card unmask prompt. */
+    protected String getUnmaskPromptErrorMessage() {
+        return mTestCommon.getUnmaskPromptErrorMessage();
+    }
+
+    /** Selects the spinner value in the editor UI for credit cards. */
+    protected void setSpinnerSelectionsInCardEditorAndWait(final int[] selections,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        mTestCommon.setSpinnerSelectionsInCardEditorAndWait(selections, helper);
+    }
+
+    /** Selects the spinner value in the editor UI. */
+    protected void setSpinnerSelectionInEditorAndWait(final int selection, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.setSpinnerSelectionInEditorAndWait(selection, helper);
+    }
+
+    /** Directly sets the text in the editor UI for credit cards. */
+    protected void setTextInCardEditorAndWait(final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.setTextInCardEditorAndWait(values, helper);
+    }
+
+    /** Directly sets the text in the editor UI. */
+    protected void setTextInEditorAndWait(final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.setTextInEditorAndWait(values, helper);
+    }
+
+    /** Directly sets the checkbox selection in the editor UI for credit cards. */
+    protected void selectCheckboxAndWait(final int resourceId, final boolean isChecked,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        mTestCommon.selectCheckboxAndWait(resourceId, isChecked, helper);
+    }
+
+    /** Directly sets the text in the card unmask UI. */
+    protected void setTextInCardUnmaskDialogAndWait(final int resourceId, final String input,
+            CallbackHelper helper) throws InterruptedException, TimeoutException {
+        mTestCommon.setTextInCardUnmaskDialogAndWait(resourceId, input, helper);
+    }
+
+    /** Directly sets the text in the expired card unmask UI. */
+    protected void setTextInExpiredCardUnmaskDialogAndWait(
+            final int[] resourceIds, final String[] values, CallbackHelper helper)
+            throws InterruptedException, TimeoutException {
+        mTestCommon.setTextInExpiredCardUnmaskDialogAndWait(resourceIds, values, helper);
+    }
+
+    /** Verifies the contents of the test webpage. */
+    protected void expectResultContains(final String[] contents) {
+        mTestCommon.expectResultContains(contents);
+    }
+
+    /**  Will fail if the OptionRow at |index| is not selected in Contact Details.*/
+    protected void expectContactDetailsRowIsSelected(final int index) {
+        mTestCommon.expectContactDetailsRowIsSelected(index);
+    }
+
+    /**  Will fail if the OptionRow at |index| is not selected in Shipping Address section.*/
+    protected void expectShippingAddressRowIsSelected(final int index) {
+        mTestCommon.expectShippingAddressRowIsSelected(index);
+    }
+
+    /**  Will fail if the OptionRow at |index| is not selected in PaymentMethod section.*/
+    protected void expectPaymentMethodRowIsSelected(final int index) {
+        mTestCommon.expectPaymentMethodRowIsSelected(index);
+    }
+
+    /**
+     * Asserts that only the specified reason for abort is logged.
+     *
+     * @param abortReason The only bucket in the abort histogram that should have a record.
+     */
+    protected void assertOnlySpecificAbortMetricLogged(int abortReason) {
+        mTestCommon.assertOnlySpecificAbortMetricLogged(abortReason);
+    }
+
+    public void onPaymentRequestReadyForInput(PaymentRequestUI ui) {
+        mTestCommon.onPaymentRequestReadyForInput(ui);
+    }
+
+    public void onPaymentRequestReadyToEdit() {
+        mTestCommon.onPaymentRequestReadyToEdit();
+    }
+
+    public void onPaymentRequestEditorValidationError() {
+        mTestCommon.onPaymentRequestEditorValidationError();
+    }
+
+    public void onPaymentRequestEditorTextUpdate() {
+        mTestCommon.onPaymentRequestEditorTextUpdate();
+    }
+
+    public void onPaymentRequestReadyToPay(PaymentRequestUI ui) {
+        mTestCommon.onPaymentRequestReadyToPay(ui);
+    }
+
+    public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {
+        mTestCommon.onPaymentRequestSelectionChecked(ui);
+    }
+
+    public void onPaymentRequestResultReady(PaymentRequestUI ui) {
+        mTestCommon.onPaymentRequestResultReady(ui);
+    }
+
+    public void onPaymentRequestDismiss() {
+        mTestCommon.onPaymentRequestDismiss();
+    }
+
+    public void onPaymentRequestServiceUnableToAbort() {
+        mTestCommon.onPaymentRequestServiceUnableToAbort();
+    }
+
+    public void onPaymentRequestServiceBillingAddressChangeProcessed() {
+        mTestCommon.onPaymentRequestServiceBillingAddressChangeProcessed();
+    }
+
+    public void onPaymentRequestServiceExpirationMonthChange() {
+        mTestCommon.onPaymentRequestServiceExpirationMonthChange();
+    }
+
+    public void onPaymentRequestServiceShowFailed() {
+        mTestCommon.onPaymentRequestServiceShowFailed();
+    }
+
+    public void onPaymentRequestServiceCanMakePaymentQueryResponded() {
+        mTestCommon.onPaymentRequestServiceCanMakePaymentQueryResponded();
+    }
+
+    public void onCardUnmaskPromptReadyForInput(CardUnmaskPrompt prompt) {
+        mTestCommon.onCardUnmaskPromptReadyForInput(prompt);
+    }
+
+    public void onCardUnmaskPromptReadyToUnmask(CardUnmaskPrompt prompt) {
+        mTestCommon.onCardUnmaskPromptReadyToUnmask(prompt);
+    }
+
+    public void onCardUnmaskPromptValidationDone(CardUnmaskPrompt prompt) {
+        mTestCommon.onCardUnmaskPromptValidationDone(prompt);
+    }
+
+    /**
+     * Installs a payment app for testing.
+     *
+     * @param instrumentPresence Whether the app has any payment instruments. Either NO_INSTRUMENTS
+     *                           or HAVE_INSTRUMENTS.
+     * @param responseSpeed      How quickly the app will respond to "get instruments" query. Either
+     *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
+     */
+    protected void installPaymentApp(int instrumentPresence, int responseSpeed) {
+        mTestCommon.installPaymentApp(instrumentPresence, responseSpeed);
+    }
+
+    /**
+     * Installs a payment app for testing.
+     *
+     * @param methodName         The name of the payment method used in the payment app.
+     * @param instrumentPresence Whether the app has any payment instruments. Either NO_INSTRUMENTS
+     *                           or HAVE_INSTRUMENTS.
+     * @param responseSpeed      How quickly the app will respond to "get instruments" query. Either
+     *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
+     */
+    protected void installPaymentApp(String methodName, int instrumentPresence, int responseSpeed) {
+        mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed);
+    }
+
+    /**
+     * Installs a payment app for testing.
+     *
+     * @param methodName         The name of the payment method used in the payment app.
+     * @param instrumentPresence Whether the app has any payment instruments. Either NO_INSTRUMENTS
+     *                           or HAVE_INSTRUMENTS.
+     * @param responseSpeed      How quickly the app will respond to "get instruments" query. Either
+     *                           IMMEDIATE_RESPONSE or DELAYED_RESPONSE.
+     * @param creationSpeed      How quickly the app factory will create this app. Either
+     *                           IMMEDIATE_CREATION or DELAYED_CREATION.
+     */
+    protected void installPaymentApp(
+            String methodName, int instrumentPresence, int responseSpeed, int creationSpeed) {
+        mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed, creationSpeed);
+    }
+
+    protected void installPaymentApp(final List<String> appMethodNames,
+            final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
+        mTestCommon.installPaymentApp(
+                appMethodNames, instrumentPresence, responseSpeed, creationSpeed);
+    }
+
+    @Override
+    public void onMainActivityStarted()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        if (mCallback != null) {
+            mCallback.onMainActivityStarted();
+        }
+    }
+
+    @Override
+    public Statement apply(final Statement base, Description description) {
+        return super.apply(new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                startMainActivity();
+                base.evaluate();
+            }
+        }, description);
+    }
+
+    public interface MainActivityStartCallback {
+        void onMainActivityStarted() throws
+                InterruptedException, ExecutionException, TimeoutException;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
index 5e17c9b..a95219c8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
@@ -51,15 +51,15 @@
     @Feature({"Payments"})
     public void testLogProfileAndCreditCardUse() throws InterruptedException, ExecutionException,
             TimeoutException {
-        triggerUIAndWait(mReadyToPay);
+        triggerUIAndWait(getReadyToPay());
 
         // Get the current date value just before the start of the Payment Request.
         long timeBeforeRecord = mHelper.getCurrentDateForTesting();
 
         // Proceed with the payment.
-        clickAndWait(R.id.button_primary, mReadyForUnmaskInput);
-        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask);
-        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed);
+        clickAndWait(R.id.button_primary, getReadyForUnmaskInput());
+        setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", getReadyToUnmask());
+        clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, getDismissed());
 
         // Get the current date value just after the end of the Payment Request.
         long timeAfterRecord = mHelper.getCurrentDateForTesting();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
index 21eb45e4..0b9d9e2f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
@@ -43,6 +43,7 @@
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.KeyUtils;
+import org.chromium.content_public.common.ContentUrlConstants;
 
 import java.util.concurrent.Callable;
 
@@ -146,7 +147,17 @@
 
     @Test
     @SmallTest
-    public void testStartsBrowserAfterUrlSubmitted() throws Exception {
+    public void testStartsBrowserAfterUrlSubmitted_aboutblank() throws Exception {
+        verifyUrlLoads(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
+    }
+
+    @Test
+    @SmallTest
+    public void testStartsBrowserAfterUrlSubmitted_chromeUrl() throws Exception {
+        verifyUrlLoads("chrome://flags/");
+    }
+
+    private void verifyUrlLoads(final String url) throws Exception {
         SearchActivity searchActivity = startSearchActivity();
 
         // Wait for the Activity to fully load.
@@ -161,10 +172,10 @@
         instrumentation.addMonitor(browserMonitor);
 
         // Type in a URL that should get kicked to ChromeTabbedActivity.
-        setUrlBarText(searchActivity, "about:blank");
+        setUrlBarText(searchActivity, url);
         final UrlBar urlBar = (UrlBar) searchActivity.findViewById(R.id.url_bar);
         KeyUtils.singleKeyEventView(instrumentation, urlBar, KeyEvent.KEYCODE_ENTER);
-        waitForChromeTabbedActivityToStart(browserMonitor);
+        waitForChromeTabbedActivityToStart(browserMonitor, url);
     }
 
     @Test
@@ -178,7 +189,7 @@
         Assert.assertEquals(0, mTestDelegate.onFinishDeferredInitializationCallback.getCallCount());
 
         // Set some text in the search box (but don't hit enter).
-        setUrlBarText(searchActivity, "about:blank");
+        setUrlBarText(searchActivity, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
 
         // Start loading native, then let the activity finish initialization.
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -206,7 +217,8 @@
         instrumentation.addMonitor(browserMonitor);
         UrlBar urlBar = (UrlBar) searchActivity.findViewById(R.id.url_bar);
         KeyUtils.singleKeyEventView(instrumentation, urlBar, KeyEvent.KEYCODE_ENTER);
-        waitForChromeTabbedActivityToStart(browserMonitor);
+        waitForChromeTabbedActivityToStart(
+                browserMonitor, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
     }
 
     @Test
@@ -221,7 +233,7 @@
 
         // Submit a URL before native is loaded.  The browser shouldn't start yet.
         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        setUrlBarText(searchActivity, "about:blank");
+        setUrlBarText(searchActivity, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
         UrlBar urlBar = (UrlBar) searchActivity.findViewById(R.id.url_bar);
         KeyUtils.singleKeyEventView(instrumentation, urlBar, KeyEvent.KEYCODE_ENTER);
         Assert.assertEquals(searchActivity, ApplicationStatus.getLastTrackedFocusedActivity());
@@ -242,7 +254,8 @@
                 1, mTestDelegate.shouldDelayNativeInitializationCallback.getCallCount());
         mTestDelegate.showSearchEngineDialogIfNeededCallback.waitForCallback(0);
         mTestDelegate.onFinishDeferredInitializationCallback.waitForCallback(0);
-        waitForChromeTabbedActivityToStart(browserMonitor);
+        waitForChromeTabbedActivityToStart(
+                browserMonitor, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
     }
 
     @Test
@@ -256,7 +269,7 @@
         Assert.assertEquals(0, mTestDelegate.onFinishDeferredInitializationCallback.getCallCount());
 
         // Set some text in the search box, then continue startup.
-        setUrlBarText(searchActivity, "about:blank");
+        setUrlBarText(searchActivity, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -283,7 +296,8 @@
         instrumentation.addMonitor(browserMonitor);
         UrlBar urlBar = (UrlBar) searchActivity.findViewById(R.id.url_bar);
         KeyUtils.singleKeyEventView(instrumentation, urlBar, KeyEvent.KEYCODE_ENTER);
-        waitForChromeTabbedActivityToStart(browserMonitor);
+        waitForChromeTabbedActivityToStart(
+                browserMonitor, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
     }
 
     @Test
@@ -298,7 +312,7 @@
         Assert.assertEquals(0, mTestDelegate.onFinishDeferredInitializationCallback.getCallCount());
 
         // Set some text in the search box, then select the first engine to continue startup.
-        setUrlBarText(searchActivity, "about:blank");
+        setUrlBarText(searchActivity, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
         DefaultSearchEngineDialogHelperUtils.clickOnFirstEngine(
                 mTestDelegate.shownPromoDialog.findViewById(android.R.id.content));
 
@@ -321,7 +335,8 @@
         instrumentation.addMonitor(browserMonitor);
         UrlBar urlBar = (UrlBar) searchActivity.findViewById(R.id.url_bar);
         KeyUtils.singleKeyEventView(instrumentation, urlBar, KeyEvent.KEYCODE_ENTER);
-        waitForChromeTabbedActivityToStart(browserMonitor);
+        waitForChromeTabbedActivityToStart(
+                browserMonitor, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
     }
 
     @Test
@@ -404,8 +419,8 @@
         return (SearchActivity) searchActivity;
     }
 
-    private void waitForChromeTabbedActivityToStart(ActivityMonitor browserMonitor)
-            throws Exception {
+    private void waitForChromeTabbedActivityToStart(
+            ActivityMonitor browserMonitor, String expectedUrl) throws Exception {
         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
         final Activity browserActivity = instrumentation.waitForMonitorWithTimeout(
                 browserMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL);
@@ -413,16 +428,16 @@
         Assert.assertTrue(
                 "Wrong activity started", browserActivity instanceof ChromeTabbedActivity);
 
-        CriteriaHelper.pollUiThread(new Criteria() {
+        CriteriaHelper.pollUiThread(Criteria.equals(expectedUrl, new Callable<String>() {
             @Override
-            public boolean isSatisfied() {
+            public String call() throws Exception {
                 ChromeTabbedActivity chromeActivity = (ChromeTabbedActivity) browserActivity;
                 Tab tab = chromeActivity.getActivityTab();
-                if (tab == null) return false;
+                if (tab == null) return null;
 
-                return TextUtils.equals("about:blank", tab.getUrl());
+                return tab.getUrl();
             }
-        });
+        }));
     }
 
     @SuppressLint("SetTextI18n")
diff --git a/content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderTest.java
similarity index 99%
rename from content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderTest.java
index 881e906..a522a4cf 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/installedapp/InstalledAppProviderTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser.installedapp;
+package org.chromium.chrome.browser.installedapp;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
diff --git a/content/public/android/junit/src/org/chromium/content/browser/installedapp/PackageHashTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/installedapp/PackageHashTest.java
similarity index 96%
rename from content/public/android/junit/src/org/chromium/content/browser/installedapp/PackageHashTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/installedapp/PackageHashTest.java
index ef175c4..2c2d6d2 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/installedapp/PackageHashTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/installedapp/PackageHashTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.content.browser.installedapp;
+package org.chromium.chrome.browser.installedapp;
 
 import org.junit.Assert;
 import org.junit.Test;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6dcf752f0..f79724f 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -648,6 +648,8 @@
     "metrics/network_quality_estimator_provider_impl.h",
     "metrics/perf/perf_provider_chromeos.cc",
     "metrics/perf/perf_provider_chromeos.h",
+    "metrics/process_memory_metrics_emitter.cc",
+    "metrics/process_memory_metrics_emitter.h",
     "metrics/renderer_uptime_tracker.cc",
     "metrics/renderer_uptime_tracker.h",
     "metrics/renderer_uptime_web_contents_observer.cc",
@@ -1645,6 +1647,7 @@
     "//services/preferences/public/cpp/tracked",
     "//services/preferences/public/interfaces",
     "//services/preferences/tracked",
+    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//services/service_manager/public/cpp",
     "//services/shape_detection/public/interfaces",
     "//skia",
@@ -3682,6 +3685,10 @@
 
   if (enable_vr) {
     if (is_android) {
+      sources += [
+        "android/vr_shell/vr_tab_helper.cc",
+        "android/vr_shell/vr_tab_helper.h",
+      ]
       deps += [ "android/vr_shell:vr_common" ]
       configs += [ "//third_party/gvr-android-sdk:libgvr_config" ]
     }
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 224c8b1..0efb7cf 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -51,6 +51,7 @@
   "+services/identity/public/interfaces",
   "+services/preferences/public/cpp",
   "+services/preferences/public/interfaces",
+  "+services/resource_coordinator/public/interfaces/memory",
   "+services/service_manager",
   "+services/shape_detection/public/interfaces",
   "+services/ui/public",
@@ -106,6 +107,7 @@
   "-third_party/WebKit",
   "+third_party/WebKit/public/platform/WebCache.h",
   "+third_party/WebKit/public/platform/WebDisplayMode.h",
+  "+third_party/WebKit/public/platform/WebFeaturePolicyFeature.h",
   "+third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h",
   "+third_party/WebKit/public/platform/WebGestureEvent.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 0af672d..4db353e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1856,7 +1856,7 @@
     {"enable-top-document-isolation",
      flag_descriptions::kTopDocumentIsolationName,
      flag_descriptions::kTopDocumentIsolationDescription, kOsAll,
-     SINGLE_VALUE_TYPE(switches::kTopDocumentIsolation)},
+     FEATURE_VALUE_TYPE(features::kTopDocumentIsolation)},
     {"enable-use-zoom-for-dsf", flag_descriptions::kEnableUseZoomForDsfName,
      flag_descriptions::kEnableUseZoomForDsfDescription, kOsAll,
      MULTI_VALUE_TYPE(kEnableUseZoomForDSFChoices)},
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index fa26ef6c..a010e88 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -13,6 +13,12 @@
 #include "chrome/browser/android/banners/app_banner_manager_android.h"
 #include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/android/hung_renderer_infobar_delegate.h"
+
+#include "device/vr/features/features.h"
+#if BUILDFLAG(ENABLE_VR)
+#include "chrome/browser/android/vr_shell/vr_tab_helper.h"
+#endif  // BUILDFLAG(ENABLE_VR)
+
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/file_select_helper.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -119,6 +125,12 @@
 void TabWebContentsDelegateAndroid::RunFileChooser(
     content::RenderFrameHost* render_frame_host,
     const FileChooserParams& params) {
+#if BUILDFLAG(ENABLE_VR)
+  if (vr_shell::VrTabHelper::IsInVr(
+          WebContents::FromRenderFrameHost(render_frame_host))) {
+    return;
+  }
+#endif
   FileSelectHelper::RunFileChooser(render_frame_host, params);
 }
 
@@ -255,6 +267,11 @@
 content::JavaScriptDialogManager*
 TabWebContentsDelegateAndroid::GetJavaScriptDialogManager(
     WebContents* source) {
+#if BUILDFLAG(ENABLE_VR)
+  if (vr_shell::VrTabHelper::IsInVr(source)) {
+    return nullptr;
+  }
+#endif
   return app_modal::JavaScriptDialogManager::GetInstance();
 }
 
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn
index 7823b77..4115f78 100644
--- a/chrome/browser/android/vr_shell/BUILD.gn
+++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -110,10 +110,6 @@
       "//ui/vector_icons",
     ]
 
-    public_deps = [
-      "//device/vr:mojo_bindings",
-    ]
-
     libs = [
       "//third_party/gvr-android-sdk/libgvr_shim_static_${current_cpu}.a",
       "android",
diff --git a/chrome/browser/android/vr_shell/textures/insecure_content_permanent_texture.cc b/chrome/browser/android/vr_shell/textures/insecure_content_permanent_texture.cc
index 881ffa5..68e4edfc 100644
--- a/chrome/browser/android/vr_shell/textures/insecure_content_permanent_texture.cc
+++ b/chrome/browser/android/vr_shell/textures/insecure_content_permanent_texture.cc
@@ -12,6 +12,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/render_text.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/vector_icons/vector_icons.h"
 
@@ -41,33 +42,29 @@
 
   DCHECK(texture_size.height() * 4 == texture_size.width());
   size_.set_height(texture_size.height());
-  int max_width = texture_size.width();
-  cc::PaintFlags flags;
-  flags.setColor(kBackgroundColor);
-
-  int text_flags = gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::NO_ELLIPSIS;
+  SkPaint paint;
+  paint.setColor(kBackgroundColor);
   auto text =
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_INSECURE_WEBVR_CONTENT_PERMANENT);
   auto fonts = GetFontList(size_.height() * kFontSizeFactor, text);
-  int text_height = kTextHeightFactor * size_.height();
-  int text_width = kTextWidthFactor * size_.height();
-  gfx::Canvas::SizeStringInt(text, fonts, &text_width, &text_height, 0,
-                             text_flags);
-  // Giving some extra width without reaching the texture limit.
-  text_width =
-      static_cast<int>(std::min(text_width + 2 * kBorderFactor * size_.height(),
-                                kTextWidthFactor * size_.height()));
-  size_.set_width((3 * kBorderFactor + kIconSizeFactor) * size_.height() +
-                  text_width);
-  DCHECK_LE(size_.width(), max_width);
-  canvas->DrawRoundRect(gfx::Rect(size_.width(), size_.height()),
-                        size_.height() * kBorderFactor, flags);
+  gfx::Rect text_size(0, kTextHeightFactor * size_.height());
+
+  std::vector<std::unique_ptr<gfx::RenderText>> lines =
+      PrepareDrawStringRect(text, fonts, kForegroundColor, &text_size, 0);
+
+  DCHECK_LE(text_size.width(), kTextWidthFactor * size_.height());
+  // Setting background size giving some extra lateral padding to the text.
+  size_.set_width((5 * kBorderFactor + kIconSizeFactor) * size_.height() +
+                  text_size.width());
+  float radius = size_.height() * kBorderFactor;
+  sk_canvas->drawRoundRect(SkRect::MakeWH(size_.width(), size_.height()),
+                           radius, radius, paint);
 
   canvas->Save();
-  canvas->Translate(
-      gfx::Vector2d(IsRTL() ? 2 * kBorderFactor * size_.height() + text_width
-                            : size_.height() * kBorderFactor,
-                    size_.height() * (1.0 - kIconSizeFactor) / 2.0));
+  canvas->Translate(gfx::Vector2d(
+      IsRTL() ? 4 * kBorderFactor * size_.height() + text_size.width()
+              : size_.height() * kBorderFactor,
+      size_.height() * (1.0 - kIconSizeFactor) / 2.0));
   PaintVectorIcon(canvas, ui::kInfoOutlineIcon,
                   size_.height() * kIconSizeFactor, kForegroundColor);
   canvas->Restore();
@@ -75,11 +72,10 @@
   canvas->Save();
   canvas->Translate(gfx::Vector2d(
       size_.height() *
-          (IsRTL() ? kBorderFactor : 2 * kBorderFactor + kIconSizeFactor),
+          (IsRTL() ? 2 * kBorderFactor : 3 * kBorderFactor + kIconSizeFactor),
       size_.height() * kBorderFactor));
-  canvas->DrawStringRectWithFlags(
-      text, fonts, kForegroundColor,
-      gfx::Rect(text_width, kTextHeightFactor * size_.height()), text_flags);
+  for (auto& render_text : lines)
+    render_text->Draw(canvas);
   canvas->Restore();
 }
 
diff --git a/chrome/browser/android/vr_shell/textures/insecure_content_transient_texture.cc b/chrome/browser/android/vr_shell/textures/insecure_content_transient_texture.cc
index 67db5ed6c..0781290 100644
--- a/chrome/browser/android/vr_shell/textures/insecure_content_transient_texture.cc
+++ b/chrome/browser/android/vr_shell/textures/insecure_content_transient_texture.cc
@@ -12,6 +12,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/render_text.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/vector_icons/vector_icons.h"
 
@@ -38,33 +39,29 @@
   gfx::Canvas* canvas = &gfx_canvas;
 
   size_.set_width(texture_size.width());
-  int max_height = texture_size.height();
-  cc::PaintFlags flags;
-  flags.setColor(kBackgroundColor);
-
-  int text_flags = gfx::Canvas::TEXT_ALIGN_CENTER | gfx::Canvas::MULTI_LINE;
+  SkPaint paint;
+  paint.setColor(kBackgroundColor);
   auto text =
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_INSECURE_WEBVR_CONTENT_TRANSIENT);
   auto fonts = GetFontList(size_.width() * kFontSizeFactor, text);
-  int text_width = size_.width() * kTextWidthFactor;
-  int text_height = 0;  // Will be increased during text measurement.
-  gfx::Canvas::SizeStringInt(text, fonts, &text_width, &text_height, 0,
-                             text_flags);
+  gfx::Rect text_size(size_.width() * kTextWidthFactor, 0);
 
-  // Making sure the drawing fits within the texture.
-  text_height = std::min(
-      text_height, static_cast<int>((1.0 - 2 * kBorderFactor) * size_.width()));
-  size_.set_height(size_.width() * 2 * kBorderFactor + text_height);
-  DCHECK_LE(size_.height(), max_height);
-  canvas->DrawRoundRect(gfx::Rect(size_.width(), size_.height()),
-                        size_.height() * kBorderFactor, flags);
+  std::vector<std::unique_ptr<gfx::RenderText>> lines =
+      PrepareDrawStringRect(text, fonts, kForegroundColor, &text_size,
+                            TEXT_ALIGN_CENTER | MULTI_LINE);
+
+  DCHECK_LE(text_size.height(),
+            static_cast<int>((1.0 - 2 * kBorderFactor) * size_.width()));
+  size_.set_height(size_.width() * 2 * kBorderFactor + text_size.height());
+  float radius = size_.height() * kBorderFactor;
+  sk_canvas->drawRoundRect(SkRect::MakeWH(size_.width(), size_.height()),
+                           radius, radius, paint);
 
   canvas->Save();
   canvas->Translate(gfx::Vector2d(size_.width() * kBorderFactor,
                                   size_.width() * kBorderFactor));
-  canvas->DrawStringRectWithFlags(
-      text, fonts, kForegroundColor,
-      gfx::Rect(kTextWidthFactor * size_.width(), text_height), text_flags);
+  for (auto& render_text : lines)
+    render_text->Draw(canvas);
   canvas->Restore();
 }
 
diff --git a/chrome/browser/android/vr_shell/textures/ui_texture.cc b/chrome/browser/android/vr_shell/textures/ui_texture.cc
index 31a36a3..4d3153c 100644
--- a/chrome/browser/android/vr_shell/textures/ui_texture.cc
+++ b/chrome/browser/android/vr_shell/textures/ui_texture.cc
@@ -12,12 +12,15 @@
 #include "base/i18n/rtl.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
+#include "base/trace_event/trace_event.h"
 #include "chrome/browser/android/vr_shell/font_fallback.h"
 #include "chrome/browser/browser_process.h"
 #include "third_party/icu/source/common/unicode/uscript.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
+#include "ui/gfx/render_text.h"
+#include "ui/gfx/text_elider.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace vr_shell {
@@ -26,6 +29,33 @@
 
 static constexpr char kDefaultFontFamily[] = "sans-serif";
 
+std::unique_ptr<gfx::RenderText> CreateRenderText(
+    const base::string16& text,
+    const gfx::FontList& font_list,
+    SkColor color,
+    int flags) {
+  std::unique_ptr<gfx::RenderText> render_text(
+      gfx::RenderText::CreateInstance());
+  render_text->SetText(text);
+  render_text->SetFontList(font_list);
+  render_text->SetColor(color);
+
+  if (flags & UiTexture::TEXT_ALIGN_LEFT)
+    render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  else if (flags & UiTexture::TEXT_ALIGN_RIGHT)
+    render_text->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
+  else if (flags & UiTexture::TEXT_ALIGN_CENTER)
+    render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+
+  const int font_style = font_list.GetFontStyle();
+  render_text->SetStyle(gfx::ITALIC, (font_style & gfx::Font::ITALIC) != 0);
+  render_text->SetStyle(gfx::UNDERLINE,
+                        (font_style & gfx::Font::UNDERLINE) != 0);
+  render_text->SetWeight(font_list.GetFontWeight());
+
+  return render_text;
+}
+
 std::set<UChar32> CollectDifferentChars(base::string16 text) {
   std::set<UChar32> characters;
   for (base::i18n::UTF16CharIterator it(&text); !it.end(); it.Advance()) {
@@ -48,10 +78,76 @@
 }
 
 void UiTexture::DrawAndLayout(SkCanvas* canvas, const gfx::Size& texture_size) {
+  TRACE_EVENT0("gpu", "UiTexture::DrawAndLayout");
   canvas->drawColor(SK_ColorTRANSPARENT);
   Draw(canvas, texture_size);
 }
 
+std::vector<std::unique_ptr<gfx::RenderText>> UiTexture::PrepareDrawStringRect(
+    const base::string16& text,
+    const gfx::FontList& font_list,
+    SkColor color,
+    gfx::Rect* bounds,
+    int flags) {
+  DCHECK(bounds);
+
+  std::vector<std::unique_ptr<gfx::RenderText>> lines;
+  gfx::Rect rect(*bounds);
+
+  if (flags & MULTI_LINE) {
+    std::vector<base::string16> strings;
+    gfx::ElideRectangleText(text, font_list, bounds->width(),
+                            bounds->height() ? bounds->height() : INT_MAX,
+                            gfx::WRAP_LONG_WORDS, &strings);
+
+    int height = 0;
+    int line_height = 0;
+    for (size_t i = 0; i < strings.size(); i++) {
+      std::unique_ptr<gfx::RenderText> render_text =
+          CreateRenderText(strings[i], font_list, color, flags);
+
+      if (i == 0) {
+        // Measure line and center text vertically.
+        line_height = render_text->GetStringSize().height();
+        rect.set_height(line_height);
+        if (bounds->height()) {
+          const int text_height = strings.size() * line_height;
+          rect += gfx::Vector2d(0, (bounds->height() - text_height) / 2);
+        }
+      }
+
+      render_text->SetDisplayRect(rect);
+      height += line_height;
+      rect += gfx::Vector2d(0, line_height);
+      lines.push_back(std::move(render_text));
+    }
+
+    // Set calculated height.
+    if (bounds->height() == 0)
+      bounds->set_height(height);
+
+  } else {
+    std::unique_ptr<gfx::RenderText> render_text =
+        CreateRenderText(text, font_list, color, flags);
+    if (bounds->width() != 0)
+      render_text->SetElideBehavior(gfx::TRUNCATE);
+    else
+      rect.set_width(INT_MAX);
+
+    render_text->SetDisplayRect(rect);
+
+    if (bounds->width() == 0) {
+      int text_width = render_text->GetStringSize().width();
+      bounds->set_width(text_width);
+      rect.set_width(text_width);
+      render_text->SetDisplayRect(rect);
+    }
+
+    lines.push_back(std::move(render_text));
+  }
+  return lines;
+}
+
 bool UiTexture::IsRTL() {
   return base::i18n::IsRTL();
 }
diff --git a/chrome/browser/android/vr_shell/textures/ui_texture.h b/chrome/browser/android/vr_shell/textures/ui_texture.h
index cfe1fc99..9fb0b0fc 100644
--- a/chrome/browser/android/vr_shell/textures/ui_texture.h
+++ b/chrome/browser/android/vr_shell/textures/ui_texture.h
@@ -6,21 +6,35 @@
 #define CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_UI_TEXTURE_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/strings/string16.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
 
 class SkCanvas;
 
 namespace gfx {
+
 class FontList;
+class RenderText;
+
 }  // namespace gfx
 
 namespace vr_shell {
 
 class UiTexture {
  public:
+  enum {
+    // Flags to configure PrepareDrawStringRect
+    TEXT_ALIGN_LEFT = 1 << 0,
+    TEXT_ALIGN_CENTER = 1 << 1,
+    TEXT_ALIGN_RIGHT = 1 << 2,
+    MULTI_LINE = 1 << 3
+  };
+
   UiTexture();
   virtual ~UiTexture();
 
@@ -28,12 +42,25 @@
   virtual gfx::Size GetPreferredTextureSize(int maximum_width) const = 0;
   virtual gfx::SizeF GetDrawnSize() const = 0;
   // Returns true if the state changed.
-  bool SetDrawFlags(int draw_flags);
+  virtual bool SetDrawFlags(int draw_flags);
   int GetDrawFlags() { return draw_flags_; }
 
  protected:
   virtual void Draw(SkCanvas* canvas, const gfx::Size& texture_size) = 0;
 
+  // Prepares a set of RenderText objects with the given color and fonts.
+  // Attempts to fit the text within the provided size. |flags| specifies how
+  // the text should be rendered. If multiline is requested and provided height
+  // is 0, it will be set to the minimum needed to fit the whole text. If
+  // multiline is not requested and provided width is 0, it will be set to the
+  // minimum needed to fit the whole text.
+  static std::vector<std::unique_ptr<gfx::RenderText>> PrepareDrawStringRect(
+      const base::string16& text,
+      const gfx::FontList& font_list,
+      SkColor color,
+      gfx::Rect* bounds,
+      int flags);
+
   static bool IsRTL();
   static gfx::FontList GetDefaultFontList(int size);
   static gfx::FontList GetFontList(int size, base::string16 text);
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc
index 4d055666..1826912 100644
--- a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc
+++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc
@@ -12,6 +12,7 @@
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/render_text.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/vector_icons/vector_icons.h"
 
@@ -19,7 +20,6 @@
 
 namespace {
 
-static constexpr SkColor kTextureBackground = 0x00AAAAAA;
 static constexpr SkColor kBackground = 0xCCAAAAAA;
 static constexpr SkColor kBackgroundHover = 0xCCDDDDDD;
 static constexpr SkColor kForeground = 0xCC444444;
@@ -62,10 +62,14 @@
 UrlBarTexture::~UrlBarTexture() = default;
 
 void UrlBarTexture::SetURL(const GURL& gurl) {
+  if (gurl_ != gurl)
+    dirty_ = true;
   gurl_ = gurl;
 }
 
 void UrlBarTexture::SetSecurityLevel(int level) {
+  if (&getSecurityIcon(security_level_) != &getSecurityIcon(level))
+    dirty_ = true;
   security_level_ = level;
 }
 
@@ -84,8 +88,6 @@
   cc::SkiaPaintCanvas paint_canvas(canvas);
   gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
 
-  canvas->drawColor(kTextureBackground);
-
   // Back button area.
   SkRRect round_rect;
   SkVector rounded_corner = {kHeight / 2, kHeight / 2};
@@ -118,8 +120,7 @@
   canvas->restore();
 
   // Site security state icon.
-  // TODO(cjgrant): Plug in the correct icons based on security level.
-  if (!gurl_.spec().empty()) {
+  if (!gurl_.is_empty()) {
     canvas->save();
     canvas->translate(
         kBackButtonWidth + kSeparatorWidth + kSecurityFieldWidth / 2,
@@ -135,16 +136,24 @@
 
   canvas->restore();
 
-  // Draw text based on pixel sizes rather than meters, for correct font sizing.
-  int pixel_font_height = texture_size.height() * kFontHeight / kHeight;
-  int text_flags = gfx::Canvas::TEXT_ALIGN_LEFT;
-  float url_x = kBackButtonWidth + kSeparatorWidth + kSecurityFieldWidth;
-  float url_width = kWidth - url_x - kUrlRightMargin;
-  gfx_canvas.DrawStringRectWithFlags(
-      base::UTF8ToUTF16(gurl_.spec()), GetDefaultFontList(pixel_font_height),
-      SK_ColorBLACK,
-      gfx::Rect(ToPixels(url_x), 0, ToPixels(url_width), ToPixels(kHeight)),
-      text_flags);
+  if (!gurl_.is_empty()) {
+    if (last_drawn_gurl_ != gurl_) {
+      // Draw text based on pixel sizes rather than meters, for correct font
+      // sizing.
+      int pixel_font_height = texture_size.height() * kFontHeight / kHeight;
+      float url_x = kBackButtonWidth + kSeparatorWidth + kSecurityFieldWidth;
+      float url_width = kWidth - url_x - kUrlRightMargin;
+      gfx::Rect text_bounds(ToPixels(url_x), 0, ToPixels(url_width),
+                            ToPixels(kHeight));
+      gurl_render_texts_ =
+          PrepareDrawStringRect(base::UTF8ToUTF16(gurl_.spec()),
+                                GetDefaultFontList(pixel_font_height),
+                                SK_ColorBLACK, &text_bounds, TEXT_ALIGN_LEFT);
+      last_drawn_gurl_ = gurl_;
+    }
+    for (auto& render_text : gurl_render_texts_)
+      render_text->Draw(&gfx_canvas);
+  }
 }
 
 gfx::Size UrlBarTexture::GetPreferredTextureSize(int maximum_width) const {
@@ -155,4 +164,10 @@
   return size_;
 }
 
+bool UrlBarTexture::SetDrawFlags(int draw_flags) {
+  if (draw_flags != GetDrawFlags())
+    dirty_ = true;
+  return UiTexture::SetDrawFlags(draw_flags);
+}
+
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.h b/chrome/browser/android/vr_shell/textures/url_bar_texture.h
index 3231f46e..0204d86 100644
--- a/chrome/browser/android/vr_shell/textures/url_bar_texture.h
+++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.h
@@ -5,10 +5,16 @@
 #ifndef CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_URL_BAR_TEXTURE_H_
 #define CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_URL_BAR_TEXTURE_H_
 
-#include "chrome/browser/android/vr_shell/textures/ui_texture.h"
+#include <memory>
+#include <vector>
 
+#include "chrome/browser/android/vr_shell/textures/ui_texture.h"
 #include "url/gurl.h"
 
+namespace gfx {
+class RenderText;
+}  // namespace gfx
+
 namespace vr_shell {
 
 class UrlBarTexture : public UiTexture {
@@ -21,17 +27,23 @@
   ~UrlBarTexture() override;
   gfx::Size GetPreferredTextureSize(int width) const override;
   gfx::SizeF GetDrawnSize() const override;
+  bool SetDrawFlags(int draw_flags) override;
 
   void SetURL(const GURL& gurl);
   void SetSecurityLevel(int level);
 
+  bool dirty() const { return dirty_; }
+
  private:
   void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override;
   float ToPixels(float meters) const;
 
   gfx::SizeF size_;
+  bool dirty_ = false;
   int security_level_;
   GURL gurl_;
+  GURL last_drawn_gurl_;
+  std::vector<std::unique_ptr<gfx::RenderText>> gurl_render_texts_;
 };
 
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/close_button.cc b/chrome/browser/android/vr_shell/ui_elements/close_button.cc
index cc2549f..ff71c55 100644
--- a/chrome/browser/android/vr_shell/ui_elements/close_button.cc
+++ b/chrome/browser/android/vr_shell/ui_elements/close_button.cc
@@ -50,7 +50,7 @@
   flags |= (down_ && hover_) ? CloseButtonTexture::FLAG_DOWN : 0;
   if (!texture_->SetDrawFlags(flags))
     return;
-  Update();
+  UpdateTexture();
 }
 
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/textured_element.cc b/chrome/browser/android/vr_shell/ui_elements/textured_element.cc
index ed30634d..82e56fc 100644
--- a/chrome/browser/android/vr_shell/ui_elements/textured_element.cc
+++ b/chrome/browser/android/vr_shell/ui_elements/textured_element.cc
@@ -22,14 +22,14 @@
   glGenTextures(1, &texture_handle_);
   DCHECK(GetTexture() != nullptr);
   texture_size_ = GetTexture()->GetPreferredTextureSize(maximum_width_);
-  Update();
+  UpdateTexture();
   set_fill(Fill::SELF);
   gfx::SizeF drawn_size = GetTexture()->GetDrawnSize();
   float y = drawn_size.height() / drawn_size.width() * size().x();
   set_size({size().x(), y, 1});
 }
 
-void TexturedElement::Update() {
+void TexturedElement::UpdateTexture() {
   sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
       texture_size_.width(), texture_size_.height());
   GetTexture()->DrawAndLayout(surface->getCanvas(), texture_size_);
diff --git a/chrome/browser/android/vr_shell/ui_elements/textured_element.h b/chrome/browser/android/vr_shell/ui_elements/textured_element.h
index d2858f3..5491f42 100644
--- a/chrome/browser/android/vr_shell/ui_elements/textured_element.h
+++ b/chrome/browser/android/vr_shell/ui_elements/textured_element.h
@@ -31,7 +31,7 @@
 
  protected:
   virtual UiTexture* GetTexture() const = 0;
-  void Update();
+  virtual void UpdateTexture();
 
  private:
   void Flush(SkSurface* surface);
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element.cc b/chrome/browser/android/vr_shell/ui_elements/ui_element.cc
index 70f582a0..6a90fd511 100644
--- a/chrome/browser/android/vr_shell/ui_elements/ui_element.cc
+++ b/chrome/browser/android/vr_shell/ui_elements/ui_element.cc
@@ -126,6 +126,8 @@
 
 void UiElement::OnButtonUp(gfx::PointF position) {}
 
+void UiElement::OnBeginFrame(const base::TimeTicks& begin_frame_time) {}
+
 void UiElement::Animate(const base::TimeTicks& time) {
   for (auto& it : animations_) {
     Animation& animation = *it;
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element.h b/chrome/browser/android/vr_shell/ui_elements/ui_element.h
index 225d5eae..2cf8a02 100644
--- a/chrome/browser/android/vr_shell/ui_elements/ui_element.h
+++ b/chrome/browser/android/vr_shell/ui_elements/ui_element.h
@@ -94,6 +94,8 @@
   UiElement();
   virtual ~UiElement();
 
+  virtual void OnBeginFrame(const base::TimeTicks& begin_frame_time);
+
   void Animate(const base::TimeTicks& time);
 
   // Indicates whether the element should be visually rendered.
diff --git a/chrome/browser/android/vr_shell/ui_elements/url_bar.cc b/chrome/browser/android/vr_shell/ui_elements/url_bar.cc
index 9e063df..ca12a32 100644
--- a/chrome/browser/android/vr_shell/ui_elements/url_bar.cc
+++ b/chrome/browser/android/vr_shell/ui_elements/url_bar.cc
@@ -9,12 +9,27 @@
 
 namespace vr_shell {
 
+namespace {
+
+// We will often get spammed with many updates. We will also get security and
+// url updates out of sync. To address both these problems, we will hang onto
+// dirtyness for |kUpdateDelay| before updating our texture to reduce visual
+// churn.
+constexpr int64_t kUpdateDelayMS = 50;
+
+}  // namespace
+
 UrlBar::UrlBar(int preferred_width)
     : TexturedElement(preferred_width),
       texture_(base::MakeUnique<UrlBarTexture>()) {}
 
 UrlBar::~UrlBar() = default;
 
+void UrlBar::UpdateTexture() {
+  TexturedElement::UpdateTexture();
+  last_update_time_ = last_begin_frame_time_;
+}
+
 UiTexture* UrlBar::GetTexture() const {
   return texture_.get();
 }
@@ -22,40 +37,38 @@
 void UrlBar::OnHoverEnter(gfx::PointF position) {
   if (!texture_->SetDrawFlags(UrlBarTexture::FLAG_HOVER))
     return;
-  Update();
+  UpdateTexture();
 }
 
 void UrlBar::OnHoverLeave() {
   if (!texture_->SetDrawFlags(0))
     return;
-  Update();
+  UpdateTexture();
 }
 
 void UrlBar::OnButtonUp(gfx::PointF position) {
   back_button_callback_.Run();
 }
 
-void UrlBar::SetEnabled(bool enabled) {
-  if (enabled && !enabled_) {
-    Update();
+void UrlBar::OnBeginFrame(const base::TimeTicks& begin_frame_time) {
+  last_begin_frame_time_ = begin_frame_time;
+  if (enabled_ && texture_->dirty()) {
+    int64_t delta_ms = (begin_frame_time - last_update_time_).InMilliseconds();
+    if (delta_ms > kUpdateDelayMS)
+      UpdateTexture();
   }
+}
+
+void UrlBar::SetEnabled(bool enabled) {
   enabled_ = enabled;
 }
 
 void UrlBar::SetURL(const GURL& gurl) {
-  // TODO(cjgrant): See if we get duplicate security level numbers, despite the
-  // source of this information being called "on changed". Also, consider
-  // delaying the texture update slighly, such that back-to-back URL and
-  // security state changes generate a single texture update instead of two.
   texture_->SetURL(gurl);
-  if (enabled_)
-    Update();
 }
 
 void UrlBar::SetSecurityLevel(int level) {
   texture_->SetSecurityLevel(level);
-  if (enabled_)
-    Update();
 }
 
 void UrlBar::SetBackButtonCallback(const base::Callback<void()>& callback) {
diff --git a/chrome/browser/android/vr_shell/ui_elements/url_bar.h b/chrome/browser/android/vr_shell/ui_elements/url_bar.h
index 3ce3d80f..790e186 100644
--- a/chrome/browser/android/vr_shell/ui_elements/url_bar.h
+++ b/chrome/browser/android/vr_shell/ui_elements/url_bar.h
@@ -9,6 +9,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "chrome/browser/android/vr_shell/ui_elements/textured_element.h"
 #include "url/gurl.h"
 
@@ -23,6 +24,7 @@
 
   void OnHoverEnter(gfx::PointF position) override;
   void OnHoverLeave() override;
+  void OnBeginFrame(const base::TimeTicks& begin_frame_time) override;
   void OnButtonUp(gfx::PointF position) override;
   void SetEnabled(bool enabled);
 
@@ -31,10 +33,13 @@
   void SetBackButtonCallback(const base::Callback<void()>& callback);
 
  private:
+  void UpdateTexture() override;
   UiTexture* GetTexture() const override;
   std::unique_ptr<UrlBarTexture> texture_;
   base::Callback<void()> back_button_callback_;
   bool enabled_ = false;
+  base::TimeTicks last_begin_frame_time_;
+  base::TimeTicks last_update_time_;
 
   DISALLOW_COPY_AND_ASSIGN(UrlBar);
 };
diff --git a/chrome/browser/android/vr_shell/ui_scene.cc b/chrome/browser/android/vr_shell/ui_scene.cc
index 07e2eff..52e3684 100644
--- a/chrome/browser/android/vr_shell/ui_scene.cc
+++ b/chrome/browser/android/vr_shell/ui_scene.cc
@@ -102,10 +102,18 @@
   }
 }
 
-void UiScene::UpdateTransforms(const base::TimeTicks& time) {
+void UiScene::OnBeginFrame(const base::TimeTicks& current_time) {
   for (const auto& element : ui_elements_) {
     // Process all animations before calculating object transforms.
-    element->Animate(time);
+    // TODO: eventually, we'd like to stop assuming that animations are
+    // element-level concepts. A single animation may simultaneously update
+    // properties on multiple elements, say.
+    element->Animate(current_time);
+
+    // Even if we're not animating, an element may wish to know about the
+    // current frame. It may throttle, for example.
+    element->OnBeginFrame(current_time);
+
     element->set_dirty(true);
   }
   for (auto& element : ui_elements_) {
diff --git a/chrome/browser/android/vr_shell/ui_scene.h b/chrome/browser/android/vr_shell/ui_scene.h
index 62fa01ad..712f0e9 100644
--- a/chrome/browser/android/vr_shell/ui_scene.h
+++ b/chrome/browser/android/vr_shell/ui_scene.h
@@ -46,10 +46,10 @@
   // Remove |animation_id| from element |element_id|.
   void RemoveAnimation(int element_id, int animation_id);
 
-  // Update the positions of all elements in the scene, according to active
-  // animations and time.  The units of time are arbitrary, but must match the
-  // unit used in animations.
-  void UpdateTransforms(const base::TimeTicks& current_time);
+  // Handles per-frame updates, giving each element the opportunity to update,
+  // if necessary (eg, for animations). NB: |current_time| is the shared,
+  // absolute begin frame time.
+  void OnBeginFrame(const base::TimeTicks& current_time);
 
   // Handle a batch of commands passed from the UI HTML.
   void HandleCommands(std::unique_ptr<base::ListValue> commands,
@@ -74,6 +74,7 @@
   void OnGLInitialized();
 
  private:
+  void Animate(const base::TimeTicks& current_time);
   void ApplyRecursiveTransforms(UiElement* element);
 
   std::vector<std::unique_ptr<UiElement>> ui_elements_;
diff --git a/chrome/browser/android/vr_shell/ui_scene_unittest.cc b/chrome/browser/android/vr_shell/ui_scene_unittest.cc
index 078650d..1f5f81d 100644
--- a/chrome/browser/android/vr_shell/ui_scene_unittest.cc
+++ b/chrome/browser/android/vr_shell/ui_scene_unittest.cc
@@ -136,7 +136,7 @@
   const gfx::Vector3dF origin(0, 0, 0);
   const gfx::Vector3dF point(1, 0, 0);
 
-  scene.UpdateTransforms(usToTicks(0));
+  scene.OnBeginFrame(usToTicks(0));
   auto new_origin = vr::MatrixVectorMul(child->TransformMatrix(), origin);
   auto new_point = vr::MatrixVectorMul(child->TransformMatrix(), point);
   EXPECT_VEC3F_NEAR(gfx::Vector3dF(6, 10, 0), new_origin);
@@ -157,7 +157,7 @@
   element->set_opacity(0.5);
   scene.AddUiElement(std::move(element));
 
-  scene.UpdateTransforms(usToTicks(0));
+  scene.OnBeginFrame(usToTicks(0));
   EXPECT_EQ(0.5f, scene.GetUiElementById(0)->computed_opacity());
   EXPECT_EQ(0.25f, scene.GetUiElementById(1)->computed_opacity());
 }
@@ -176,7 +176,7 @@
   element->set_lock_to_fov(false);
   scene.AddUiElement(std::move(element));
 
-  scene.UpdateTransforms(usToTicks(0));
+  scene.OnBeginFrame(usToTicks(0));
   EXPECT_TRUE(scene.GetUiElementById(0)->computed_lock_to_fov());
   EXPECT_TRUE(scene.GetUiElementById(1)->computed_lock_to_fov());
 }
@@ -208,7 +208,7 @@
   element->set_y_anchoring(GetParam().y_anchoring);
   scene.AddUiElement(std::move(element));
 
-  scene.UpdateTransforms(usToTicks(0));
+  scene.OnBeginFrame(usToTicks(0));
   const UiElement* child = scene.GetUiElementById(1);
   EXPECT_NEAR(GetParam().expected_x, child->GetCenter().x(), TOLERANCE);
   EXPECT_NEAR(GetParam().expected_y, child->GetCenter().y(), TOLERANCE);
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc
index 43b95b0c..c32e477 100644
--- a/chrome/browser/android/vr_shell/vr_shell.cc
+++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -11,6 +11,7 @@
 
 #include "base/android/jni_string.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
@@ -28,8 +29,11 @@
 #include "chrome/browser/android/vr_shell/vr_input_manager.h"
 #include "chrome/browser/android/vr_shell/vr_shell_delegate.h"
 #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
+#include "chrome/browser/android/vr_shell/vr_tab_helper.h"
 #include "chrome/browser/android/vr_shell/vr_usage_monitor.h"
 #include "chrome/browser/android/vr_shell/vr_web_contents_observer.h"
+#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/render_view_host.h"
@@ -62,9 +66,20 @@
 namespace {
 vr_shell::VrShell* g_instance;
 
+constexpr base::TimeDelta poll_media_access_interval_ =
+    base::TimeDelta::FromSecondsD(0.01);
+
 void SetIsInVR(content::WebContents* contents, bool is_in_vr) {
-  if (contents && contents->GetRenderWidgetHostView())
+  if (contents && contents->GetRenderWidgetHostView()) {
+    // TODO(asimjour) Contents should not be aware of VR mode. Instead, we
+    // should add a flag for disabling specific UI such as the keyboard (see
+    // VrTabHelper for details).
     contents->GetRenderWidgetHostView()->SetIsInVR(is_in_vr);
+
+    VrTabHelper* vr_tab_helper = VrTabHelper::FromWebContents(contents);
+    DCHECK(vr_tab_helper);
+    vr_tab_helper->SetIsInVr(is_in_vr);
+  }
 }
 
 void LoadControllerModelTask(
@@ -179,6 +194,7 @@
 
 VrShell::~VrShell() {
   DVLOG(1) << __FUNCTION__ << "=" << this;
+  poll_capturing_media_task_.Cancel();
   if (gamepad_source_active_) {
     device::GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory(
         device::GAMEPAD_SOURCE_GVR);
@@ -515,11 +531,46 @@
 
 void VrShell::UpdateVSyncInterval(int64_t timebase_nanos,
                                   double interval_seconds) {
+  PollMediaAccessFlag();
   PostToGlThreadWhenReady(base::Bind(&VrShellGl::UpdateVSyncInterval,
                                      gl_thread_->GetVrShellGl(), timebase_nanos,
                                      interval_seconds));
 }
 
+void VrShell::PollMediaAccessFlag() {
+  poll_capturing_media_task_.Cancel();
+
+  poll_capturing_media_task_.Reset(
+      base::Bind(&VrShell::PollMediaAccessFlag, base::Unretained(this)));
+  main_thread_task_runner_->PostDelayedTask(
+      FROM_HERE, poll_capturing_media_task_.callback(),
+      poll_media_access_interval_);
+
+  scoped_refptr<MediaStreamCaptureIndicator> indicator =
+      MediaCaptureDevicesDispatcher::GetInstance()
+          ->GetMediaStreamCaptureIndicator();
+  bool is_capturing_audio = indicator->IsCapturingAudio(web_contents_);
+  if (is_capturing_audio != is_capturing_audio_)
+    PostToGlThreadWhenReady(base::Bind(&VrShellGl::SetAudioCapturingWarning,
+                                       gl_thread_->GetVrShellGl(),
+                                       is_capturing_audio));
+  is_capturing_audio_ = is_capturing_audio;
+
+  bool is_capturing_video = indicator->IsCapturingVideo(web_contents_);
+  if (is_capturing_video != is_capturing_video_)
+    PostToGlThreadWhenReady(base::Bind(&VrShellGl::SetVideoCapturingWarning,
+                                       gl_thread_->GetVrShellGl(),
+                                       is_capturing_video));
+  is_capturing_video_ = is_capturing_video;
+
+  bool is_capturing_screen = indicator->IsBeingMirrored(web_contents_);
+  if (is_capturing_screen != is_capturing_screen_)
+    PostToGlThreadWhenReady(base::Bind(&VrShellGl::SetScreenCapturingWarning,
+                                       gl_thread_->GetVrShellGl(),
+                                       is_capturing_screen));
+  is_capturing_screen_ = is_capturing_screen;
+}
+
 void VrShell::SetContentCssSize(float width, float height, float dpr) {
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_VrShellImpl_setContentCssSize(env, j_vr_shell_.obj(), width, height,
diff --git a/chrome/browser/android/vr_shell/vr_shell.h b/chrome/browser/android/vr_shell/vr_shell.h
index ef4afa5..1837b884 100644
--- a/chrome/browser/android/vr_shell/vr_shell.h
+++ b/chrome/browser/android/vr_shell/vr_shell.h
@@ -191,6 +191,8 @@
 
   void ProcessTabArray(JNIEnv* env, jobjectArray tabs, bool incognito);
 
+  void PollMediaAccessFlag();
+
   bool vr_shell_enabled_;
 
   bool content_paused_ = false;
@@ -216,6 +218,10 @@
   bool reprojected_rendering_;
 
   jobject content_surface_ = nullptr;
+  base::CancelableClosure poll_capturing_media_task_;
+  bool is_capturing_audio_ = false;
+  bool is_capturing_video_ = false;
+  bool is_capturing_screen_ = false;
 
   // TODO(mthiesse): Remove the need for this to be stored here.
   // crbug.com/674594
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index 5296650..d91f22a 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -985,7 +985,7 @@
   }
 
   // Update the render position of all UI elements (including desktop).
-  scene_->UpdateTransforms(current_time);
+  scene_->OnBeginFrame(current_time);
 
   {
     // TODO(crbug.com/704690): Acquire controller state in a way that's timely
@@ -1378,6 +1378,18 @@
   vr_shell_renderer_->GetControllerRenderer()->SetUp(std::move(model));
 }
 
+void VrShellGl::SetAudioCapturingWarning(bool is_capturing) {
+  // TODO inform scene_;
+}
+
+void VrShellGl::SetVideoCapturingWarning(bool is_capturing) {
+  // TODO inform scene_;
+}
+
+void VrShellGl::SetScreenCapturingWarning(bool is_capturing) {
+  // TODO inform scene_;
+}
+
 void VrShellGl::OnVSync() {
   while (premature_received_frames_ > 0) {
     TRACE_EVENT0("gpu", "VrShellGl::OnWebVRFrameAvailableRetry");
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h
index c41e1eb5..17dbec9 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.h
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -108,6 +108,10 @@
   void SetSubmitClient(
       device::mojom::VRSubmitFrameClientPtrInfo submit_client_info);
 
+  void SetAudioCapturingWarning(bool is_capturing);
+  void SetVideoCapturingWarning(bool is_capturing);
+  void SetScreenCapturingWarning(bool is_capturing);
+
  private:
   void GvrInit(gvr_context* gvr_api);
   void InitializeRenderer();
diff --git a/chrome/browser/android/vr_shell/vr_tab_helper.cc b/chrome/browser/android/vr_shell/vr_tab_helper.cc
new file mode 100644
index 0000000..eef1ffb
--- /dev/null
+++ b/chrome/browser/android/vr_shell/vr_tab_helper.cc
@@ -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.
+
+#include "chrome/browser/android/vr_shell/vr_tab_helper.h"
+
+#include "chrome/browser/android/vr_shell/vr_shell_delegate.h"
+#include "device/vr/android/gvr/gvr_delegate_provider.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(vr_shell::VrTabHelper);
+
+namespace vr_shell {
+
+VrTabHelper::VrTabHelper(content::WebContents* contents) {}
+VrTabHelper::~VrTabHelper() {}
+
+void VrTabHelper::SetIsInVr(bool is_in_vr) {
+  is_in_vr_ = is_in_vr;
+}
+
+/* static */
+bool VrTabHelper::IsInVr(content::WebContents* contents) {
+  VrTabHelper* vr_tab_helper = VrTabHelper::FromWebContents(contents);
+  return vr_tab_helper->is_in_vr();
+}
+
+}  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_tab_helper.h b/chrome/browser/android/vr_shell/vr_tab_helper.h
new file mode 100644
index 0000000..f14764e
--- /dev/null
+++ b/chrome/browser/android/vr_shell/vr_tab_helper.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_VR_TAB_HELPER_H_
+#define CHROME_BROWSER_ANDROID_VR_SHELL_VR_TAB_HELPER_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace vr_shell {
+
+class VrTabHelper : public content::WebContentsUserData<VrTabHelper> {
+ public:
+  ~VrTabHelper() override;
+
+  bool is_in_vr() const { return is_in_vr_; }
+
+  // Called by VrShell when we enter and exit vr mode. It finds us by looking us
+  // up on the WebContents. Eventually, we will also set a number of flags here
+  // as we enter and exit vr mode (see TODO below).
+  void SetIsInVr(bool is_in_vr);
+
+  static bool IsInVr(content::WebContents* contents);
+
+ private:
+  friend class content::WebContentsUserData<VrTabHelper>;
+
+  explicit VrTabHelper(content::WebContents* contents);
+
+  // TODO(asimjour): once we have per-dialog flags for disabling specific
+  // content-related popups, we should hang onto a pointer to the web contents
+  // and set those flags as we enter and exit vr mode.
+  bool is_in_vr_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(VrTabHelper);
+};
+
+}  // namespace vr_shell
+
+#endif  // CHROME_BROWSER_ANDROID_VR_SHELL_VR_TAB_HELPER_H_
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 1d46c37..63324c0 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
index 919877c..4557c55 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
@@ -9,6 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
diff --git a/chrome/browser/apps/app_window_browsertest.cc b/chrome/browser/apps/app_window_browsertest.cc
index f0596bd..0ee62f5 100644
--- a/chrome/browser/apps/app_window_browsertest.cc
+++ b/chrome/browser/apps/app_window_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index cfe196177..305b5d17 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc
index 1bdfa0e..d4e42be 100644
--- a/chrome/browser/autofill/autofill_uitest_util.cc
+++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/macros.h"
 #include "chrome/browser/autofill/autofill_uitest_util.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 562caa37..29e5f01e 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -21,6 +21,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index cb9e7ff..10854ff 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -46,6 +46,8 @@
       <if expr="chromeos">
         <structure name="IDR_LOCK_HTML" file="resources\chromeos\login\lock.html" flattenhtml="true" type="chrome_html" variables="OOBE=lock" expand_variables="true"/>
         <structure name="IDR_LOCK_JS" file="resources\chromeos\login\lock.js" flattenhtml="true" type="chrome_html" variables="OOBE=lock" expand_variables="true" />
+        <structure name="IDR_MD_LOCK_HTML" file="resources\chromeos\login\md_lock.html" flattenhtml="true" type="chrome_html" variables="OOBE=md_lock" expand_variables="true"/>
+        <structure name="IDR_MD_LOCK_JS" file="resources\chromeos\login\md_lock.js" flattenhtml="true" type="chrome_html" />
         <structure name="IDR_LOGIN_HTML" file="resources\chromeos\login\login.html" flattenhtml="true" type="chrome_html" variables="OOBE=login" expand_variables="true"/>
         <structure name="IDR_LOGIN_JS" file="resources\chromeos\login\login.js" flattenhtml="true" type="chrome_html" />
         <structure name="IDR_MD_LOGIN_HTML" file="resources\chromeos\login\md_login.html" flattenhtml="true" type="chrome_html" variables="OOBE=md_login" expand_variables="true"/>
@@ -72,6 +74,8 @@
         <structure name="IDR_CUSTOM_ELEMENTS_LOGIN_JS" file="resources\chromeos\login\custom_elements_login.js" flattenhtml="true" type="chrome_html" />
         <structure name="IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_HTML" file="resources\chromeos\quick_unlock\pin_keyboard.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
         <structure name="IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_JS" file="resources\chromeos\quick_unlock\pin_keyboard.js" type="chrome_html" />
+        <structure name="IDR_MD_CUSTOM_ELEMENTS_PIN_KEYBOARD_HTML" file="resources\chromeos\quick_unlock\md_pin_keyboard.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
+        <structure name="IDR_MD_CUSTOM_ELEMENTS_PIN_KEYBOARD_JS" file="resources\chromeos\quick_unlock\md_pin_keyboard.js" type="chrome_html" />
       </if>
       <structure name="IDR_SIGNIN_SHARED_CSS_HTML" file="resources\signin\signin_shared_css.html" preprocess="true" allowexternalscript="true" type="chrome_html" />
       <if expr="not is_android and not is_ios and not chromeos">
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
index 20db697..9325148a 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_helper_browsertest.h"
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
index 8524ba33..a2ade37 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/thread_test_helper.h"
 #include "base/threading/sequenced_worker_pool.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 097f602..48f2b4f 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/guid.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 65f3961..3a4a743c 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -23,6 +23,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
diff --git a/chrome/browser/chrome_browser_main_android.cc b/chrome/browser/chrome_browser_main_android.cc
index bb13ba0..a5879bd 100644
--- a/chrome/browser/chrome_browser_main_android.cc
+++ b/chrome/browser/chrome_browser_main_android.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/trace_event/trace_event.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f16ea78..ec142f36 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1359,8 +1359,6 @@
     "system_logs/device_event_log_source.h",
     "system_logs/lsb_release_log_source.cc",
     "system_logs/lsb_release_log_source.h",
-    "system_logs/single_log_source.cc",
-    "system_logs/single_log_source.h",
     "system_logs/touch_log_source.h",
     "system_logs/touch_log_source_ozone.cc",
     "system_logs/touch_log_source_x11.cc",
@@ -1761,7 +1759,6 @@
     "status/data_promo_notification_unittest.cc",
     "system/automatic_reboot_manager_unittest.cc",
     "system/device_disabling_manager_unittest.cc",
-    "system_logs/single_log_source_unittest.cc",
     "tether/tether_service_unittest.cc",
     "ui/accessibility_focus_ring_controller_unittest.cc",
     "ui/idle_app_name_notification_view_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
index 0f0d9f0c..ff038640 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/arc/intent_helper/arc_settings_service.h"
diff --git a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
index 8627099..ffa7faab 100644
--- a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
+++ b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/customization/customization_document.h"
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index e5ffef3..45667d7 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_value_converter.h"
 #include "base/json/json_writer.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
index de39a991..182a7cd8 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind_helpers.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.cc b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
index cdfe432..a488fd7 100644
--- a/chrome/browser/chromeos/input_method/textinput_test_helper.cc
+++ b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
 #include "ash/shell.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "content/public/browser/render_view_host.h"
diff --git a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
index fe0bbbd7d..f86c942 100644
--- a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
+++ b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index f900f41..6f210290 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -221,6 +221,7 @@
     chromeos::switches::kLoginProfile,
     chromeos::switches::kNaturalScrollDefault,
     chromeos::switches::kShowMdLogin,
+    chromeos::switches::kShowNonViewMdLogin,
     chromeos::switches::kSystemInDevMode,
     policy::switches::kDeviceManagementUrl,
     wm::switches::kWindowAnimationsDisabled,
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
index 5937ed8..b540527a 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc
index 46d5ed4e..1cd1cd1 100644
--- a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/clock.h"
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
index 7780fbf8..a498e86 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -17,6 +17,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc
index fb2514d3..069bb110 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc
@@ -20,7 +20,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -41,7 +41,6 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/user_manager/user_image/user_image.h"
 #include "components/user_manager/user_manager.h"
-#include "content/public/browser/browser_thread.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia.h"
 
@@ -570,12 +569,9 @@
       profile_image_requested_(false),
       has_managed_image_(false),
       weak_factory_(this) {
-  base::SequencedWorkerPool* blocking_pool =
-      content::BrowserThread::GetBlockingPool();
-  background_task_runner_ =
-      blocking_pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          blocking_pool->GetSequenceToken(),
-          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
+  background_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+      {base::MayBlock(), base::TaskPriority::BACKGROUND,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
 }
 
 UserImageManagerImpl::~UserImageManagerImpl() {}
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
index 028da45f..87bc037 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
@@ -12,6 +12,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
diff --git a/chrome/browser/chromeos/net/client_cert_store_chromeos_unittest.cc b/chrome/browser/chromeos/net/client_cert_store_chromeos_unittest.cc
index b5d4d3c..6cd545d 100644
--- a/chrome/browser/chromeos/net/client_cert_store_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/net/client_cert_store_chromeos_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/chromeos/net/network_state_notifier_unittest.cc b/chrome/browser/chromeos/net/network_state_notifier_unittest.cc
index 3b9bfb38..ad69b86 100644
--- a/chrome/browser/chromeos/net/network_state_notifier_unittest.cc
+++ b/chrome/browser/chromeos/net/network_state_notifier_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_device_client.h"
diff --git a/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc b/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc
index ac50b96..6b0b8e94 100644
--- a/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc
+++ b/chrome/browser/chromeos/policy/recommendation_restorer_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "ash/accessibility_types.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/chromeos/system_logs/single_log_source.cc b/chrome/browser/chromeos/system_logs/single_log_source.cc
deleted file mode 100644
index 4359af8d..0000000
--- a/chrome/browser/chromeos/system_logs/single_log_source.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/system_logs/single_log_source.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/task_scheduler/post_task.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace system_logs {
-
-namespace {
-
-// Converts a logs source type to the corresponding filename. In the future, if
-// non-file source types are added, this function should return an empty string.
-std::string GetLogFileSourceFilename(SingleLogSource::SupportedSource source) {
-  switch (source) {
-    case SingleLogSource::SupportedSource::kMessages:
-      return "/var/log/messages";
-    case SingleLogSource::SupportedSource::kUiLatest:
-      return "/var/log/ui/ui.LATEST";
-  }
-}
-
-}  // namespace
-
-SingleLogSource::SingleLogSource(SupportedSource source)
-    : SystemLogsSource(GetLogFileSourceFilename(source)),
-      num_bytes_read_(0),
-      weak_ptr_factory_(this) {}
-
-SingleLogSource::~SingleLogSource() {}
-
-void SingleLogSource::Fetch(const SysLogsSourceCallback& callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(!callback.is_null());
-
-  SystemLogsResponse* response = new SystemLogsResponse;
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE,
-      base::TaskTraits(base::MayBlock(), base::TaskPriority::BACKGROUND),
-      base::Bind(&SingleLogSource::ReadFile, weak_ptr_factory_.GetWeakPtr(),
-                 response),
-      base::Bind(callback, base::Owned(response)));
-}
-
-void SingleLogSource::ReadFile(SystemLogsResponse* result) {
-  // Attempt to open the file if it was not previously opened.
-  if (!file_.IsValid()) {
-    file_.Initialize(base::FilePath(source_name()),
-                     base::File::FLAG_OPEN | base::File::FLAG_READ);
-    if (!file_.IsValid())
-      return;
-  }
-
-  // Check for file size reset.
-  const size_t length = file_.GetLength();
-  if (length < num_bytes_read_) {
-    num_bytes_read_ = 0;
-    file_.Seek(base::File::FROM_BEGIN, 0);
-  }
-
-  // Read from file until end.
-  const size_t size_to_read = length - num_bytes_read_;
-  std::string result_string;
-  result_string.resize(size_to_read);
-  const size_t size_read =
-      file_.ReadAtCurrentPos(&result_string[0], size_to_read);
-  result_string.resize(size_read);
-
-  // The reader may only read complete lines.
-  if (result_string.empty() || result_string.back() != '\n') {
-    // If an incomplete line was read, reset the file read offset to before the
-    // most recent read.
-    file_.Seek(base::File::FROM_CURRENT, -size_read);
-    result->emplace(source_name(), "");
-    return;
-  }
-
-  num_bytes_read_ += size_read;
-
-  // Pass it back to the callback.
-  result->emplace(source_name(), anonymizer_.Anonymize(result_string));
-}
-
-}  // namespace system_logs
diff --git a/chrome/browser/chromeos/system_logs/single_log_source.h b/chrome/browser/chromeos/system_logs/single_log_source.h
deleted file mode 100644
index 18b4cc5f..0000000
--- a/chrome/browser/chromeos/system_logs/single_log_source.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SINGLE_LOG_SOURCE_H_
-#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SINGLE_LOG_SOURCE_H_
-
-#include <stddef.h>
-
-#include "base/files/file.h"
-#include "base/macros.h"
-#include "chrome/browser/feedback/system_logs/system_logs_fetcher_base.h"
-#include "components/feedback/anonymizer_tool.h"
-
-namespace system_logs {
-
-// Gathers log data from a single source, possibly incrementally.
-class SingleLogSource : public SystemLogsSource {
- public:
-  enum class SupportedSource {
-    // For /var/log/messages.
-    kMessages,
-
-    // For /var/log/ui/ui.LATEST.
-    kUiLatest,
-  };
-
-  explicit SingleLogSource(SupportedSource source);
-  ~SingleLogSource() override;
-
-  // system_logs::SystemLogsSource:
-  void Fetch(const SysLogsSourceCallback& callback) override;
-
- private:
-  friend class SingleLogSourceTest;
-
-  // Reads all available content from |file_| that has not already been read.
-  void ReadFile(SystemLogsResponse* result);
-
-  // Keeps track of how much data has been read from |file_|.
-  size_t num_bytes_read_;
-
-  // Handle for reading the log file that is source of logging data.
-  base::File file_;
-
-  // For removing PII from log results.
-  feedback::AnonymizerTool anonymizer_;
-
-  base::WeakPtrFactory<SingleLogSource> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleLogSource);
-};
-
-}  // namespace system_logs
-
-#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SINGLE_LOG_SOURCE_H_
diff --git a/chrome/browser/chromeos/system_logs/single_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/single_log_source_unittest.cc
deleted file mode 100644
index 2ccda01a9..0000000
--- a/chrome/browser/chromeos/system_logs/single_log_source_unittest.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/system_logs/single_log_source.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace system_logs {
-
-class SingleLogSourceTest : public ::testing::Test {
- public:
-  SingleLogSourceTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        source_(SingleLogSource::SupportedSource::kMessages),
-        num_callback_calls_(0) {
-    CHECK(dir_.CreateUniqueTempDir());
-    log_file_path_ = dir_.GetPath().Append("log_file");
-
-    // Create the dummy log file for writing.
-    base::File new_file;
-    new_file.Initialize(log_file_path_, base::File::FLAG_CREATE_ALWAYS |
-                                            base::File::FLAG_WRITE);
-    new_file.Close();
-    CHECK(base::PathExists(log_file_path_));
-
-    // Open the dummy log file for reading from within the log source.
-    source_.file_.Initialize(log_file_path_,
-                             base::File::FLAG_OPEN | base::File::FLAG_READ);
-    CHECK(source_.file_.IsValid());
-  }
-
-  ~SingleLogSourceTest() override {}
-
-  // Writes a string to |log_file_path_|.
-  bool WriteFile(const std::string& input) {
-    return base::WriteFile(log_file_path_, input.data(), input.size());
-  }
-  // Appends a string to |log_file_path_|.
-  bool AppendToFile(const std::string& input) {
-    return base::AppendToFile(log_file_path_, input.data(), input.size());
-  }
-
-  // Calls source_.Fetch() to start a logs fetch operation. Passes in
-  // OnFileRead() as a callback. Runs until Fetch() has completed.
-  void FetchFromSource() {
-    source_.Fetch(
-        base::Bind(&SingleLogSourceTest::OnFileRead, base::Unretained(this)));
-    scoped_task_environment_.RunUntilIdle();
-  }
-
-  // Callback for fetching logs from |source_|. Overwrites the previous stored
-  // value of |latest_response_|.
-  void OnFileRead(SystemLogsResponse* response) {
-    ++num_callback_calls_;
-    if (response->empty())
-      return;
-
-    // Since |source_| represents a single log source, it should only return a
-    // single string result.
-    EXPECT_EQ(1U, response->size());
-    latest_response_ = std::move(response->begin()->second);
-  }
-
-  int num_callback_calls() const { return num_callback_calls_; }
-
-  const std::string& latest_response() const { return latest_response_; }
-
-  const base::FilePath& log_file_path() const { return log_file_path_; }
-
- private:
-  // For running scheduled tasks.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  // Creates the necessary browser threads. Defined after
-  // |scoped_task_environment_| in order to use the MessageLoop it created.
-  content::TestBrowserThreadBundle browser_thread_bundle_;
-
-  // Unit under test.
-  SingleLogSource source_;
-
-  // Counts the number of times that |source_| has invoked the callback.
-  int num_callback_calls_;
-
-  // Stores the string response returned from |source_| the last time it invoked
-  // OnFileRead.
-  std::string latest_response_;
-
-  // Temporary dir for creating a dummy log file.
-  base::ScopedTempDir dir_;
-
-  // Path to the dummy log file in |dir_|.
-  base::FilePath log_file_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleLogSourceTest);
-};
-
-TEST_F(SingleLogSourceTest, EmptyFile) {
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("", latest_response());
-}
-
-TEST_F(SingleLogSourceTest, SingleRead) {
-  EXPECT_TRUE(AppendToFile("Hello world!\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("Hello world!\n", latest_response());
-}
-
-TEST_F(SingleLogSourceTest, IncrementalReads) {
-  EXPECT_TRUE(AppendToFile("Hello world!\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("Hello world!\n", latest_response());
-
-  EXPECT_TRUE(AppendToFile("The quick brown fox jumps over the lazy dog\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(2, num_callback_calls());
-  EXPECT_EQ("The quick brown fox jumps over the lazy dog\n", latest_response());
-
-  EXPECT_TRUE(AppendToFile("Some like it hot.\nSome like it cold\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(3, num_callback_calls());
-  EXPECT_EQ("Some like it hot.\nSome like it cold\n", latest_response());
-
-  // As a sanity check, read entire contents of file separately to make sure it
-  // was written incrementally, and hence read incrementally.
-  std::string file_contents;
-  EXPECT_TRUE(base::ReadFileToString(log_file_path(), &file_contents));
-  EXPECT_EQ(
-      "Hello world!\nThe quick brown fox jumps over the lazy dog\n"
-      "Some like it hot.\nSome like it cold\n",
-      file_contents);
-}
-
-// The log files read by SingleLogSource are not expected to be overwritten.
-// This test is just to ensure that the SingleLogSource class is robust enough
-// not to break in the event of an overwrite.
-TEST_F(SingleLogSourceTest, FileOverwrite) {
-  EXPECT_TRUE(AppendToFile("0123456789\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("0123456789\n", latest_response());
-
-  // Overwrite the file.
-  EXPECT_TRUE(WriteFile("abcdefg\n"));
-  FetchFromSource();
-
-  // Should re-read from the beginning.
-  EXPECT_EQ(2, num_callback_calls());
-  EXPECT_EQ("abcdefg\n", latest_response());
-
-  // Append to the file to make sure incremental read still works.
-  EXPECT_TRUE(AppendToFile("hijk\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(3, num_callback_calls());
-  EXPECT_EQ("hijk\n", latest_response());
-
-  // Overwrite again, this time with a longer length than the existing file.
-  // Previous contents:
-  //   abcdefg~hijk~     <-- "~" is a single-char representation of newline.
-  // New contents:
-  //   lmnopqrstuvwxyz~  <-- excess text beyond end of prev contents: "yz~"
-  EXPECT_TRUE(WriteFile("lmnopqrstuvwxyz\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(4, num_callback_calls());
-  EXPECT_EQ("yz\n", latest_response());
-}
-
-TEST_F(SingleLogSourceTest, IncompleteLines) {
-  EXPECT_TRUE(AppendToFile("0123456789"));
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("", latest_response());
-
-  EXPECT_TRUE(AppendToFile("abcdefg"));
-  FetchFromSource();
-
-  EXPECT_EQ(2, num_callback_calls());
-  EXPECT_EQ("", latest_response());
-
-  EXPECT_TRUE(AppendToFile("hijk\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(3, num_callback_calls());
-  // All the previously written text should be read this time.
-  EXPECT_EQ("0123456789abcdefghijk\n", latest_response());
-
-  EXPECT_TRUE(AppendToFile("Hello world\n"));
-  EXPECT_TRUE(AppendToFile("Goodbye world"));
-  FetchFromSource();
-
-  // Partial whole-line reads are not supported. The last byte of the read must
-  // be a new line.
-  EXPECT_EQ(4, num_callback_calls());
-  EXPECT_EQ("", latest_response());
-
-  EXPECT_TRUE(AppendToFile("\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(5, num_callback_calls());
-  EXPECT_EQ("Hello world\nGoodbye world\n", latest_response());
-}
-
-TEST_F(SingleLogSourceTest, Anonymize) {
-  EXPECT_TRUE(AppendToFile("My MAC address is: 11:22:33:44:55:66\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(1, num_callback_calls());
-  EXPECT_EQ("My MAC address is: 11:22:33:00:00:01\n", latest_response());
-
-  // Suppose the write operation is not atomic, and the MAC address is written
-  // across two separate writes.
-  EXPECT_TRUE(AppendToFile("Your MAC address is: AB:88:C"));
-  FetchFromSource();
-
-  EXPECT_EQ(2, num_callback_calls());
-  EXPECT_EQ("", latest_response());
-
-  EXPECT_TRUE(AppendToFile("D:99:EF:77\n"));
-  FetchFromSource();
-
-  EXPECT_EQ(3, num_callback_calls());
-  EXPECT_EQ("Your MAC address is: ab:88:cd:00:00:02\n", latest_response());
-}
-
-}  // namespace system_logs
diff --git a/chrome/browser/conflicts/module_inspector_win_unittest.cc b/chrome/browser/conflicts/module_inspector_win_unittest.cc
index 017c619..39cc4f7 100644
--- a/chrome/browser/conflicts/module_inspector_win_unittest.cc
+++ b/chrome/browser/conflicts/module_inspector_win_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/environment.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_scheduler.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc b/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
index 2cd47931..3da5dc8 100644
--- a/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
+++ b/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/devtools/device/adb/adb_device_provider.h"
 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
diff --git a/chrome/browser/devtools/device/adb/mock_adb_server.cc b/chrome/browser/devtools/device/adb/mock_adb_server.cc
index e0380ffa..88658a3 100644
--- a/chrome/browser/devtools/device/adb/mock_adb_server.cc
+++ b/chrome/browser/devtools/device/adb/mock_adb_server.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc
index e75e0d3..77e12e9 100644
--- a/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -11,6 +11,7 @@
 
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/devtools/device/port_forwarding_browsertest.cc b/chrome/browser/devtools/device/port_forwarding_browsertest.cc
index 475c52c..016b64b 100644
--- a/chrome/browser/devtools/device/port_forwarding_browsertest.cc
+++ b/chrome/browser/devtools/device/port_forwarding_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index 370b294..d733496 100644
--- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -11,6 +11,7 @@
 
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index ec98831..5ac3e8a1 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
index 62c3b1b..f8745e28 100644
--- a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
diff --git a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
index 4d98433..83085ff 100644
--- a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
+++ b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 09c9855..c627089d 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -23,6 +23,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index e4b9949..d6b4131 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/command_line.h"
 #include "base/location.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_split.h"
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index e3f1672a..c0850d7a 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/location.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/stringprintf.h"
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 557969f6..725dc57 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -23,6 +23,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
index 6ce18ce6..78d9b7b 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 68f42d9..803e0325 100644
--- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/extensions/api/socket/udp_socket_unittest.cc b/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
index c02ad14..27fd028 100644
--- a/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/udp_socket_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/test_timeouts.h"
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
index c5d05775..3a0266d6 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -4,6 +4,7 @@
 
 #include "base/command_line.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_timeouts.h"
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index 77edc91..f14ef646 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -11,6 +11,7 @@
 
 #include "apps/test/app_window_waiter.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
index ce4c056..e0f47f99 100644
--- a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
+++ b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index f2ee8aab..b29f88d 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/extensions/app_data_migrator_unittest.cc b/chrome/browser/extensions/app_data_migrator_unittest.cc
index 0bea1900..2ed85f6 100644
--- a/chrome/browser/extensions/app_data_migrator_unittest.cc
+++ b/chrome/browser/extensions/app_data_migrator_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/callback_forward.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 9e32e0d..296b1a0 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/extensions/error_console/error_console_browsertest.cc b/chrome/browser/extensions/error_console/error_console_browsertest.cc
index 87785665..bea3f47 100644
--- a/chrome/browser/extensions/error_console/error_console_browsertest.cc
+++ b/chrome/browser/extensions/error_console/error_console_browsertest.cc
@@ -8,6 +8,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index a870c20..cbd6545 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -28,6 +28,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/chrome/browser/extensions/extension_storage_monitor_browsertest.cc b/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
index b9671a8..0a356e4 100644
--- a/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
+++ b/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include <set>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
diff --git a/chrome/browser/extensions/extension_user_script_loader_unittest.cc b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
index 878eedd..ffeb5de4 100644
--- a/chrome/browser/extensions/extension_user_script_loader_unittest.cc
+++ b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.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_util.h"
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index fd14606..d200836 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
diff --git a/chrome/browser/geolocation/access_token_store_browsertest.cc b/chrome/browser/geolocation/access_token_store_browsertest.cc
index 3ad8692..86c5463f 100644
--- a/chrome/browser/geolocation/access_token_store_browsertest.cc
+++ b/chrome/browser/geolocation/access_token_store_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/geolocation/chrome_access_token_store.h"
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index c8d635d..34efb8e6 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -8,6 +8,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/history/android/sqlite_cursor_unittest.cc b/chrome/browser/history/android/sqlite_cursor_unittest.cc
index 6f657b38..84e65e7f 100644
--- a/chrome/browser/history/android/sqlite_cursor_unittest.cc
+++ b/chrome/browser/history/android/sqlite_cursor_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/android/jni_string.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/strings/utf_string_conversions.h"
 #include "base/task/cancelable_task_tracker.h"
diff --git a/chrome/browser/history/redirect_browsertest.cc b/chrome/browser/history/redirect_browsertest.cc
index ba0e687..e41893f 100644
--- a/chrome/browser/history/redirect_browsertest.cc
+++ b/chrome/browser/history/redirect_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc
index 8a48a67..6ea126f 100644
--- a/chrome/browser/importer/profile_writer_unittest.cc
+++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
diff --git a/chrome/browser/local_discovery/local_domain_resolver_unittest.cc b/chrome/browser/local_discovery/local_domain_resolver_unittest.cc
index 241c3a1..e3dec70 100644
--- a/chrome/browser/local_discovery/local_domain_resolver_unittest.cc
+++ b/chrome/browser/local_discovery/local_domain_resolver_unittest.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.mm b/chrome/browser/local_discovery/service_discovery_client_mac.mm
index 23f77f5..f5cbf5ad 100644
--- a/chrome/browser/local_discovery/service_discovery_client_mac.mm
+++ b/chrome/browser/local_discovery/service_discovery_client_mac.mm
@@ -12,6 +12,7 @@
 
 #include "base/debug/dump_without_crashing.h"
 #include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/chrome/browser/local_discovery/service_discovery_client_unittest.cc b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
index 1ac644f..c252f465 100644
--- a/chrome/browser/local_discovery/service_discovery_client_unittest.cc
+++ b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/location.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
index 562dcd5..c5a5371 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
@@ -26,22 +26,29 @@
   DCHECK(request_context_);
 }
 
-DialMediaSinkService::~DialMediaSinkService() {}
+DialMediaSinkService::~DialMediaSinkService() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  Stop();
+}
 
 void DialMediaSinkService::Start() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  dial_registry()->RegisterObserver(this);
-  dial_registry()->StartPeriodicDiscovery();
+  if (dial_registry_)
+    return;
+
+  dial_registry_ = DialRegistry::GetInstance();
+  dial_registry_->RegisterObserver(this);
+  dial_registry_->OnListenerAdded();
 }
 
 void DialMediaSinkService::Stop() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  dial_registry()->UnregisterObserver(this);
-}
+  if (!dial_registry_)
+    return;
 
-DialRegistry* DialMediaSinkService::dial_registry() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  return DialRegistry::GetInstance();
+  dial_registry_->OnListenerRemoved();
+  dial_registry_->UnregisterObserver(this);
+  dial_registry_ = nullptr;
 }
 
 DeviceDescriptionService* DialMediaSinkService::GetDescriptionService() {
@@ -56,18 +63,33 @@
   return description_service_.get();
 }
 
+void DialMediaSinkService::SetDialRegistryForTest(DialRegistry* dial_registry) {
+  DCHECK(!dial_registry_);
+  dial_registry_ = dial_registry;
+
+  DCHECK(dial_registry);
+  dial_registry_->RegisterObserver(this);
+  dial_registry_->OnListenerAdded();
+}
+
+void DialMediaSinkService::SetDescriptionServiceForTest(
+    std::unique_ptr<DeviceDescriptionService> description_service) {
+  DCHECK(!description_service_);
+  description_service_ = std::move(description_service);
+}
+
+void DialMediaSinkService::SetTimerForTest(std::unique_ptr<base::Timer> timer) {
+  DCHECK(!finish_timer_);
+  finish_timer_ = std::move(timer);
+}
+
 void DialMediaSinkService::OnDialDeviceEvent(
     const DialRegistry::DeviceList& devices) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(2) << "DialMediaSinkService::OnDialDeviceEvent found " << devices.size()
            << " devices";
 
-  // Add a finish timer.
-  finish_timer_.reset(new base::OneShotTimer());
-  base::TimeDelta finish_delay =
-      base::TimeDelta::FromSeconds(kFetchCompleteTimeoutSecs);
-  finish_timer_->Start(FROM_HERE, finish_delay, this,
-                       &DialMediaSinkService::OnFetchCompleted);
+  StartTimer();
 
   current_sinks_.clear();
   current_devices_ = devices;
@@ -107,16 +129,10 @@
 
   current_sinks_.insert(MediaSinkInternal(sink, extra_data));
 
-  if (finish_timer_)
-    return;
-
   // Start fetch timer again if device description comes back after
   // |finish_timer_| fires.
-  base::TimeDelta finish_delay =
-      base::TimeDelta::FromSeconds(kFetchCompleteTimeoutSecs);
-  finish_timer_.reset(new base::OneShotTimer());
-  finish_timer_->Start(FROM_HERE, finish_delay, this,
-                       &DialMediaSinkService::OnFetchCompleted);
+  if (!finish_timer_->IsRunning())
+    StartTimer();
 }
 
 void DialMediaSinkService::OnDeviceDescriptionError(
@@ -127,21 +143,29 @@
 }
 
 void DialMediaSinkService::OnFetchCompleted() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!sink_discovery_callback_.is_null());
 
-  finish_timer_.reset();
-
-  auto sinks = current_sinks_;
-  if (sinks == mrp_sinks_) {
+  if (current_sinks_ == mrp_sinks_) {
     DVLOG(2) << "No update to sink list.";
     return;
   }
 
-  DVLOG(2) << "Send sinks to media router, [size]: " << sinks.size();
-  sink_discovery_callback_.Run(
-      std::vector<MediaSinkInternal>(sinks.begin(), sinks.end()));
-  mrp_sinks_ = std::move(sinks);
+  DVLOG(2) << "Send sinks to media router, [size]: " << current_sinks_.size();
+  sink_discovery_callback_.Run(std::vector<MediaSinkInternal>(
+      current_sinks_.begin(), current_sinks_.end()));
+  mrp_sinks_ = current_sinks_;
+}
+
+void DialMediaSinkService::StartTimer() {
+  // Create a finish timer.
+  if (!finish_timer_)
+    finish_timer_.reset(new base::OneShotTimer());
+
+  base::TimeDelta finish_delay =
+      base::TimeDelta::FromSeconds(kFetchCompleteTimeoutSecs);
+  finish_timer_->Start(FROM_HERE, finish_delay,
+                       base::Bind(&DialMediaSinkService::OnFetchCompleted,
+                                  base::Unretained(this)));
 }
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.h b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.h
index 86f72c5..75bf0f0 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.h
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.h
@@ -28,22 +28,30 @@
                        net::URLRequestContextGetter* request_context);
   ~DialMediaSinkService() override;
 
+  // Stops listening for DIAL device events.
+  virtual void Stop();
+
   // MediaSinkService implementation
   void Start() override;
 
-  void Stop();
-
  protected:
-  virtual DialRegistry* dial_registry();
 
   // Returns instance of device description service. Create a new one if none
   // exists.
-  virtual DeviceDescriptionService* GetDescriptionService();
+  DeviceDescriptionService* GetDescriptionService();
+
+  // Does not take ownership of |dial_registry|.
+  void SetDialRegistryForTest(DialRegistry* dial_registry);
+  void SetDescriptionServiceForTest(
+      std::unique_ptr<DeviceDescriptionService> description_service);
+  void SetTimerForTest(std::unique_ptr<base::Timer> timer);
 
  private:
   friend class DialMediaSinkServiceTest;
   FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest, TestStart);
-  FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest, TestFetchCompleted);
+  FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest, TestTimer);
+  FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest,
+                           TestFetchCompleted_SameSink);
   FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest, TestIsDifferent);
   FRIEND_TEST_ALL_PREFIXES(DialMediaSinkServiceTest,
                            TestOnDeviceDescriptionAvailable);
@@ -65,13 +73,19 @@
   // Called when |finish_timer_| expires.
   void OnFetchCompleted();
 
+  // Helper function to start |finish_timer_|.
+  void StartTimer();
+
   // Timer for finishing fetching. Starts in |OnDialDeviceEvent()|, and expires
   // 3 seconds later. If |OnDeviceDescriptionAvailable()| is called after
   // |finish_timer_| expires, |finish_timer_| is restarted.
-  std::unique_ptr<base::OneShotTimer> finish_timer_;
+  std::unique_ptr<base::Timer> finish_timer_;
 
   std::unique_ptr<DeviceDescriptionService> description_service_;
 
+  // Raw pointer to DialRegistry singleton.
+  DialRegistry* dial_registry_ = nullptr;
+
   // Sorted sinks from current round of discovery.
   std::set<MediaSinkInternal> current_sinks_;
 
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc
index cf542a8..acebc86a 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/media/router/discovery/dial/dial_media_sink_service.h"
 #include "base/test/mock_callback.h"
+#include "base/timer/mock_timer.h"
 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h"
 #include "chrome/browser/media/router/discovery/dial/dial_registry.h"
 #include "chrome/browser/media/router/test_helper.h"
@@ -56,6 +57,9 @@
 
   MOCK_METHOD1(RegisterObserver, void(DialRegistry::Observer* observer));
   MOCK_METHOD1(UnregisterObserver, void(DialRegistry::Observer* observer));
+
+  MOCK_METHOD0(OnListenerAdded, void());
+  MOCK_METHOD0(OnListenerRemoved, void());
 };
 
 class MockDeviceDescriptionService : public DeviceDescriptionService {
@@ -70,48 +74,46 @@
                     net::URLRequestContextGetter* request_context));
 };
 
-class TestDialMediaSinkService : public DialMediaSinkService {
- public:
-  TestDialMediaSinkService(
-      const MediaSinkService::OnSinksDiscoveredCallback& callback,
-      net::URLRequestContextGetter* request_context,
-      TestDialRegistry* test_dial_registry,
-      MockDeviceDescriptionService* mock_description_service)
-      : DialMediaSinkService(callback, request_context),
-        test_dial_registry_(test_dial_registry),
-        mock_description_service_(mock_description_service) {}
-
-  DialRegistry* dial_registry() override { return test_dial_registry_; }
-
-  DeviceDescriptionService* GetDescriptionService() override {
-    return mock_description_service_;
-  }
-
- private:
-  TestDialRegistry* test_dial_registry_;
-  MockDeviceDescriptionService* mock_description_service_;
-};
-
 class DialMediaSinkServiceTest : public ::testing::Test {
  public:
   DialMediaSinkServiceTest()
       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
-        mock_description_service_(mock_success_cb_.Get(), mock_error_cb_.Get()),
-        media_sink_service_(mock_sink_discovered_cb_.Get(),
-                            profile_.GetRequestContext(),
-                            &test_dial_registry_,
-                            &mock_description_service_) {}
+        media_sink_service_(
+            new DialMediaSinkService(mock_sink_discovered_cb_.Get(),
+                                     profile_.GetRequestContext())) {}
 
-  DialMediaSinkService* media_sink_service() { return &media_sink_service_; }
+  void SetUp() override {
+    EXPECT_CALL(test_dial_registry_,
+                RegisterObserver(media_sink_service_.get()));
+    EXPECT_CALL(test_dial_registry_, OnListenerAdded());
+
+    media_sink_service_->SetDialRegistryForTest(&test_dial_registry_);
+
+    auto mock_description_service =
+        base::MakeUnique<MockDeviceDescriptionService>(mock_success_cb_.Get(),
+                                                       mock_error_cb_.Get());
+    mock_description_service_ = mock_description_service.get();
+    media_sink_service_->SetDescriptionServiceForTest(
+        std::move(mock_description_service));
+    mock_timer_ =
+        new base::MockTimer(true /*retain_user_task*/, false /*is_repeating*/);
+    media_sink_service_->SetTimerForTest(base::WrapUnique(mock_timer_));
+  }
+
+  void TearDown() override {
+    EXPECT_CALL(test_dial_registry_,
+                UnregisterObserver(media_sink_service_.get()));
+    EXPECT_CALL(test_dial_registry_, OnListenerRemoved());
+  }
 
   void TestFetchCompleted(const std::vector<MediaSinkInternal>& old_sinks,
                           const std::vector<MediaSinkInternal>& new_sinks) {
-    media_sink_service()->mrp_sinks_ =
+    media_sink_service_->mrp_sinks_ =
         std::set<MediaSinkInternal>(old_sinks.begin(), old_sinks.end());
-    media_sink_service()->current_sinks_ =
+    media_sink_service_->current_sinks_ =
         std::set<MediaSinkInternal>(new_sinks.begin(), new_sinks.end());
     EXPECT_CALL(mock_sink_discovered_cb_, Run(new_sinks));
-    media_sink_service()->OnFetchCompleted();
+    media_sink_service_->OnFetchCompleted();
   }
 
  protected:
@@ -128,14 +130,16 @@
       mock_error_cb_;
 
   TestDialRegistry test_dial_registry_;
-  MockDeviceDescriptionService mock_description_service_;
+  MockDeviceDescriptionService* mock_description_service_;
+  base::MockTimer* mock_timer_;
 
-  TestDialMediaSinkService media_sink_service_;
+  std::unique_ptr<DialMediaSinkService> media_sink_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(DialMediaSinkServiceTest);
 };
 
 TEST_F(DialMediaSinkServiceTest, TestStart) {
-  EXPECT_CALL(test_dial_registry_, RegisterObserver(&media_sink_service_));
-  media_sink_service()->Start();
+  media_sink_service_->Start();
 
   DialRegistry::DeviceList deviceList;
   DialDeviceData first_device("first", GURL("http://127.0.0.1/dd.xml"),
@@ -148,10 +152,10 @@
   deviceList.push_back(second_device);
   deviceList.push_back(third_device);
 
-  EXPECT_CALL(mock_description_service_, GetDeviceDescriptions(deviceList, _));
+  EXPECT_CALL(*mock_description_service_, GetDeviceDescriptions(deviceList, _));
 
-  media_sink_service()->OnDialDeviceEvent(deviceList);
-  EXPECT_TRUE(media_sink_service_.finish_timer_->IsRunning());
+  media_sink_service_->OnDialDeviceEvent(deviceList);
+  EXPECT_TRUE(media_sink_service_->finish_timer_->IsRunning());
 }
 
 TEST_F(DialMediaSinkServiceTest, TestOnDeviceDescriptionAvailable) {
@@ -163,28 +167,56 @@
   device_description.app_url = GURL("http://192.168.1.1/apps");
   device_description.unique_id = "unique id";
 
-  media_sink_service()->OnDeviceDescriptionAvailable(device_data,
-                                                     device_description);
-  EXPECT_TRUE(media_sink_service()->current_sinks_.empty());
+  media_sink_service_->OnDeviceDescriptionAvailable(device_data,
+                                                    device_description);
+  EXPECT_TRUE(media_sink_service_->current_sinks_.empty());
 
   std::vector<DialDeviceData> deviceList{device_data};
-  EXPECT_CALL(mock_description_service_, GetDeviceDescriptions(deviceList, _));
+  EXPECT_CALL(*mock_description_service_, GetDeviceDescriptions(deviceList, _));
 
-  media_sink_service()->OnDialDeviceEvent(deviceList);
-  media_sink_service()->OnDeviceDescriptionAvailable(device_data,
-                                                     device_description);
+  media_sink_service_->OnDialDeviceEvent(deviceList);
+  media_sink_service_->OnDeviceDescriptionAvailable(device_data,
+                                                    device_description);
 
-  EXPECT_EQ(size_t(1), media_sink_service()->current_sinks_.size());
+  EXPECT_EQ(size_t(1), media_sink_service_->current_sinks_.size());
 }
 
-TEST_F(DialMediaSinkServiceTest, TestFetchCompleted) {
+TEST_F(DialMediaSinkServiceTest, TestTimer) {
+  DialDeviceData device_data("first", GURL("http://127.0.0.1/dd.xml"),
+                             base::Time::Now());
+  ParsedDialDeviceDescription device_description;
+  device_description.model_name = "model name";
+  device_description.friendly_name = "friendly name";
+  device_description.app_url = GURL("http://192.168.1.1/apps");
+  device_description.unique_id = "unique id";
+
+  std::vector<DialDeviceData> deviceList{device_data};
+  EXPECT_CALL(*mock_description_service_, GetDeviceDescriptions(deviceList, _));
+
+  EXPECT_FALSE(mock_timer_->IsRunning());
+  media_sink_service_->OnDialDeviceEvent(deviceList);
+  media_sink_service_->OnDeviceDescriptionAvailable(device_data,
+                                                    device_description);
+  EXPECT_TRUE(mock_timer_->IsRunning());
+
+  EXPECT_CALL(mock_sink_discovered_cb_, Run(_));
+  mock_timer_->Fire();
+
+  EXPECT_FALSE(mock_timer_->IsRunning());
+  device_description.app_url = GURL("http://192.168.1.11/apps");
+  media_sink_service_->OnDeviceDescriptionAvailable(device_data,
+                                                    device_description);
+  EXPECT_TRUE(mock_timer_->IsRunning());
+}
+
+TEST_F(DialMediaSinkServiceTest, TestFetchCompleted_SameSink) {
   std::vector<MediaSinkInternal> old_sinks;
   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
   TestFetchCompleted(old_sinks, new_sinks);
 
   // Same sink
   EXPECT_CALL(mock_sink_discovered_cb_, Run(new_sinks)).Times(0);
-  media_sink_service()->OnFetchCompleted();
+  media_sink_service_->OnFetchCompleted();
 }
 
 TEST_F(DialMediaSinkServiceTest, TestFetchCompleted_OneNewSink) {
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.h b/chrome/browser/media/router/discovery/dial/dial_registry.h
index 93afe541..f981fbb 100644
--- a/chrome/browser/media/router/discovery/dial/dial_registry.h
+++ b/chrome/browser/media/router/discovery/dial/dial_registry.h
@@ -62,8 +62,8 @@
   // Called by the DIAL API when event listeners are added or removed. The dial
   // service is started after the first listener is added and stopped after the
   // last listener is removed.
-  void OnListenerAdded();
-  void OnListenerRemoved();
+  virtual void OnListenerAdded();
+  virtual void OnListenerRemoved();
 
   // pass a reference of |observer| to allow it to notify on DIAL device events.
   // This class does not take ownership of observer.
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
index 183441a..07323f8 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
index 77e52ca..94f1ac5f 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
@@ -15,6 +15,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/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.cc b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
index aef50dc..39a0f0cb 100644
--- a/chrome/browser/memory/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
@@ -636,8 +636,6 @@
         MemoryKillsMonitor::LogLowMemoryKill("TAB", estimated_memory_freed_kb);
         MEMORY_LOG(ERROR) << "Killed " << *it << ", estimated "
                           << estimated_memory_freed_kb << " KB freed";
-      } else {
-        MEMORY_LOG(ERROR) << "Failed to kill " << *it;
       }
     }
   }
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 4a2fb00e..0842a5e 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/metrics/https_engagement_metrics_provider.h"
 #include "chrome/browser/metrics/metrics_reporting_state.h"
 #include "chrome/browser/metrics/network_quality_estimator_provider_impl.h"
+#include "chrome/browser/metrics/process_memory_metrics_emitter.h"
 #include "chrome/browser/metrics/sampling_metrics_provider.h"
 #include "chrome/browser/metrics/subprocess_metrics_provider.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -813,6 +814,10 @@
   scoped_refptr<MetricsMemoryDetails> details(
       new MetricsMemoryDetails(callback, &memory_growth_tracker_));
   details->StartFetch();
+
+  scoped_refptr<ProcessMemoryMetricsEmitter> emitter(
+      new ProcessMemoryMetricsEmitter);
+  emitter->FetchAndEmitProcessMemoryMetrics();
 }
 
 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() {
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index c371d73..c2367bd 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -27,6 +27,7 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/base/filename_util.h"
+#include "services/service_manager/embedder/switches.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
 
@@ -195,6 +196,11 @@
 // OOM code only works on Windows.
 #if defined(OS_WIN) && !defined(ADDRESS_SANITIZER)
 IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, OOMRenderers) {
+  // Disable stack traces during this test since DbgHelp is unreliable in
+  // low-memory conditions (see crbug.com/692564).
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      service_manager::switches::kDisableInProcessStackTraces);
+
   base::HistogramTester histogram_tester;
 
   OpenTabsAndNavigateToCrashyUrl(content::kChromeUIMemoryExhaustURL);
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc
new file mode 100644
index 0000000..2b53ff1
--- /dev/null
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -0,0 +1,100 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/process_memory_metrics_emitter.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/memory_dump_request_args.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+using ProcessMemoryDumpPtr =
+    memory_instrumentation::mojom::ProcessMemoryDumpPtr;
+
+namespace {
+
+void EmitBrowserMemoryMetrics(const ProcessMemoryDumpPtr& pmd) {
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Browser2.Resident",
+                                pmd->os_dump.resident_set_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Browser2.Malloc",
+                                pmd->chrome_dump.malloc_total_kb * 1024);
+
+  // TODO(erikchen): Emit private memory footprint. https://crbug.com/721434.
+}
+
+void EmitRendererMemoryMetrics(const ProcessMemoryDumpPtr& pmd) {
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Renderer2.Resident",
+                                pmd->os_dump.resident_set_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Renderer2.Malloc",
+                                pmd->chrome_dump.malloc_total_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB(
+      "Memory.Experimental.Renderer2.PartitionAlloc",
+      pmd->chrome_dump.partition_alloc_total_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Renderer2.BlinkGC",
+                                pmd->chrome_dump.blink_gc_total_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Renderer2.V8",
+                                pmd->chrome_dump.v8_total_kb * 1024);
+
+  // TODO(erikchen): Emit private memory footprint. https://crbug.com/721434.
+}
+
+void EmitGpuMemoryMetrics(const ProcessMemoryDumpPtr& pmd) {
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Gpu2.Resident",
+                                pmd->os_dump.resident_set_kb * 1024);
+  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Experimental.Gpu2.Malloc",
+                                pmd->chrome_dump.malloc_total_kb * 1024);
+
+  // TODO(erikchen): Emit private memory footprint. https://crbug.com/721434.
+}
+
+}  // namespace
+
+ProcessMemoryMetricsEmitter::ProcessMemoryMetricsEmitter() {}
+
+void ProcessMemoryMetricsEmitter::FetchAndEmitProcessMemoryMetrics() {
+  service_manager::Connector* connector =
+      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  connector->BindInterface(content::mojom::kBrowserServiceName,
+                           mojo::MakeRequest(&coordinator_));
+
+  // The callback keeps this object alive until the callback is invoked..
+  auto callback =
+      base::Bind(&ProcessMemoryMetricsEmitter::ReceivedMemoryDump, this);
+
+  base::trace_event::MemoryDumpRequestArgs args = {
+      0, base::trace_event::MemoryDumpType::SUMMARY_ONLY,
+      base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND};
+  coordinator_->RequestGlobalMemoryDump(args, callback);
+}
+
+ProcessMemoryMetricsEmitter::~ProcessMemoryMetricsEmitter() {}
+
+void ProcessMemoryMetricsEmitter::ReceivedMemoryDump(
+    uint64_t dump_guid,
+    bool success,
+    memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr) {
+  if (!success)
+    return;
+  if (!ptr)
+    return;
+
+  for (const ProcessMemoryDumpPtr& pmd : ptr->process_dumps) {
+    switch (pmd->process_type) {
+      case memory_instrumentation::mojom::ProcessType::BROWSER:
+        EmitBrowserMemoryMetrics(pmd);
+        break;
+      case memory_instrumentation::mojom::ProcessType::RENDERER:
+        EmitRendererMemoryMetrics(pmd);
+        break;
+      case memory_instrumentation::mojom::ProcessType::GPU:
+        EmitGpuMemoryMetrics(pmd);
+        break;
+      case memory_instrumentation::mojom::ProcessType::UTILITY:
+      case memory_instrumentation::mojom::ProcessType::PLUGIN:
+      case memory_instrumentation::mojom::ProcessType::OTHER:
+        break;
+    }
+  }
+}
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.h b/chrome/browser/metrics/process_memory_metrics_emitter.h
new file mode 100644
index 0000000..9edcd027
--- /dev/null
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_
+#define CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_
+
+#include "base/memory/ref_counted.h"
+#include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h"
+
+// This class asynchronously fetches memory metrics for each process, and then
+// emits UMA metrics from those metrics.
+// Each instance is self-owned, and will delete itself once it has finished
+// emitting metrics.
+// This class is an analog to MetricsMemoryDetails, but uses the resource
+// coordinator service to fetch data, rather than doing all the processing
+// manually.
+class ProcessMemoryMetricsEmitter
+    : public base::RefCountedThreadSafe<ProcessMemoryMetricsEmitter> {
+ public:
+  ProcessMemoryMetricsEmitter();
+
+  // This must be called on the main thread of the browser process.
+  void FetchAndEmitProcessMemoryMetrics();
+
+ protected:
+  virtual ~ProcessMemoryMetricsEmitter();
+
+  // Virtual for testing.
+  virtual void ReceivedMemoryDump(
+      uint64_t dump_guid,
+      bool success,
+      memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr);
+
+ private:
+  friend class base::RefCountedThreadSafe<ProcessMemoryMetricsEmitter>;
+
+  memory_instrumentation::mojom::CoordinatorPtr coordinator_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitter);
+};
+
+#endif  // CHROME_BROWSER_METRICS_PROCESS_MEMORY_METRICS_EMITTER_H_
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
new file mode 100644
index 0000000..173ebe0
--- /dev/null
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/process_memory_metrics_emitter.h"
+
+#include "base/message_loop/message_loop.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/test_utils.h"
+
+namespace {
+
+class ProcessMemoryMetricsEmitterFake : public ProcessMemoryMetricsEmitter {
+ public:
+  ProcessMemoryMetricsEmitterFake() {}
+
+ private:
+  ~ProcessMemoryMetricsEmitterFake() override {}
+
+  void ReceivedMemoryDump(
+      uint64_t dump_guid,
+      bool success,
+      memory_instrumentation::mojom::GlobalMemoryDumpPtr ptr) override {
+    EXPECT_TRUE(success);
+    base::MessageLoop::current()->QuitWhenIdle();
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterFake);
+};
+
+}  // namespace
+
+class ProcessMemoryMetricsEmitterTest : public InProcessBrowserTest {
+ public:
+  ProcessMemoryMetricsEmitterTest() {}
+  ~ProcessMemoryMetricsEmitterTest() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitterTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ProcessMemoryMetricsEmitterTest, FetchAndEmitMetrics) {
+  // Intentionally let emitter leave scope to check that it correctly keeps
+  // itself alive.
+  {
+    scoped_refptr<ProcessMemoryMetricsEmitterFake> emitter(
+        new ProcessMemoryMetricsEmitterFake);
+    emitter->FetchAndEmitProcessMemoryMetrics();
+  }
+
+  content::RunMessageLoop();
+}
diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc
index 85c5f63db..7df1e68 100644
--- a/chrome/browser/net/predictor_browsertest.cc
+++ b/chrome/browser/net/predictor_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/synchronization/lock.h"
diff --git a/chrome/browser/net/sdch_browsertest.cc b/chrome/browser/net/sdch_browsertest.cc
index f05bf94b..d958321 100644
--- a/chrome/browser/net/sdch_browsertest.cc
+++ b/chrome/browser/net/sdch_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_tokenizer.h"
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc
index 16c9d109..2eb1d984 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/histogram_tester.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
index f6a08a1..cb4ad34 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
@@ -23,25 +23,37 @@
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool FrameIsAd(content::NavigationHandle* navigation_handle) {
-  content::RenderFrameHost* current_frame_host =
-      navigation_handle->GetRenderFrameHost();
-  DCHECK(current_frame_host);
-  const std::string& name = current_frame_host->GetFrameName();
-  const GURL& url = navigation_handle->GetURL();
-
   // Because sub-resource filtering isn't always enabled, and doesn't work
   // well in monitoring mode (no CSS enforcement), it's difficult to identify
   // ads. Google ads are prevalent and easy to track, so we'll start by
   // tracking those. Note that the frame name can be very large, so be careful
   // to avoid full string searches if possible.
   // TODO(jkarlin): Track other ad networks that are easy to identify.
-  return base::StartsWith(name, "google_ads_iframe",
-                          base::CompareCase::SENSITIVE) ||
-         base::StartsWith(name, "google_ads_frame",
-                          base::CompareCase::SENSITIVE) ||
-         (url.host_piece() == "tpc.googlesyndication.com" &&
-          base::StartsWith(url.path_piece(), "/safeframe",
-                           base::CompareCase::SENSITIVE));
+
+  // In case the navigation aborted, look up the RFH by the Frame Tree Node
+  // ID. It returns the committed frame host or the initial frame host for the
+  // frame if no committed host exists. Using a previous host is fine because
+  // once a frame has an ad we always consider it to have an ad.
+  // We use the unsafe method of FindFrameByFrameTreeNodeId because we're not
+  // concerned with which process the frame lives on (we're just measuring
+  // bytes and not granting security priveleges).
+  content::RenderFrameHost* current_frame_host =
+      navigation_handle->GetWebContents()->UnsafeFindFrameByFrameTreeNodeId(
+          navigation_handle->GetFrameTreeNodeId());
+  if (current_frame_host) {
+    const std::string& frame_name = current_frame_host->GetFrameName();
+    if (base::StartsWith(frame_name, "google_ads_iframe",
+                         base::CompareCase::SENSITIVE) ||
+        base::StartsWith(frame_name, "google_ads_frame",
+                         base::CompareCase::SENSITIVE)) {
+      return true;
+    }
+  }
+
+  const GURL& url = navigation_handle->GetURL();
+  return url.host_piece() == "tpc.googlesyndication.com" &&
+         base::StartsWith(url.path_piece(), "/safeframe",
+                          base::CompareCase::SENSITIVE);
 }
 
 }  // namespace
@@ -77,22 +89,13 @@
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
     content::NavigationHandle* navigation_handle) {
+  // Determine if the frame is part of an existing ad, the root of a new ad,
+  // or a non-ad frame. Once a frame is labled as an ad, it is always
+  // considered an ad, even if it navigates to a non-ad page. This function
+  // labels all of a page's frames, even those that fail to commit.
   FrameTreeNodeId frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
-
-  if (!navigation_handle->HasCommitted() ||
-      navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage()) {
-    // We're not interested in tracking this navigation. In case we've seen a
-    // resource for the navigation before this message, clear it from
-    // ongoing_navigation_resources_.
-    ongoing_navigation_resources_.erase(frame_tree_node_id);
-    return CONTINUE_OBSERVING;
-  }
-
   content::RenderFrameHost* parent_frame_host =
-      navigation_handle->GetRenderFrameHost()->GetParent();
-  DCHECK(parent_frame_host);
-
-  bool top_level_subframe = !parent_frame_host->GetParent();
+      navigation_handle->GetParentFrame();
 
   const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id);
   if (id_and_data != ad_frames_data_.end()) {
@@ -107,7 +110,6 @@
             "PageLoad.Clients.Ads.Google.Navigations.AdFrameRenavigatedToAd",
             FrameIsAd(navigation_handle));
       }
-
       return CONTINUE_OBSERVING;
     }
     // This frame was previously not an ad, process it as usual. If it had
@@ -115,7 +117,7 @@
     UMA_HISTOGRAM_BOOLEAN(
         "PageLoad.Clients.Ads.Google.Navigations.NonAdFrameRenavigatedToAd",
         FrameIsAd(navigation_handle));
-  } else if (top_level_subframe) {
+  } else if (navigation_handle->IsParentMainFrame()) {
     top_level_subframe_count_ += 1;
   }
 
@@ -133,7 +135,7 @@
 
   ad_frames_data_[frame_tree_node_id] = ad_data;
 
-  if (top_level_subframe && ad_data)
+  if (navigation_handle->IsParentMainFrame() && ad_data)
     top_level_ad_frame_count_ += 1;
 
   ProcessOngoingNavigationResource(frame_tree_node_id);
@@ -176,12 +178,13 @@
   const auto& id_and_data =
       ad_frames_data_.find(extra_request_info.frame_tree_node_id);
   if (id_and_data == ad_frames_data_.end()) {
-    // This resouce is for a frame that hasn't yet committed. It must be the
-    // main document for the frame. Hold onto it and once it commits we'll run
-    // it in ProcessOngoingNavigationResource.
-    // TODO(jkarlin): Plumb the resource type through and DCHECK that the type
-    // is document.
-    auto it_and_success = ongoing_navigation_resources_.emplace(
+    // This resource is for a frame that hasn't ever finished a navigation. We
+    // expect it to be the frame's main resource but don't have enough
+    // confidence in that to dcheck it. For example, there might be races
+    // between doc.written resources and navigation failure.
+    // TODO(jkarlin): Add UMA to measure how often we see multiple resources
+    // for a frame before navigation finishes.
+    ongoing_navigation_resources_.emplace(
         std::piecewise_construct,
         std::forward_as_tuple(extra_request_info.frame_tree_node_id),
         std::forward_as_tuple(
@@ -189,7 +192,6 @@
             extra_request_info.was_cached, extra_request_info.raw_body_bytes,
             extra_request_info.original_network_content_length, nullptr,
             extra_request_info.resource_type));
-    DCHECK(it_and_success.second);
     return;
   }
 
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
index 91a95e580..cb6603a 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
@@ -13,6 +13,8 @@
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "net/http/http_response_info.h"
 
+// This observer labels each sub-frame as an ad or not, and keeps track of
+// relevant per-frame and whole-page byte statistics.
 class AdsPageLoadMetricsObserver
     : public page_load_metrics::PageLoadMetricsObserver {
  public:
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
new file mode 100644
index 0000000..8623212
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
@@ -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 <string>
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/test/histogram_tester.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+const char kAdsMetricsFeature[] = "AdsMetrics";
+
+class AdsPageLoadMetricsObserverBrowserTest : public InProcessBrowserTest {
+ public:
+  AdsPageLoadMetricsObserverBrowserTest() {
+    base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+    cmd_line->AppendSwitchASCII(switches::kEnableFeatures, kAdsMetricsFeature);
+  }
+  ~AdsPageLoadMetricsObserverBrowserTest() override {}
+
+  void SetUpOnMainThread() override {
+    ASSERT_TRUE(embedded_test_server()->Start());
+    InProcessBrowserTest::SetUpOnMainThread();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AdsPageLoadMetricsObserverBrowserTest);
+};
+
+// Test that a subframe that aborts (due to doc.write) doesn't cause a crash
+// if it continues to load resources.
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       DocOverwritesNavigation) {
+  content::DOMMessageQueue msg_queue;
+
+  base::HistogramTester histogram_tester;
+
+  ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL(
+                     "/ads_observer/docwrite_provisional_frame.html"));
+  std::string status;
+  EXPECT_TRUE(msg_queue.WaitForMessage(&status));
+  EXPECT_EQ("\"loaded\"", status);
+
+  // Navigate away to force the histogram recording.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  histogram_tester.ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames", 1, 1);
+  histogram_tester.ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total",
+      0 /* < 1 KB */, 1);
+}
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
index 706022d..79c9fae 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_unittest.cc
@@ -450,6 +450,70 @@
       "PageLoad.Clients.Ads.Google.Bytes.NonAdFrames.Aggregate.Total", 20, 1);
 }
 
+TEST_F(AdsPageLoadMetricsObserverTest, CountAbortedNavigation) {
+  // If the first navigation in a frame is aborted, keep track of its bytes.
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  LoadResource(main_frame, ResourceCached::NOT_CACHED, 10);
+
+  // Create an ad subframe that aborts before committing.
+  RenderFrameHost* subframe_ad =
+      RenderFrameHostTester::For(main_frame)->AppendChild(kAdName);
+  auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
+      GURL(kNonAdUrl), subframe_ad);
+  // The sub-frame renavigates before it commits.
+  navigation_simulator->Start();
+  navigation_simulator->Fail(net::ERR_ABORTED);
+
+  // Load resources for the aborted frame (e.g., simulate the navigation
+  // aborting due to a doc.write during provisional navigation). They should
+  // be counted.
+  LoadResource(subframe_ad, ResourceCached::NOT_CACHED, 10);
+  LoadResource(subframe_ad, ResourceCached::NOT_CACHED, 10);
+
+  // Navigate again to trigger histograms.
+  NavigateFrame(kNonAdUrl, main_frame);
+
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames", 1, 1);
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total", 20, 1);
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total", 30, 1);
+}
+
+TEST_F(AdsPageLoadMetricsObserverTest, CountAbortedSecondNavigationForFrame) {
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  LoadResource(main_frame, ResourceCached::NOT_CACHED, 10);
+
+  // Sub frame that is not an ad.
+  RenderFrameHost* sub_frame =
+      CreateAndNavigateSubFrame(kNonAdUrl, kNonAdName, main_frame);
+  LoadResource(sub_frame, ResourceCached::NOT_CACHED, 10);
+
+  // Now navigate (and abort) the subframe to an ad.
+  auto navigation_simulator =
+      NavigationSimulator::CreateRendererInitiated(GURL(kAdUrl), sub_frame);
+  // The sub-frame renavigates before it commits.
+  navigation_simulator->Start();
+  navigation_simulator->Fail(net::ERR_ABORTED);
+
+  // Load resources for the aborted frame (e.g., simulate the navigation
+  // aborting due to a doc.write during provisional navigation). Since the
+  // frame attempted to load an ad, the frame is tagged forever as an ad.
+  LoadResource(sub_frame, ResourceCached::NOT_CACHED, 10);
+  LoadResource(sub_frame, ResourceCached::NOT_CACHED, 10);
+
+  // Navigate again to trigger histograms.
+  NavigateFrame(kNonAdUrl, main_frame);
+
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.FrameCounts.AnyParentFrame.AdFrames", 1, 1);
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total", 20, 1);
+  histogram_tester().ExpectUniqueSample(
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total", 40, 1);
+}
+
 TEST_F(AdsPageLoadMetricsObserverTest, TwoResourceLoadsBeforeCommit) {
   // Main frame.
   RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
@@ -482,13 +546,13 @@
 
   // 30KB in total was loaded. Ten for the main page, ten for an aborted
   // ad subframe, and ten for a successful ad subframe. The aborted ad
-  // subframe's bytes don't count.
+  // subframe's bytes count.
 
   // Individual Ad Frame Metrics
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Total", 10, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Total", 20, 1);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Network", 10, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.Network", 20, 1);
   histogram_tester().ExpectUniqueSample(
       "PageLoad.Clients.Ads.Google.Bytes.AdFrames.PerFrame.PercentNetwork", 100,
       1);
@@ -507,22 +571,22 @@
 
   // Page percentages
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total.PercentAds", 50, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total.PercentAds", 66, 1);
   histogram_tester().ExpectUniqueSample(
       "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.PercentNetwork",
       100, 1);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network.PercentAds", 50, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network.PercentAds", 66, 1);
 
   // Page byte counts
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total", 10, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Total", 20, 1);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Network", 10, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.AdFrames.Aggregate.Network", 20, 1);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total", 20, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Total", 30, 1);
   histogram_tester().ExpectUniqueSample(
-      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network", 20, 1);
+      "PageLoad.Clients.Ads.Google.Bytes.FullPage.Network", 30, 1);
   histogram_tester().ExpectUniqueSample(
       "PageLoad.Clients.Ads.Google.Bytes.NonAdFrames.Aggregate.Total", 10, 1);
 }
diff --git a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
index 2b2015211..d121c7f 100644
--- a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
@@ -60,6 +60,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.ParseTiming.NavigationToParseStart",
           timing.parse_timing.parse_start.value());
@@ -111,6 +112,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.PaintTiming."
           "NavigationToFirstContentfulPaint",
@@ -168,6 +170,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.Experimental.PaintTiming."
           "NavigationToFirstMeaningfulPaint",
@@ -215,6 +218,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToDOMContentLoadedEventFired",
@@ -257,6 +261,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToLoadEventFired",
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
index 8b03144..3e9e040 100644
--- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/location.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/stl_util.h"
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc
index 8dac601..02241ab 100644
--- a/chrome/browser/password_manager/password_store_mac_unittest.cc
+++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -11,6 +11,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/scoped_observer.h"
 #include "base/stl_util.h"
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index b8ad00c..c87fc065 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
index e23599b..e771f55 100644
--- a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/sample_map.h"
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 9447024..a364e864 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -24,6 +24,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
diff --git a/chrome/browser/policy/profile_policy_connector_unittest.cc b/chrome/browser/policy/profile_policy_connector_unittest.cc
index 53ec53d6..3f584a1f 100644
--- a/chrome/browser/policy/profile_policy_connector_unittest.cc
+++ b/chrome/browser/policy/profile_policy_connector_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/policy/profile_policy_connector.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
index 5125913..d4dc131 100644
--- a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
index 436da5a..2cb8618 100644
--- a/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
+++ b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
@@ -7,6 +7,7 @@
 
 #include "base/json/json_string_value_serializer.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
diff --git a/chrome/browser/printing/cloud_print/privet_http_unittest.cc b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
index 52d40243..cce9a991 100644
--- a/chrome/browser/printing/cloud_print/privet_http_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_writer.h"
 #include "base/location.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/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc b/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
index 18249f8..666056e 100644
--- a/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/notifications/notification_test_util.h"
 #include "chrome/browser/printing/cloud_print/privet_http_asynchronous_factory.h"
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
index 2b1a82e..5412825 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 9d5a84d..d7f5ec8 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/location.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/utf_string_conversions.h"
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 8eb31578..67cb77fb 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -19,7 +19,6 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -236,11 +235,10 @@
   main_request_context_getter_ = ChromeURLRequestContextGetter::Create(
       profile_, io_data_, protocol_handlers, std::move(request_interceptors));
 
-  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
   scoped_refptr<base::SequencedTaskRunner> db_task_runner =
-      pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          pool->GetSequenceToken(),
-          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   std::unique_ptr<data_reduction_proxy::DataStore> store(
       new data_reduction_proxy::DataStoreImpl(io_data_->profile_path_));
   DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile_)
diff --git a/chrome/browser/profiles/profile_list_desktop_browsertest.cc b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
index 34aea035..2a18925 100644
--- a/chrome/browser/profiles/profile_list_desktop_browsertest.cc
+++ b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/avatar_menu.h"
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc
index bfb4cdc..f958fca8 100644
--- a/chrome/browser/profiles/profile_manager_browsertest.cc
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 4c76404..099624e1 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -9,6 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index c9da53c..c5e42c17 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/resources/chromeos/login/md_header_bar.css b/chrome/browser/resources/chromeos/login/md_header_bar.css
index b39ab27..b9c3bb1 100644
--- a/chrome/browser/resources/chromeos/login/md_header_bar.css
+++ b/chrome/browser/resources/chromeos/login/md_header_bar.css
@@ -13,7 +13,6 @@
 }
 
 #login-header-bar {
-  background-color: rgba(0, 0, 0, 0.6);
   padding-top: 7px;
 }
 
diff --git a/chrome/browser/resources/chromeos/login/md_lock.html b/chrome/browser/resources/chromeos/login/md_lock.html
new file mode 100644
index 0000000..87b5f986
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/md_lock.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html i18n-values="dir:textdirection;
+                   build:buildType;
+                   highlight:highlightStrength;
+                   lang:language">
+<head>
+<meta charset="utf-8">
+<meta name="google" value="notranslate">
+<title i18n-content="title"></title>
+
+<include src="login_shared.html">
+
+<!-- custom_elements.html (polymer) gets lazily-loaded in lock.js -->
+
+<script src="chrome://oobe/lock.js"></script>
+
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;" class="chromeos">
+  <include src="screen_container.html">
+  <script src="chrome://resources/js/i18n_template.js"></script>
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/login/md_lock.js b/chrome/browser/resources/chromeos/login/md_lock.js
new file mode 100644
index 0000000..12493dc
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/md_lock.js
@@ -0,0 +1,95 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Login UI based on a stripped down OOBE controller.
+ */
+
+// <include src="login_shared.js">
+
+/**
+ * Ensures that the pin keyboard is loaded.
+ * @param {function()} onLoaded Callback run when the pin keyboard is loaded.
+ */
+function ensurePinKeyboardLoaded(onLoaded) {
+  'use strict';
+
+  // The element we want to see if loaded.
+  var getPinKeyboard = function() {
+    return $('pod-row').querySelectorAll('pin-keyboard')[0];
+  };
+
+  // Do not reload assets if they are already loaded. Run |onLoaded| once assets
+  // are done loading, though.
+  if (cr.ui.login.ResourceLoader.hasDeferredAssets('custom-elements')) {
+    cr.ui.login.ResourceLoader.waitUntilLayoutComplete(getPinKeyboard,
+                                                       onLoaded);
+    return;
+  }
+
+  // Register loader for custom elements.
+  cr.ui.login.ResourceLoader.registerAssets({
+    id: 'custom-elements',
+    html: [{ url: 'chrome://oobe/custom_elements.html' }]
+  });
+
+  // We only load the PIN element when it is actually shown so that lock screen
+  // load times remain low when the user is not using a PIN.
+  //
+  // Loading the PIN element blocks the DOM, which will interrupt any running
+  // animations. We load the PIN after an idle notification to allow the pod
+  // fly-in animation to complete without interruption.
+  cr.ui.login.ResourceLoader.loadAssetsOnIdle('custom-elements', function() {
+    cr.ui.login.ResourceLoader.waitUntilLayoutComplete(getPinKeyboard,
+                                                       onLoaded);
+  });
+}
+
+cr.define('cr.ui.Oobe', function() {
+  return {
+    /**
+     * Initializes the OOBE flow.  This will cause all C++ handlers to
+     * be invoked to do final setup.
+     */
+    initialize: function() {
+      cr.ui.login.DisplayManager.initialize();
+      login.AccountPickerScreen.register();
+
+      cr.ui.Bubble.decorate($('bubble'));
+      login.HeaderBar.decorate($('login-header-bar'));
+
+      chrome.send('screenStateInitialize');
+    },
+
+    /**
+     * Notification from the host that the PIN keyboard will be used in the
+     * lock session so it should also get preloaded.
+     */
+    preloadPinKeyboard: function() {
+      ensurePinKeyboardLoaded(function() {});
+    },
+
+    // Dummy Oobe functions not present with stripped login UI.
+    initializeA11yMenu: function(e) {},
+    handleAccessibilityLinkClick: function(e) {},
+    handleSpokenFeedbackClick: function(e) {},
+    handleHighContrastClick: function(e) {},
+    handleScreenMagnifierClick: function(e) {},
+    setUsageStats: function(checked) {},
+    setOemEulaUrl: function(oemEulaUrl) {},
+    setTpmPassword: function(password) {},
+    refreshA11yInfo: function(data) {},
+    reloadEulaContent: function(data) {},
+
+    /**
+     * Reloads content of the page.
+     * @param {!Object} data New dictionary with i18n values.
+     */
+    reloadContent: function(data) {
+      loadTimeData.overrideValues(data);
+      i18nTemplate.process(document, loadTimeData);
+      Oobe.getInstance().updateLocalizedContent_();
+    },
+  };
+});
diff --git a/chrome/browser/resources/chromeos/login/md_lock_screens.html b/chrome/browser/resources/chromeos/login/md_lock_screens.html
new file mode 100644
index 0000000..7f8ed7a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/md_lock_screens.html
@@ -0,0 +1 @@
+<include src="../../../../../ui/login/account_picker/screen_account_picker.html">
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/md_screen_container.html b/chrome/browser/resources/chromeos/login/md_screen_container.html
index f00bc11..6c96ac0d 100644
--- a/chrome/browser/resources/chromeos/login/md_screen_container.html
+++ b/chrome/browser/resources/chromeos/login/md_screen_container.html
@@ -1,7 +1,7 @@
 <div id="background" class="background-initial"></div>
 <include src="api_keys_notice.html">
 <div id="scroll-container">
-  <div id="oobe-shield"></div>
+  <div id="login-shield"></div>
   <div id="outer-container" class="down">
     <div id="oobe" class="faded">
       <div id="inner-container" class="down">
diff --git a/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.html b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.html
new file mode 100644
index 0000000..703a161
--- /dev/null
+++ b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.html
@@ -0,0 +1,261 @@
+<!-- TODO(crbug.com/603217): Use i18n instead of string literals. Figure out
+                             what i18n to use for keypad, ie, does 1 ABC make
+                             sense in every scenario? -->
+
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<iron-iconset-svg name="pin-keyboard" size="24">
+  <svg>
+    <defs>
+      <!--
+      Inlined from Polymer's iron-icons to avoid importing everything.
+      See http://goo.gl/Y1OdAq for instructions on adding additional icons.
+      -->
+      <g id="arrow-forward">
+        <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z">
+        </path>
+      </g>
+      <g id="backspace">
+        <path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z">
+      </g>
+    </defs>
+  </svg>
+</iron-iconset-svg>
+
+<dom-module id="pin-keyboard">
+  <template>
+    <style include="cr-shared-style">
+      :host {
+        outline: none;
+      }
+
+      :host(:not([enable-submit-button])) #pinInput {
+        left: 0;
+        text-align: center;
+        width: 180px;
+      }
+
+      #root {
+        direction: ltr;
+        display: flex;
+      }
+
+      .row {
+        display: flex;
+      }
+
+      .digit-button {
+        align-items: center;
+        background: none;
+        border-radius: 0;
+        box-sizing: border-box;
+        color: #000;
+        display: flex;
+        flex-direction: column;
+        font-size: 18px;
+        height: 48px;
+        justify-content: center;
+        margin: 0;
+        min-height: 48px;
+        min-width: 48px;
+        opacity: 0.87;
+        padding: 15px 21px;
+        width: 60px;
+      }
+
+      [hidden=true] {
+        display: none;
+      }
+
+      .first-row {
+        height: 43px;
+      }
+
+      .bottom-row {
+        margin-bottom: 6px;
+      }
+
+      .top-row {
+        margin-top: 6px;
+      }
+
+      .backspace-button-container {
+        position: relative;
+      }
+
+      .backspace-button-container paper-ripple {
+        position: absolute;
+        top: 0;
+      }
+
+      paper-ripple {
+        border-radius: 100px;
+        color: #000;
+        height: 48px;
+        left: 6px;
+        width: 48px;
+      }
+
+      .digit-button.backspace-button {
+        left: 0;
+        opacity: var(--dark-primary-opacity);
+        padding: 14px;
+        position: absolute;
+        top: 0;
+      }
+
+      .digit-button.backspace-button:not([has-content]) {
+        color: #000;
+        opacity: 0.26;
+      }
+
+      .digit-button inner-text {
+        color: var(--paper-blue-grey-700);
+        display: flex;
+        flex-direction: column;
+        height: 52px;
+      }
+
+      #pinInput {
+        background-color: white;
+        border: 0;
+        box-sizing: border-box;
+        font-face: Roboto-Regular;
+        font-size: 13px;
+        height: 43px;
+        left: 10px;
+        opacity: var(--dark-secondary-opacity);
+        outline: 0;
+        position: relative;
+        width: 127px;
+
+        --paper-input-container-input: {
+          caret-color: var(--paper-input-container-focus-color);
+        }
+      }
+
+      #pinInput[has-content] {
+        opacity: var(--dark-primary-opacity);
+      }
+
+      #pinInput[is-input-rtl] {
+        direction: rtl;
+      }
+
+      #pinInput[type=number]::-webkit-inner-spin-button,
+      #pinInput[type=number]::-webkit-outer-spin-button {
+        -webkit-appearance: none;
+        margin: 0;
+      }
+
+      .separator {
+        border-bottom: var(--cr-separator-line);
+        margin: 0 10px;
+        position: relative;
+      }
+
+      /* Ensure that all children of paper-button do not consume events. This
+       * simplifies the event handler code. */
+      paper-button * {
+        pointer-events: none;
+      }
+    </style>
+
+    <div id="root">
+      <div id="container-constrained-width">
+        <div class="row first-row">
+          <paper-input id="pinInput" type="password" no-label-float
+              value="[[value]]"
+              is-input-rtl$="[[isInputRtl_(value)]]"
+              has-content$="[[hasInput_(value)]]"
+              label="[[getInputPlaceholder_(enablePassword)]]"
+              on-keydown="onInputKeyDown_"
+              hidden="[[!showPinInput_]]">
+          </paper-input>
+        </div>
+        <div class="separator" hidden="[[showPinInput_]]"></div>
+        <div class="row keyboard">
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="1"
+              noink>
+            <inner-text>$i18n{pinKeyboard1}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="2"
+              noink>
+            <inner-text>$i18n{pinKeyboard2}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="3"
+              noink>
+            <inner-text>$i18n{pinKeyboard3}</inner-text>
+            <paper-ripple>
+          </paper-button>
+        </div>
+        <div class="row keyboard">
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="4"
+              noink>
+            <inner-text>$i18n{pinKeyboard4}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="5"
+              noink>
+            <inner-text>$i18n{pinKeyboard5}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="6"
+              noink>
+            <inner-text>$i18n{pinKeyboard6}</inner-text>
+            <paper-ripple>
+          </paper-button>
+        </div>
+        <div class="row keyboard">
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="7"
+              noink>
+            <inner-text>$i18n{pinKeyboard7}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="8"
+              noink>
+            <inner-text>$i18n{pinKeyboard8}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="9"
+              noink>
+            <inner-text>$i18n{pinKeyboard9}</inner-text>
+            <paper-ripple>
+          </paper-button>
+        </div>
+        <div class="row keyboard bottom-row">
+          <div class="digit-button"></div>
+          <paper-button class="digit-button" on-tap="onNumberTap_" value="0"
+              noink>
+            <inner-text>$i18n{pinKeyboard0}</inner-text>
+            <paper-ripple>
+          </paper-button>
+          <div class="backspace-button-container">
+            <paper-icon-button class="digit-button backspace-button"
+                has-content$="[[hasInput_(value)]]"
+                icon="pin-keyboard:backspace"
+                on-pointerdown="onBackspacePointerDown_"
+                on-pointerout="onBackspacePointerOut_"
+                on-pointerup="onBackspacePointerUp_"
+                aria-label="$i18n{pinKeyboardDeleteAccessibleName}"
+                noink>
+            </paper-icon-button>
+            <paper-ripple>
+          </div>
+        </div>
+      </div>
+    </div>
+  </template>
+  <script src="pin_keyboard.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js
new file mode 100644
index 0000000..d3740c76
--- /dev/null
+++ b/chrome/browser/resources/chromeos/quick_unlock/md_pin_keyboard.js
@@ -0,0 +1,400 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'pin-keyboard' is a keyboard that can be used to enter PINs or more generally
+ * numeric values.
+ *
+ * Properties:
+ *    value: The value of the PIN keyboard. Writing to this property will adjust
+ *           the PIN keyboard's value.
+ *
+ * Events:
+ *    pin-change: Fired when the PIN value has changed. The PIN is available at
+ *                event.detail.pin.
+ *    submit: Fired when the PIN is submitted. The PIN is available at
+ *            event.detail.pin.
+ *
+ * Example:
+ *    <pin-keyboard on-pin-change="onPinChange" on-submit="onPinSubmit">
+ *    </pin-keyboard>
+ */
+
+(function() {
+
+/**
+ * Once auto backspace starts, the time between individual backspaces.
+ * @type {number}
+ * @const
+ */
+var REPEAT_BACKSPACE_DELAY_MS = 150;
+
+/**
+ * How long the backspace button must be held down before auto backspace
+ * starts.
+ * @type {number}
+ * @const
+ */
+var INITIAL_BACKSPACE_DELAY_MS = 500;
+
+/**
+ * The key codes of the keys allowed to be used on the pin input, in addition to
+ * number keys. Currently we allow backspace(8), tab(9), left(37) and right(39).
+ * @type {Array<number>}
+ * @const
+ */
+var PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39];
+
+Polymer({
+  is: 'pin-keyboard',
+
+  behaviors: [
+    I18nBehavior,
+  ],
+
+  properties: {
+    /**
+     * Whether or not the keyboard's input element should be numerical
+     * or password.
+     * @private
+     */
+    enablePassword: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * The password element the pin keyboard is associated with. If this is not
+     * set, then a default input element is shown and used.
+     * @type {?Element}
+     * @private
+     */
+    passwordElement: {
+      type: Object,
+      value: function() {
+        return this.$.pinInput.inputElement;
+      },
+      observer: 'onPasswordElementAttached_',
+    },
+
+    /**
+     * The intervalID used for the backspace button set/clear interval.
+     * @private
+     */
+    repeatBackspaceIntervalId_: {
+      type: Number,
+      value: 0,
+    },
+
+    /**
+     * The timeoutID used for the auto backspace.
+     * @private
+     */
+    startAutoBackspaceId_: {
+      type: Number,
+      value: 0,
+    },
+
+    /**
+     * Whether or not to show the default pin input.
+     * @private
+     */
+    showPinInput_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * The value stored in the keyboard's input element.
+     * @private
+     */
+    value: {
+      type: String,
+      notify: true,
+      value: '',
+      observer: 'onPinValueChange_',
+    },
+  },
+
+  /**
+   * Called when a password element is attached to the pin keyboard.
+   * @param {HTMLInputElement} inputElement The PIN keyboard's input element.
+   * @private
+   */
+  onPasswordElementAttached_: function(inputElement) {
+    this.showPinInput_ = inputElement == this.$.pinInput.inputElement;
+    inputElement.addEventListener('input',
+        this.handleInputChanged_.bind(this));
+  },
+
+  /**
+   * Called when the user uses the keyboard to enter a value into the input
+   * element.
+   * @param {Event} event The event object.
+   * @private
+   */
+  handleInputChanged_: function(event) {
+    this.value = event.target.value;
+  },
+
+  /**
+   * Gets the selection start of the input field.
+   * @type {number}
+   * @private
+   */
+  get selectionStart_() {
+    return this.passwordElement.selectionStart;
+  },
+
+  /**
+   * Gets the selection end of the input field.
+   * @type {number}
+   * @private
+   */
+  get selectionEnd_() {
+    return this.passwordElement.selectionEnd;
+  },
+
+  /**
+   * Sets the selection start of the input field.
+   * @param {number} start The new selection start of the input element.
+   * @private
+   */
+  set selectionStart_(start) {
+    this.passwordElement.selectionStart = start;
+  },
+
+  /**
+   * Sets the selection end of the input field.
+   * @param {number} end The new selection end of the input element.
+   * @private
+   */
+  set selectionEnd_(end) {
+    this.passwordElement.selectionEnd = end;
+  },
+
+  /** Transfers focus to the input element. */
+  focus: function() {
+    this.passwordElement.focus();
+  },
+
+  /**
+   * Called when a keypad number has been tapped.
+   * @param {Event} event The event object.
+   * @private
+   */
+  onNumberTap_: function(event) {
+    var numberValue = event.target.getAttribute('value');
+
+    // Add the number where the caret is, then update the selection range of the
+    // input element.
+    var selectionStart = this.selectionStart_;
+    this.value = this.value.substring(0, this.selectionStart_) + numberValue +
+        this.value.substring(this.selectionEnd_);
+    this.selectionStart_ = selectionStart + 1;
+    this.selectionEnd_ = this.selectionStart_;
+
+    // If a number button is clicked, we do not want to switch focus to the
+    // button, therefore we transfer focus back to the input, but if a number
+    // button is tabbed into, it should keep focus, so users can use tab and
+    // spacebar/return to enter their PIN.
+    if (!event.target.receivedFocusFromKeyboard)
+      this.focus();
+    event.preventDefault();
+  },
+
+  /** Fires a submit event with the current PIN value. */
+  firePinSubmitEvent_: function() {
+    this.fire('submit', { pin: this.value });
+  },
+
+  /**
+   * Fires an update event with the current PIN value. The event will only be
+   * fired if the PIN value has actually changed.
+   * @param {string} value
+   * @param {string} previous
+   */
+  onPinValueChange_: function(value, previous) {
+    if (value != previous) {
+      this.passwordElement.value = this.value;
+      this.fire('pin-change', { pin: value });
+    }
+  },
+
+  /**
+   * Called when the user wants to erase the last character of the entered
+   * PIN value.
+   * @private
+   */
+  onPinClear_: function() {
+    // If the input is shown, clear the text based on the caret location or
+    // selected region of the input element. If it is just a caret, remove the
+    // character in front of the caret.
+    var selectionStart = this.selectionStart_;
+    var selectionEnd = this.selectionEnd_;
+    if (selectionStart == selectionEnd)
+      selectionStart--;
+
+    this.value = this.value.substring(0, selectionStart) +
+        this.value.substring(selectionEnd);
+
+    // Move the caret or selected region to the correct new place.
+    this.selectionStart_ = selectionStart;
+    this.selectionEnd_ = selectionStart;
+  },
+
+  /**
+   * Called when the user presses or touches the backspace button. Starts a
+   * timer which starts an interval to repeatedly backspace the pin value until
+   * the interval is cleared.
+   * @param {Event} event The event object.
+   * @private
+   */
+  onBackspacePointerDown_: function(event) {
+    this.startAutoBackspaceId_ = setTimeout(function() {
+        this.repeatBackspaceIntervalId_ = setInterval(
+            this.onPinClear_.bind(this), REPEAT_BACKSPACE_DELAY_MS);
+    }.bind(this), INITIAL_BACKSPACE_DELAY_MS);
+
+    if (!event.target.receivedFocusFromKeyboard)
+      this.focus();
+    event.preventDefault();
+  },
+
+  /**
+   * Helper function which clears the timer / interval ids and resets them.
+   * @private
+   */
+  clearAndReset_: function() {
+    clearInterval(this.repeatBackspaceIntervalId_);
+    this.repeatBackspaceIntervalId_ = 0;
+    clearTimeout(this.startAutoBackspaceId_);
+    this.startAutoBackspaceId_ = 0;
+  },
+
+  /**
+   * Called when the user exits the backspace button. Stops the interval
+   * callback.
+   * @param {Event} event The event object.
+   * @private
+   */
+  onBackspacePointerOut_: function(event) {
+    this.clearAndReset_();
+
+    if (!event.target.receivedFocusFromKeyboard)
+      this.focus();
+    event.preventDefault();
+  },
+
+  /**
+   * Called when the user unpresses or untouches the backspace button. Stops the
+   * interval callback and fires a backspace event if there is no interval
+   * running.
+   * @param {Event} event The event object.
+   * @private
+   */
+  onBackspacePointerUp_: function(event) {
+    // If an interval has started, do not fire event on pointer up.
+    if (!this.repeatBackspaceIntervalId_)
+      this.onPinClear_();
+    this.clearAndReset_();
+
+    if (!event.target.receivedFocusFromKeyboard)
+      this.focus();
+    event.preventDefault();
+  },
+
+  /**
+   * Helper function to check whether a given |event| should be processed by
+   * the numeric only input.
+   * @param {Event} event The event object.
+   * @private
+   */
+  isValidEventForInput_: function(event) {
+    // Valid if the key is a number, and shift is not pressed.
+    if ((event.keyCode >= 48 && event.keyCode <= 57) && !event.shiftKey)
+      return true;
+
+    // Valid if the key is one of the selected special keys defined in
+    // |PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES|.
+    if (PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES.indexOf(event.keyCode) > -1)
+      return true;
+
+    // Valid if the key is CTRL+A to allow users to quickly select the entire
+    // PIN.
+    if (event.keyCode == 65 && event.ctrlKey)
+      return true;
+
+    // The rest of the keys are invalid.
+    return false;
+  },
+
+  /**
+   * Called when a key event is pressed while the input element has focus.
+   * @param {Event} event The event object.
+   * @private
+   */
+  onInputKeyDown_: function(event) {
+    // Up/down pressed, swallow the event to prevent the input value from
+    // being incremented or decremented.
+    if (event.keyCode == 38 || event.keyCode == 40) {
+      event.preventDefault();
+      return;
+    }
+
+    // Enter pressed.
+    if (event.keyCode == 13) {
+      this.firePinSubmitEvent_();
+      event.preventDefault();
+      return;
+    }
+
+    // Do not pass events that are not numbers or special keys we care about. We
+    // use this instead of input type number because there are several issues
+    // with input type number, such as no selectionStart/selectionEnd and
+    // entered non numbers causes the caret to jump to the left.
+    if (!this.isValidEventForInput_(event)) {
+      event.preventDefault();
+      return;
+    }
+  },
+
+  /**
+   * Disables the backspace button if nothing is entered.
+   * @param {string} value
+   * @private
+   */
+  hasInput_: function(value) {
+    return value.length > 0;
+  },
+
+  /**
+   * Computes the value of the pin input placeholder.
+   * @param {boolean} enablePassword
+   * @private
+   */
+  getInputPlaceholder_: function(enablePassword) {
+    return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') :
+                            this.i18n('pinKeyboardPlaceholderPin');
+  },
+
+  /**
+   * Computes the direction of the pin input.
+   * @param {string} password
+   * @private
+   */
+  isInputRtl_: function(password) {
+    // +password will convert a string to a number or to NaN if that's not
+    // possible. Number.isInteger will verify the value is not a NaN and that it
+    // does not contain decimals.
+    // This heuristic will fail for inputs like '1.0'.
+    //
+    // Since we still support users entering their passwords through the PIN
+    // keyboard, we swap the input box to rtl when we think it is a password
+    // (just numbers), if the document direction is rtl.
+    return (document.dir == 'rtl') && !Number.isInteger(+password);
+  },
+});
+})();
diff --git a/chrome/browser/resources/inspect/inspect.css b/chrome/browser/resources/inspect/inspect.css
index b25cb2e..8c3957b 100644
--- a/chrome/browser/resources/inspect/inspect.css
+++ b/chrome/browser/resources/inspect/inspect.css
@@ -6,16 +6,20 @@
   box-sizing: border-box;
 }
 
+html {
+  height: 100%;
+}
+
 body {
   color: rgb(48, 57, 66);
   font-size: 13px;
+  height: 100%;
   margin: 0;
-  min-width: 47em;
-  overflow: hidden;
+  overflow: auto;
 }
 
 .hidden {
-    display: none !important;
+  display: none !important;
 }
 
 img {
@@ -28,8 +32,8 @@
 }
 
 #container {
-  -webkit-flex-direction: row;
-  display: -webkit-flex;
+  display: flex;
+  height: 100%
 }
 
 #infobar {
@@ -49,12 +53,13 @@
 }
 
 #navigation {
+  flex-shrink: 0;
   padding-top: 20px;
   width: 150px;
 }
 
 #content {
-  -webkit-flex: 1;
+  flex-grow: 1;
 }
 
 #caption {
@@ -92,6 +97,7 @@
 }
 
 #content > div {
+  min-width: 32em;
   padding: 0 20px 65px 0;
 }
 #content > div:not(.selected) {
@@ -430,20 +436,3 @@
 .config-buttons > label {
   flex-grow: 1
 }
-
-@media (max-width: 47em) {
-  #navigation,
-  #content {
-    overflow: visible;
-  }
-}
-@media (min-width: 47em) {
-  #container {
-    max-height: 100vh;
-  }
-  #navigation,
-  #content {
-    max-height: 100vh;
-    overflow: auto;
-  }
-}
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
index 724edb52..22f5849 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/atomic_sequence_num.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/histogram_tester.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 92453f04e..05437fd 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win_unittest.cc
index 5cc1c2d0..1d27df21 100644
--- a/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/platform_state_store_win_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/chrome/browser/safe_browsing/incident_reporting/state_store_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/state_store_unittest.cc
index f1db3466c..95d7b93f 100644
--- a/chrome/browser/safe_browsing/incident_reporting/state_store_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/state_store_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 2d77b73..e866451 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -27,7 +27,7 @@
 using content::BrowserThread;
 using content::InterstitialPage;
 using content::WebContents;
-using security_interstitials::SafeBrowsingErrorUI;
+using security_interstitials::BaseSafeBrowsingErrorUI;
 using security_interstitials::SecurityInterstitialControllerClient;
 
 namespace safe_browsing {
@@ -70,7 +70,7 @@
     // Display Options below.
     safe_browsing::UpdatePrefsBeforeSecurityInterstitial(prefs);
 
-    SafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
+    BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
         BaseBlockingPage::IsMainPageLoadBlocked(unsafe_resources),
         is_extended_reporting_opt_in_allowed,
         web_contents->GetBrowserContext()->IsOffTheRecord(),
@@ -105,7 +105,7 @@
     WebContents* web_contents,
     const GURL& main_frame_url,
     const UnsafeResourceList& unsafe_resources,
-    const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
+    const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
     : BaseBlockingPage(
           ui_manager,
           web_contents,
@@ -188,9 +188,8 @@
   if (threat_details_.get() == NULL)
     return;  // Not all interstitials have threat details (eg., incognito mode).
 
-  const bool enabled =
-      sb_error_ui()->is_extended_reporting_enabled() &&
-      sb_error_ui()->is_extended_reporting_opt_in_allowed();
+  const bool enabled = sb_error_ui()->is_extended_reporting_enabled() &&
+                       sb_error_ui()->is_extended_reporting_opt_in_allowed();
   if (!enabled)
     return;
 
@@ -246,13 +245,13 @@
 
 // static
 std::string SafeBrowsingBlockingPage::GetSamplingEventName(
-    SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason) {
+    BaseSafeBrowsingErrorUI::SBInterstitialReason interstitial_reason) {
   switch (interstitial_reason) {
-    case SafeBrowsingErrorUI::SB_REASON_MALWARE:
+    case BaseSafeBrowsingErrorUI::SB_REASON_MALWARE:
       return kEventNameMalware;
-    case SafeBrowsingErrorUI::SB_REASON_HARMFUL:
+    case BaseSafeBrowsingErrorUI::SB_REASON_HARMFUL:
       return kEventNameHarmful;
-    case SafeBrowsingErrorUI::SB_REASON_PHISHING:
+    case BaseSafeBrowsingErrorUI::SB_REASON_PHISHING:
       return kEventNamePhishing;
     default:
       return kEventNameOther;
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
index fe0f3228..1854a5f 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
@@ -44,6 +44,8 @@
 
 class SafeBrowsingBlockingPage : public BaseBlockingPage {
  public:
+  typedef security_interstitials::BaseSafeBrowsingErrorUI
+      BaseSafeBrowsingErrorUI;
   // Interstitial type, used in tests.
   static content::InterstitialPageDelegate::TypeID kTypeForTesting;
 
@@ -104,7 +106,7 @@
       content::WebContents* web_contents,
       const GURL& main_frame_url,
       const UnsafeResourceList& unsafe_resources,
-      const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
 
   // Called after the user clicks OnProceed(). If the page has malicious
   // subresources, then we show another interstitial.
@@ -129,7 +131,7 @@
   static SafeBrowsingBlockingPageFactory* factory_;
  private:
   static std::string GetSamplingEventName(
-      SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason);
+      BaseSafeBrowsingErrorUI::SBInterstitialReason interstitial_reason);
 
   static std::unique_ptr<
       security_interstitials::SecurityInterstitialControllerClient>
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index 8836baf3c..42800c98 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
@@ -68,7 +69,7 @@
 using content::NavigationController;
 using content::RenderFrameHost;
 using content::WebContents;
-using security_interstitials::SafeBrowsingErrorUI;
+using security_interstitials::BaseSafeBrowsingErrorUI;
 
 namespace safe_browsing {
 
@@ -241,7 +242,7 @@
       WebContents* web_contents,
       const GURL& main_frame_url,
       const UnsafeResourceList& unsafe_resources,
-      const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
       : SafeBrowsingBlockingPage(manager,
                                  web_contents,
                                  main_frame_url,
@@ -296,7 +297,7 @@
         prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed);
     bool is_proceed_anyway_disabled =
         prefs->GetBoolean(prefs::kSafeBrowsingProceedAnywayDisabled);
-    SafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
+    BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
         BaseBlockingPage::IsMainPageLoadBlocked(unsafe_resources),
         is_extended_reporting_opt_in_allowed,
         web_contents->GetBrowserContext()->IsOffTheRecord(),
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
index 002d9be8..5690dac0 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
@@ -29,7 +29,7 @@
 using content::NavigationEntry;
 using content::WebContents;
 using content::WebContentsTester;
-using security_interstitials::SafeBrowsingErrorUI;
+using security_interstitials::BaseSafeBrowsingErrorUI;
 
 static const char* kGoogleURL = "http://www.google.com/";
 static const char* kGoodURL = "http://www.goodguys.com/";
@@ -49,7 +49,7 @@
       WebContents* web_contents,
       const GURL& main_frame_url,
       const UnsafeResourceList& unsafe_resources,
-      const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
       : SafeBrowsingBlockingPage(manager,
                                  web_contents,
                                  main_frame_url,
@@ -80,7 +80,7 @@
         prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingOptInAllowed);
     bool is_proceed_anyway_disabled =
         prefs->GetBoolean(prefs::kSafeBrowsingProceedAnywayDisabled);
-    SafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
+    BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options(
         BaseBlockingPage::IsMainPageLoadBlocked(unsafe_resources),
         is_extended_reporting_opt_in_allowed,
         web_contents->GetBrowserContext()->IsOffTheRecord(),
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 4ee2407..c92e98c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
diff --git a/chrome/browser/safe_browsing/ui_manager_unittest.cc b/chrome/browser/safe_browsing/ui_manager_unittest.cc
index 9a421b5..174936a1 100644
--- a/chrome/browser/safe_browsing/ui_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/ui_manager_unittest.cc
@@ -12,7 +12,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/safe_browsing_db/safe_browsing_prefs.h"
 #include "components/safe_browsing_db/util.h"
-#include "components/security_interstitials/core/safe_browsing_error_ui.h"
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -344,7 +344,7 @@
             web_contents,
             main_frame_url,
             unsafe_resources,
-            SafeBrowsingErrorUI::SBErrorDisplayOptions(
+            BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
                 BaseBlockingPage::IsMainPageLoadBlocked(unsafe_resources),
                 false,
                 false,
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc
index a9340b1d..e2c119e 100644
--- a/chrome/browser/service_process/service_process_control_browsertest.cc
+++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/kill.h"
 #include "base/process/process.h"
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index 8a0f490..49b4468 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -19,6 +19,7 @@
 #include "base/debug/alias.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc
index cd4b031e..8164cea 100644
--- a/chrome/browser/sessions/session_service_unittest.cc
+++ b/chrome/browser/sessions/session_service_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.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/stl_util.h"
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 421737b..88e0f13 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 169a55b..26bd68b 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_split.h"
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
index 8aad111c..c74b94f 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -56,6 +56,9 @@
           profile, ServiceAccessType::EXPLICIT_ACCESS)) {
     history_observer_.Add(history_service);
   }
+
+  cached_global_setting_for_metrics_ = settings_map_->GetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, nullptr);
 }
 
 SubresourceFilterContentSettingsManager::
@@ -140,9 +143,17 @@
 
   const ContentSettingsDetails details(primary_pattern, secondary_pattern,
                                        content_type, resource_identifier);
+  DCHECK(!details.update_all_types());
+
   if (details.update_all()) {
     ContentSetting global_setting = settings_map_->GetDefaultContentSetting(
         CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, nullptr);
+    // Ignore changes which retain the status quo. This also avoids logging
+    // metrics for changes which somehow notify this observer multiple times in
+    // a row. This shouldn't discount real user initiated changes.
+    if (global_setting == cached_global_setting_for_metrics_)
+      return;
+    cached_global_setting_for_metrics_ = global_setting;
     if (global_setting == CONTENT_SETTING_BLOCK) {
       ChromeSubresourceFilterClient::LogAction(
           kActionContentSettingsBlockedGlobal);
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
index 8f55ef6..3981f2c 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
@@ -89,6 +89,10 @@
 
   HostContentSettingsMap* settings_map_;
 
+  // Used only for metrics so we don't report global changes which just keep
+  // the same value.
+  ContentSetting cached_global_setting_for_metrics_;
+
   // A clock is injected into this class so tests can set arbitrary timestamps
   // in website settings.
   std::unique_ptr<base::Clock> clock_;
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
index 06fa25c9..4fd37f1 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
@@ -109,16 +109,21 @@
 }
 
 TEST_F(SubresourceFilterContentSettingsManagerTest, DefaultSetting) {
+  // Setting to an existing value should not log any metrics.
   GetSettingsMap()->SetDefaultContentSetting(
       CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, CONTENT_SETTING_ALLOW);
-  histogram_tester().ExpectBucketCount(kActionsHistogram,
-                                       kActionContentSettingsAllowedGlobal, 1);
+  histogram_tester().ExpectTotalCount(kActionsHistogram, 0);
 
   GetSettingsMap()->SetDefaultContentSetting(
       CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, CONTENT_SETTING_BLOCK);
-  histogram_tester().ExpectTotalCount(kActionsHistogram, 2);
   histogram_tester().ExpectBucketCount(kActionsHistogram,
                                        kActionContentSettingsBlockedGlobal, 1);
+
+  GetSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, CONTENT_SETTING_ALLOW);
+  histogram_tester().ExpectTotalCount(kActionsHistogram, 2);
+  histogram_tester().ExpectBucketCount(kActionsHistogram,
+                                       kActionContentSettingsAllowedGlobal, 1);
 }
 
 TEST_F(SubresourceFilterContentSettingsManagerTest, UrlSetting) {
@@ -251,6 +256,21 @@
                                        kActionContentSettingsBlockedFromUI, 1);
 }
 
+TEST_F(SubresourceFilterContentSettingsManagerTest,
+       IgnoreDuplicateGlobalSettings) {
+  histogram_tester().ExpectTotalCount(kActionsHistogram, 0);
+
+  GetSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, CONTENT_SETTING_BLOCK);
+  histogram_tester().ExpectBucketCount(kActionsHistogram,
+                                       kActionContentSettingsBlockedGlobal, 1);
+
+  GetSettingsMap()->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_SUBRESOURCE_FILTER, CONTENT_SETTING_BLOCK);
+  histogram_tester().ExpectBucketCount(kActionsHistogram,
+                                       kActionContentSettingsBlockedGlobal, 1);
+}
+
 TEST_F(SubresourceFilterContentSettingsManagerHistoryTest,
        HistoryUrlDeleted_ClearsWebsiteSetting) {
   if (!settings_manager()->should_use_smart_ui())
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc
index cfc07f82..9208fb3 100644
--- a/chrome/browser/sync/test/integration/bookmarks_helper.cc
+++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc
index c666e53d..81b6588 100644
--- a/chrome/browser/sync/test/integration/passwords_helper.cc
+++ b/chrome/browser/sync/test/integration/passwords_helper.cc
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc b/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
index 4c61e43..6b8229ff 100644
--- a/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h"
 
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
index 2bbf4cc1..c52dae5f 100644
--- a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
+++ b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/task_manager/mock_web_contents_task_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -14,7 +15,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "net/dns/mock_host_resolver.h"
@@ -205,12 +206,8 @@
   SubframeTaskTDIBrowserTest() {}
   ~SubframeTaskTDIBrowserTest() override {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    InProcessBrowserTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitch(switches::kTopDocumentIsolation);
-  }
-
   void SetUpOnMainThread() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
     host_resolver()->AddRule("*", "127.0.0.1");
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
     content::SetupCrossSiteRedirector(embedded_test_server());
@@ -223,6 +220,8 @@
   }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(SubframeTaskTDIBrowserTest);
 };
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 3125170..b608ee7 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2218,6 +2218,7 @@
       "//crypto:platform",
       "//device/usb/mojo",
       "//device/usb/public/interfaces",
+      "//device/vr/features",
       "//ui/android",
     ]
 
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
index ac74224..5c963a6 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
@@ -7,6 +7,7 @@
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc b/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc
index ffe3a88..ba90cf5 100644
--- a/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc
+++ b/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/desktop_ios_promotion/sms_service.h"
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 1bfa5311..6e3c531 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -21,7 +21,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
@@ -203,16 +203,17 @@
   HostedAppVsTdiTest() {}
   ~HostedAppVsTdiTest() override {}
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    HostedAppTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitch(switches::kTopDocumentIsolation);
-  }
-
   void SetUpOnMainThread() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
     HostedAppTest::SetUpOnMainThread();
     host_resolver()->AddRule("*", "127.0.0.1");
     ASSERT_TRUE(embedded_test_server()->Start());
   }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(HostedAppVsTdiTest);
 };
 
 // Tests that even with --top-document-isolation, app.site.com (covered by app's
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 00eadabc..c42d1c9 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
index 7fb1d54..7c3bd44 100644
--- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -9,6 +9,7 @@
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/metrics/statistics_recorder.h"
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 7cb45b44..ebd2d83 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -78,6 +78,12 @@
 #include "chrome/browser/android/offline_pages/recent_tab_helper.h"
 #include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h"
 #include "chrome/browser/android/voice_search_tab_helper.h"
+
+#include "device/vr/features/features.h"  // nogncheck
+#if BUILDFLAG(ENABLE_VR)
+#include "chrome/browser/android/vr_shell/vr_tab_helper.h"
+#endif  // BUILDFLAG(ENABLE_VR)
+
 #include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h"
 #include "chrome/browser/ui/android/context_menu_helper.h"
 #include "chrome/browser/ui/android/view_android_helper.h"
@@ -231,6 +237,11 @@
   SingleTabModeTabHelper::CreateForWebContents(web_contents);
   ViewAndroidHelper::CreateForWebContents(web_contents);
   VoiceSearchTabHelper::CreateForWebContents(web_contents);
+
+#if BUILDFLAG(ENABLE_VR)
+  vr_shell::VrTabHelper::CreateForWebContents(web_contents);
+#endif
+
 #else
   BookmarkTabHelper::CreateForWebContents(web_contents);
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
index bc73e882..037f870 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
index 6ffb884..b9ba6298 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
@@ -6,6 +6,7 @@
 #include "ash/test/ash_test_helper.h"
 #include "ash/test/ash_test_views_delegate.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/extensions/test_extension_environment.h"
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.h"
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h"
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
index 11380bc..eff752c 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_environment.h"
diff --git a/chrome/browser/ui/views/first_run_bubble_unittest.cc b/chrome/browser/ui/views/first_run_bubble_unittest.cc
index 91c4bd0..836fb0b 100644
--- a/chrome/browser/ui/views/first_run_bubble_unittest.cc
+++ b/chrome/browser/ui/views/first_run_bubble_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/first_run_bubble.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
index 2b19145..ef906ff 100644
--- a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
+++ b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
@@ -12,6 +12,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/scoped_comptr.h"
diff --git a/chrome/browser/ui/views/menu_model_adapter_test.cc b/chrome/browser/ui/views/menu_model_adapter_test.cc
index 1bde65a2..3bb96e2 100644
--- a/chrome/browser/ui/views/menu_model_adapter_test.cc
+++ b/chrome/browser/ui/views/menu_model_adapter_test.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ui/views/controls/menu/menu_model_adapter.h"
 #include "base/callback.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -17,7 +19,6 @@
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/controls/menu/menu_controller.h"
 #include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_model_adapter.h"
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/controls/menu/submenu_view.h"
 #include "ui/views/widget/root_view.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 73b462d..b5eb4956 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -217,7 +217,6 @@
   // views::BubbleDialogDelegateView:
   void OnWidgetDestroying(views::Widget* widget) override;
   int GetDialogButtons() const override;
-  bool ShouldSnapFrameWidth() const override;
 
  private:
   friend class PageInfoBubbleView;
@@ -379,10 +378,6 @@
   return ui::DIALOG_BUTTON_NONE;
 }
 
-bool InternalPageInfoBubbleView::ShouldSnapFrameWidth() const {
-  return false;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // PageInfoBubbleView
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
index b3b3526..dd50c2a 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -64,7 +64,7 @@
   // required.
   columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 1,
                      views::GridLayout::USE_PREF, 0, 0);
-  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
+  columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, 0,
                      views::GridLayout::FIXED, kAmountSectionWidth,
                      kAmountSectionWidth);
 
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
index ad0ee53..7dfb4fd 100644
--- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
+++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/browser_finder.h"
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 586e1f7..accae71 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -16,6 +16,7 @@
 #include "base/location.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"
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 4497720..33bdf4c 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -142,19 +142,29 @@
                             IDR_CUSTOM_ELEMENTS_OOBE_HTML);
     source->AddResourcePath(kCustomElementsJSPath, IDR_CUSTOM_ELEMENTS_OOBE_JS);
   } else if (display_type == OobeUI::kLockDisplay) {
-    source->SetDefaultResource(IDR_LOCK_HTML);
-    source->AddResourcePath(kLockJSPath, IDR_LOCK_JS);
+    if (command_line->HasSwitch(chromeos::switches::kShowNonViewMdLogin)) {
+      source->SetDefaultResource(IDR_MD_LOCK_HTML);
+      source->AddResourcePath(kLockJSPath, IDR_MD_LOCK_JS);
+      source->AddResourcePath(kCustomElementsPinKeyboardHTMLPath,
+                              IDR_MD_CUSTOM_ELEMENTS_PIN_KEYBOARD_HTML);
+      source->AddResourcePath(kCustomElementsPinKeyboardJSPath,
+                              IDR_MD_CUSTOM_ELEMENTS_PIN_KEYBOARD_JS);
+    } else {
+      source->SetDefaultResource(IDR_LOCK_HTML);
+      source->AddResourcePath(kLockJSPath, IDR_LOCK_JS);
+      source->AddResourcePath(kCustomElementsPinKeyboardHTMLPath,
+                              IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_HTML);
+      source->AddResourcePath(kCustomElementsPinKeyboardJSPath,
+                              IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_JS);
+    }
     source->AddResourcePath(kCustomElementsHTMLPath,
                             IDR_CUSTOM_ELEMENTS_LOCK_HTML);
     source->AddResourcePath(kCustomElementsJSPath, IDR_CUSTOM_ELEMENTS_LOCK_JS);
-    source->AddResourcePath(kCustomElementsPinKeyboardHTMLPath,
-                            IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_HTML);
-    source->AddResourcePath(kCustomElementsPinKeyboardJSPath,
-                            IDR_CUSTOM_ELEMENTS_PIN_KEYBOARD_JS);
     source->AddResourcePath(kCustomElementsUserPodHTMLPath,
                             IDR_CUSTOM_ELEMENTS_USER_POD_HTML);
   } else {
-    if (command_line->HasSwitch(chromeos::switches::kShowMdLogin)) {
+    if (command_line->HasSwitch(chromeos::switches::kShowMdLogin) ||
+        command_line->HasSwitch(chromeos::switches::kShowNonViewMdLogin)) {
       source->SetDefaultResource(IDR_MD_LOGIN_HTML);
       source->AddResourcePath(kLoginJSPath, IDR_MD_LOGIN_JS);
     } else {
diff --git a/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc b/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc
index 187ea14..3e1e451 100644
--- a/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/callback.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
index 75ae4c0..15bbabc 100644
--- a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
@@ -11,6 +11,7 @@
 #include "base/bind_helpers.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
diff --git a/chrome/browser/ui/webui/web_ui_test_handler.cc b/chrome/browser/ui/webui/web_ui_test_handler.cc
index a249c1e..0c700a9a 100644
--- a/chrome/browser/ui/webui/web_ui_test_handler.cc
+++ b/chrome/browser/ui/webui/web_ui_test_handler.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/render_messages.h"
diff --git a/chrome/browser/usb/usb_browsertest.cc b/chrome/browser/usb/usb_browsertest.cc
index 6578749f..011ac356 100644
--- a/chrome/browser/usb/usb_browsertest.cc
+++ b/chrome/browser/usb/usb_browsertest.cc
@@ -19,7 +19,6 @@
 #include "device/usb/mock_usb_device.h"
 #include "device/usb/mock_usb_service.h"
 #include "device/usb/public/interfaces/chooser_service.mojom.h"
-#include "device/usb/webusb_descriptors.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -104,14 +103,6 @@
     scoped_refptr<MockUsbDevice> mock_device(
         new MockUsbDevice(0, 0, "Test Manufacturer", "Test Device", "123456"));
     device_client_->usb_service()->AddDevice(mock_device);
-
-    mock_device =
-        new MockUsbDevice(1, 0, "Test Manufacturer", "Test Device", "ABCDEF");
-    auto allowed_origins = base::MakeUnique<device::WebUsbAllowedOrigins>();
-    allowed_origins->origins.push_back(
-        embedded_test_server()->GetURL("localhost", "/").GetOrigin());
-    mock_device->set_webusb_allowed_origins(std::move(allowed_origins));
-    device_client_->usb_service()->AddDevice(mock_device);
   }
 
  private:
@@ -131,11 +122,18 @@
   render_frame_host->GetInterfaceRegistry()->AddInterface(
       base::Bind(&FakeChooserService::Create, render_frame_host));
 
-  // The mock device with vendorId == 0 has no WebUSB allowed origin descriptor
-  // but because this is a top level frame it will be allowed.
   std::string result;
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
       web_contents,
+      "navigator.usb.getDevices()"
+      "    .then(devices => {"
+      "        domAutomationController.send(devices.length.toString());"
+      "     });",
+      &result));
+  EXPECT_EQ("0", result);
+
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      web_contents,
       "navigator.usb.requestDevice({ filters: [ { vendorId: 0 } ] })"
       "    .then(device => {"
       "        domAutomationController.send(device.serialNumber);"
@@ -153,51 +151,4 @@
   EXPECT_EQ("1", result);
 }
 
-IN_PROC_BROWSER_TEST_F(WebUsbTest, RequestAndGetDevicesInIframe) {
-  ui_test_utils::NavigateToURL(
-      browser(),
-      embedded_test_server()->GetURL("localhost", "/page_with_iframe.html"));
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  RenderFrameHost* main_frame = web_contents->GetMainFrame();
-  EXPECT_THAT(main_frame->GetLastCommittedOrigin().Serialize(),
-              testing::StartsWith("http://localhost:"));
-  RenderFrameHost* embedded_frame = ChildFrameAt(main_frame, 0);
-  EXPECT_THAT(embedded_frame->GetLastCommittedOrigin().Serialize(),
-              testing::StartsWith("http://localhost:"));
-
-  embedded_frame->GetInterfaceRegistry()->AddInterface(
-      base::Bind(&FakeChooserService::Create, embedded_frame));
-
-  // The mock device with vendorId == 0 has no allowed origin descriptor so an
-  // embedded frame will not be able to select it.
-  std::string result;
-  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
-      embedded_frame,
-      "navigator.usb.requestDevice({ filters: [ { vendorId: 0 } ] })"
-      "    .catch(e => { domAutomationController.send(e.toString()); });",
-      &result));
-  EXPECT_EQ("NotFoundError: No device selected.", result);
-
-  // The mock device with vendorId == 1 does however have the embedded test
-  // server listed as an allowed origin.
-  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
-      embedded_frame,
-      "navigator.usb.requestDevice({ filters: [ { vendorId: 1 } ] })"
-      "    .then(device => {"
-      "        domAutomationController.send(device.serialNumber);"
-      "     });",
-      &result));
-  EXPECT_EQ("ABCDEF", result);
-
-  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
-      embedded_frame,
-      "navigator.usb.getDevices()"
-      "    .then(devices => {"
-      "        domAutomationController.send(devices.length.toString());"
-      "     });",
-      &result));
-  EXPECT_EQ("1", result);
-}
-
 }  // namespace
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc
index 9a9cd36f..9433805 100644
--- a/chrome/browser/usb/usb_chooser_controller.cc
+++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -29,7 +29,6 @@
 #include "device/usb/usb_device.h"
 #include "device/usb/usb_device_filter.h"
 #include "device/usb/usb_ids.h"
-#include "device/usb/webusb_descriptors.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
@@ -97,7 +96,6 @@
   RenderFrameHost* main_frame = web_contents->GetMainFrame();
   requesting_origin_ = render_frame_host->GetLastCommittedURL().GetOrigin();
   embedding_origin_ = main_frame->GetLastCommittedURL().GetOrigin();
-  is_embedded_frame_ = render_frame_host != main_frame;
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   chooser_context_ =
@@ -140,8 +138,7 @@
     return false;
 
   return WebUSBPermissionProvider::HasDevicePermission(
-      chooser_context_.get(), requesting_origin_, embedding_origin_,
-      is_embedded_frame_, device);
+      chooser_context_.get(), requesting_origin_, embedding_origin_, device);
 }
 
 void UsbChooserController::RefreshOptions() {}
@@ -232,12 +229,5 @@
   if (UsbBlocklist::Get().IsExcluded(device))
     return false;
 
-  // Embedded frames must have their origin in the list provided by the device.
-  if (is_embedded_frame_) {
-    return device::FindInWebUsbAllowedOrigins(device->webusb_allowed_origins(),
-                                              requesting_origin_, base::nullopt,
-                                              base::nullopt);
-  }
-
   return true;
 }
diff --git a/chrome/browser/usb/usb_chooser_controller.h b/chrome/browser/usb/usb_chooser_controller.h
index 4dd1d3d..02611fd 100644
--- a/chrome/browser/usb/usb_chooser_controller.h
+++ b/chrome/browser/usb/usb_chooser_controller.h
@@ -66,7 +66,6 @@
   device::mojom::UsbChooserService::GetPermissionCallback callback_;
   GURL requesting_origin_;
   GURL embedding_origin_;
-  bool is_embedded_frame_;
 
   base::WeakPtr<UsbChooserContext> chooser_context_;
   ScopedObserver<device::UsbService, device::UsbService::Observer>
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc
index 76622dd..8e63cd5 100644
--- a/chrome/browser/usb/usb_chooser_controller_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -64,10 +64,6 @@
       const std::string& serial_number) {
     scoped_refptr<device::MockUsbDevice> device(new device::MockUsbDevice(
         0, 1, "Google", product_string, serial_number));
-    std::unique_ptr<device::WebUsbAllowedOrigins> webusb_allowed_origins(
-        new device::WebUsbAllowedOrigins());
-    webusb_allowed_origins->origins.push_back(GURL(kDefaultTestUrl));
-    device->set_webusb_allowed_origins(std::move(webusb_allowed_origins));
     return device;
   }
 
diff --git a/chrome/browser/usb/usb_tab_helper.cc b/chrome/browser/usb/usb_tab_helper.cc
index 539e878..a3ab205 100644
--- a/chrome/browser/usb/usb_tab_helper.cc
+++ b/chrome/browser/usb/usb_tab_helper.cc
@@ -10,7 +10,11 @@
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/usb/web_usb_permission_provider.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/common/content_features.h"
 #include "device/usb/mojo/device_manager_impl.h"
+#include "mojo/public/cpp/bindings/message.h"
+#include "third_party/WebKit/public/platform/WebFeaturePolicyFeature.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/usb/web_usb_chooser_service_android.h"
@@ -21,6 +25,15 @@
 using content::RenderFrameHost;
 using content::WebContents;
 
+namespace {
+
+// The renderer performs its own feature policy checks so a request that gets
+// to the browser process indicates malicous code.
+const char kFeaturePolicyViolation[] =
+    "Feature policy blocks access to WebUSB.";
+
+}  // namespace
+
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(UsbTabHelper);
 
 struct FrameUsbServices {
@@ -49,7 +62,10 @@
 void UsbTabHelper::CreateDeviceManager(
     RenderFrameHost* render_frame_host,
     mojo::InterfaceRequest<device::mojom::UsbDeviceManager> request) {
-  DCHECK(WebContents::FromRenderFrameHost(render_frame_host) == web_contents());
+  if (!AllowedByFeaturePolicy(render_frame_host)) {
+    mojo::ReportBadMessage(kFeaturePolicyViolation);
+    return;
+  }
   device::usb::DeviceManagerImpl::Create(
       GetPermissionProvider(render_frame_host), std::move(request));
 }
@@ -57,6 +73,10 @@
 void UsbTabHelper::CreateChooserService(
     content::RenderFrameHost* render_frame_host,
     mojo::InterfaceRequest<device::mojom::UsbChooserService> request) {
+  if (!AllowedByFeaturePolicy(render_frame_host)) {
+    mojo::ReportBadMessage(kFeaturePolicyViolation);
+    return;
+  }
   GetChooserService(render_frame_host, std::move(request));
 }
 
@@ -144,3 +164,13 @@
   }
 #endif
 }
+
+bool UsbTabHelper::AllowedByFeaturePolicy(
+    RenderFrameHost* render_frame_host) const {
+  DCHECK(WebContents::FromRenderFrameHost(render_frame_host) == web_contents());
+  if (base::FeatureList::IsEnabled(features::kFeaturePolicy)) {
+    return render_frame_host->IsFeatureEnabled(
+        blink::WebFeaturePolicyFeature::kUsb);
+  }
+  return web_contents()->GetMainFrame() == render_frame_host;
+}
diff --git a/chrome/browser/usb/usb_tab_helper.h b/chrome/browser/usb/usb_tab_helper.h
index 6a9a361..ceefd7f6 100644
--- a/chrome/browser/usb/usb_tab_helper.h
+++ b/chrome/browser/usb/usb_tab_helper.h
@@ -68,6 +68,9 @@
 
   void NotifyTabStateChanged() const;
 
+  bool AllowedByFeaturePolicy(
+      content::RenderFrameHost* render_frame_host) const;
+
   FrameUsbServicesMap frame_usb_services_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbTabHelper);
diff --git a/chrome/browser/usb/web_usb_permission_provider.cc b/chrome/browser/usb/web_usb_permission_provider.cc
index 5693689..4deb803 100644
--- a/chrome/browser/usb/web_usb_permission_provider.cc
+++ b/chrome/browser/usb/web_usb_permission_provider.cc
@@ -17,7 +17,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "device/usb/usb_device.h"
-#include "device/usb/webusb_descriptors.h"
 
 using content::RenderFrameHost;
 using content::WebContents;
@@ -27,33 +26,14 @@
     UsbChooserContext* chooser_context,
     const GURL& requesting_origin,
     const GURL& embedding_origin,
-    bool is_embedded_frame,
     scoped_refptr<const device::UsbDevice> device) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (UsbBlocklist::Get().IsExcluded(device))
     return false;
 
-  if (!chooser_context->HasDevicePermission(requesting_origin, embedding_origin,
-                                            device)) {
-    return false;
-  }
-
-  // On Android it is not possible to read the WebUSB descriptors until Chrome
-  // has been granted permission to open it. Instead we grant provisional access
-  // to the device and perform the allowed origins check when the client tries
-  // to open it.
-  if (!device->permission_granted())
-    return true;
-
-  // Embedded frames must have their origin in the list provided by the device.
-  if (is_embedded_frame) {
-    return device::FindInWebUsbAllowedOrigins(device->webusb_allowed_origins(),
-                                              requesting_origin, base::nullopt,
-                                              base::nullopt);
-  }
-
-  return true;
+  return chooser_context->HasDevicePermission(requesting_origin,
+                                              embedding_origin, device);
 }
 
 WebUSBPermissionProvider::WebUSBPermissionProvider(
@@ -83,47 +63,7 @@
   return HasDevicePermission(
       UsbChooserContextFactory::GetForProfile(profile),
       render_frame_host_->GetLastCommittedURL().GetOrigin(),
-      main_frame->GetLastCommittedURL().GetOrigin(),
-      render_frame_host_ != main_frame, device);
-}
-
-bool WebUSBPermissionProvider::HasConfigurationPermission(
-    uint8_t requested_configuration_value,
-    scoped_refptr<const device::UsbDevice> device) const {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // Embedded frames may only access configurations if their origin in the list
-  // provided by the device.
-  RenderFrameHost* main_frame =
-      WebContents::FromRenderFrameHost(render_frame_host_)->GetMainFrame();
-  if (render_frame_host_ != main_frame) {
-    return device::FindInWebUsbAllowedOrigins(
-        device->webusb_allowed_origins(),
-        render_frame_host_->GetLastCommittedURL().GetOrigin(),
-        requested_configuration_value, base::nullopt);
-  }
-
-  return true;
-}
-
-bool WebUSBPermissionProvider::HasFunctionPermission(
-    uint8_t requested_function,
-    uint8_t configuration_value,
-    scoped_refptr<const device::UsbDevice> device) const {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // Embedded frames may only access configurations if their origin in the list
-  // provided by the device.
-  RenderFrameHost* main_frame =
-      WebContents::FromRenderFrameHost(render_frame_host_)->GetMainFrame();
-  if (render_frame_host_ != main_frame) {
-    return device::FindInWebUsbAllowedOrigins(
-        device->webusb_allowed_origins(),
-        render_frame_host_->GetLastCommittedURL().GetOrigin(),
-        configuration_value, requested_function);
-  }
-
-  return true;
+      main_frame->GetLastCommittedURL().GetOrigin(), device);
 }
 
 void WebUSBPermissionProvider::IncrementConnectionCount() {
diff --git a/chrome/browser/usb/web_usb_permission_provider.h b/chrome/browser/usb/web_usb_permission_provider.h
index 436255e..5fd2e6d 100644
--- a/chrome/browser/usb/web_usb_permission_provider.h
+++ b/chrome/browser/usb/web_usb_permission_provider.h
@@ -27,7 +27,6 @@
       UsbChooserContext* chooser_context,
       const GURL& requesting_origin,
       const GURL& embedding_origin,
-      bool is_embedded_frame,
       scoped_refptr<const device::UsbDevice> device);
 
   explicit WebUSBPermissionProvider(
@@ -39,13 +38,6 @@
   // device::usb::PermissionProvider implementation.
   bool HasDevicePermission(
       scoped_refptr<const device::UsbDevice> device) const override;
-  bool HasConfigurationPermission(
-      uint8_t requested_configuration,
-      scoped_refptr<const device::UsbDevice> device) const override;
-  bool HasFunctionPermission(
-      uint8_t requested_function,
-      uint8_t configuration_value,
-      scoped_refptr<const device::UsbDevice> device) const override;
   void IncrementConnectionCount() override;
   void DecrementConnectionCount() override;
 
diff --git a/chrome/browser/win/jumplist.cc b/chrome/browser/win/jumplist.cc
index 24ac405c..9054e20 100644
--- a/chrome/browser/win/jumplist.cc
+++ b/chrome/browser/win/jumplist.cc
@@ -55,15 +55,28 @@
 
 namespace {
 
+// The number of updates to skip to alleviate the machine when a previous update
+// was too slow.
+constexpr int kUpdatesToSkipUnderHeavyLoad = 10;
+
 // The delay before updating the JumpList to prevent update storms.
 constexpr base::TimeDelta kDelayForJumplistUpdate =
     base::TimeDelta::FromMilliseconds(3500);
 
 // The maximum allowed time for JumpListUpdater::BeginUpdate. Updates taking
 // longer than this are discarded to prevent bogging down slow machines.
-constexpr base::TimeDelta kTimeOutForJumplistUpdate =
+constexpr base::TimeDelta kTimeOutForJumplistBeginUpdate =
     base::TimeDelta::FromMilliseconds(500);
 
+// The maximum allowed time for updating both "most visited" and "recently
+// closed" categories via JumpListUpdater::AddCustomCategory.
+constexpr base::TimeDelta kTimeOutForAddCustomCategory =
+    base::TimeDelta::FromMilliseconds(500);
+
+// The maximum allowed time for JumpListUpdater::CommitUpdate.
+constexpr base::TimeDelta kTimeOutForJumplistCommitUpdate =
+    base::TimeDelta::FromMilliseconds(1000);
+
 // Appends the common switches to each shell link.
 void AppendCommonSwitches(ShellLinkItem* shell_link) {
   const char* kSwitchNames[] = { switches::kUserDataDir };
@@ -514,6 +527,11 @@
 }
 
 void JumpList::DeferredTopSitesChanged() {
+  if (updates_to_skip_ > 0) {
+    --updates_to_skip_;
+    return;
+  }
+
   scoped_refptr<history::TopSites> top_sites =
       TopSitesFactory::GetForProfile(profile_);
   if (top_sites) {
@@ -525,6 +543,11 @@
 }
 
 void JumpList::DeferredTabRestoreServiceChanged() {
+  if (updates_to_skip_ > 0) {
+    --updates_to_skip_;
+    return;
+  }
+
   // Create a list of ShellLinkItems from the "Recently Closed" pages.
   // As noted above, we create a ShellLinkItem objects with the following
   // parameters.
@@ -610,9 +633,12 @@
 
   // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer
   // than the maximum allowed time, as it's very likely the following update
-  // steps will also take a long time.
-  if (begin_update_timer.Elapsed() >= kTimeOutForJumplistUpdate)
+  // steps will also take a long time. As we've not updated the icons on the
+  // disk, discarding this update wont't affect the current JumpList used by OS.
+  if (begin_update_timer.Elapsed() >= kTimeOutForJumplistBeginUpdate) {
+    updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad;
     return false;
+  }
 
   // The default maximum number of items to display in JumpList is 10.
   // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx
@@ -677,6 +703,8 @@
   // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407.
   SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration");
 
+  base::ElapsedTimer add_custom_category_timer;
+
   // Update the "Most Visited" category of the JumpList if it exists.
   // This update request is applied into the JumpList when we commit this
   // transaction.
@@ -693,12 +721,30 @@
     return false;
   }
 
+  // If JumpListUpdater::AddCustomCategory or JumpListUpdater::CommitUpdate
+  // takes longer than the maximum allowed time, skip the next
+  // |kUpdatesToSkipUnderHeavyLoad| updates. This update should be finished
+  // because we've already updated the icons on the disk. If discarding this
+  // update from here, some items in the current JumpList may not have icons
+  // as they've been delete from the disk. In this case, the background color of
+  // the JumpList panel is used instead, which doesn't look nice.
+
+  if (add_custom_category_timer.Elapsed() >= kTimeOutForAddCustomCategory)
+    updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad;
+
   // Update the "Tasks" category of the JumpList.
   if (!UpdateTaskCategory(&jumplist_updater, incognito_availability))
     return false;
 
+  base::ElapsedTimer commit_update_timer;
+
   // Commit this transaction and send the updated JumpList to Windows.
-  return jumplist_updater.CommitUpdate();
+  bool commit_result = jumplist_updater.CommitUpdate();
+
+  if (commit_update_timer.Elapsed() >= kTimeOutForJumplistCommitUpdate)
+    updates_to_skip_ = kUpdatesToSkipUnderHeavyLoad;
+
+  return commit_result;
 }
 
 void JumpList::RunUpdateJumpList(
diff --git a/chrome/browser/win/jumplist.h b/chrome/browser/win/jumplist.h
index c4b6c857..f85400e 100644
--- a/chrome/browser/win/jumplist.h
+++ b/chrome/browser/win/jumplist.h
@@ -233,6 +233,10 @@
   // jumplist.
   base::OneShotTimer timer_recently_closed_;
 
+  // Number of updates to skip to alleviate the machine when a previous update
+  // was too slow. Updates will be resumed when this reaches 0 again.
+  int updates_to_skip_ = 0;
+
   // Holds data that can be accessed from multiple threads.
   scoped_refptr<base::RefCountedData<JumpListData>> jumplist_data_;
 
diff --git a/chrome/chrome_watcher/chrome_watcher_main.cc b/chrome/chrome_watcher/chrome_watcher_main.cc
index b231cb60..e62e67e5 100644
--- a/chrome/chrome_watcher/chrome_watcher_main.cc
+++ b/chrome/chrome_watcher/chrome_watcher_main.cc
@@ -18,6 +18,7 @@
 #include "base/logging_win.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/memory.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
diff --git a/chrome/common/service_process_util_mac_unittest.mm b/chrome/common/service_process_util_mac_unittest.mm
index eb1c994..c4eaff8 100644
--- a/chrome/common/service_process_util_mac_unittest.mm
+++ b/chrome/common/service_process_util_mac_unittest.mm
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/launch.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/chrome/common/service_process_util_unittest.cc b/chrome/common/service_process_util_unittest.cc
index 1554f12..aa31ac4 100644
--- a/chrome/common/service_process_util_unittest.cc
+++ b/chrome/common/service_process_util_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/kill.h"
 #include "base/process/launch.h"
 #include "base/run_loop.h"
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index f620dc4..d17f68e5 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -823,7 +823,7 @@
 
 const char kBluetoothAdapterOffHelpURL[] =
 #if defined(OS_CHROMEOS)
-    "chrome://settings/#Bluetooth";
+    "chrome://settings/?search=bluetooth";
 #else
     "https://support.google.com/chrome?p=bluetooth";
 #endif
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index 6fc17ce..0590439 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -1678,8 +1678,12 @@
   SimulateUsernameChange("Bob");
   SimulatePasswordChange("mypassword");
 
-  username_element_.SetAttribute("style", "display:none;");
-  password_element_.SetAttribute("style", "display:none;");
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
 
   password_autofill_agent_->AJAXSucceeded();
 
@@ -1693,6 +1697,34 @@
                              expected_properties_masks);
 }
 
+TEST_F(PasswordAutofillAgentTest, RememberFieldPropertiesOnInPageNavigation_2) {
+  LoadHTML(kNoFormHTML);
+  UpdateUsernameAndPasswordElements();
+
+  SimulateUsernameChange("Bob");
+  SimulatePasswordChange("mypassword");
+
+  password_autofill_agent_->AJAXSucceeded();
+
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
+
+  base::RunLoop().RunUntilIdle();
+
+  std::map<base::string16, FieldPropertiesMask> expected_properties_masks;
+  expected_properties_masks[ASCIIToUTF16("username")] =
+      FieldPropertiesFlags::USER_TYPED;
+  expected_properties_masks[ASCIIToUTF16("password")] =
+      FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
+
+  ExpectFieldPropertiesMasks(PasswordFormInPageNavigation,
+                             expected_properties_masks);
+}
+
 // The username/password is autofilled by password manager then just before
 // sending the form off, a script changes them. This test checks that
 // PasswordAutofillAgent can still get the username and the password autofilled.
@@ -2248,8 +2280,12 @@
   SimulateUsernameChange("Bob");
   SimulatePasswordChange("mypassword");
 
-  username_element_.SetAttribute("style", "display:none;");
-  password_element_.SetAttribute("style", "display:none;");
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
 
   password_autofill_agent_->AJAXSucceeded();
 
@@ -2259,6 +2295,30 @@
 }
 
 TEST_F(PasswordAutofillAgentTest,
+       NoForm_PromptForAJAXSubmitWithoutNavigation_2) {
+  LoadHTML(kNoFormHTML);
+  UpdateUsernameAndPasswordElements();
+
+  SimulateUsernameChange("Bob");
+  SimulatePasswordChange("mypassword");
+
+  password_autofill_agent_->AJAXSucceeded();
+
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
+
+  base::RunLoop().RunUntilIdle();
+
+  ExpectInPageNavigationWithUsernameAndPasswords(
+      "Bob", "mypassword", "",
+      PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
+}
+
+TEST_F(PasswordAutofillAgentTest,
        NoForm_NoPromptForAJAXSubmitWithoutNavigationAndElementsVisible) {
   LoadHTML(kNoFormHTML);
   UpdateUsernameAndPasswordElements();
@@ -2291,7 +2351,10 @@
   SimulatePasswordChange("mypassword");
 
   // Simulate captcha element show up right before AJAX completed.
-  captcha_element.SetAttribute("style", "display:inline;");
+  std::string show_captcha =
+      "var captcha = document.getElementById('captcha');"
+      "captcha.style = 'display:inline';";
+  ExecuteJavaScriptForTests(show_captcha.c_str());
   password_autofill_agent_->AJAXSucceeded();
 
   base::RunLoop().RunUntilIdle();
@@ -2299,6 +2362,35 @@
   EXPECT_FALSE(fake_driver_.called_password_form_submitted());
 }
 
+TEST_F(PasswordAutofillAgentTest,
+       NoForm_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {
+  const char kNoFormHTMLWithHiddenField[] =
+      "<INPUT type='text' id='username'/>"
+      "<INPUT type='password' id='password'/>"
+      "<INPUT type='text' id='captcha' style='display:none'/>";
+  LoadHTML(kNoFormHTMLWithHiddenField);
+
+  UpdateUsernameAndPasswordElements();
+  WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById(
+      WebString::FromUTF8("captcha"));
+  ASSERT_FALSE(captcha_element.IsNull());
+
+  SimulateUsernameChange("Bob");
+  SimulatePasswordChange("mypassword");
+
+  password_autofill_agent_->AJAXSucceeded();
+
+  // Simulate captcha element show up right after AJAX completed.
+  std::string show_captcha =
+      "var captcha = document.getElementById('captcha');"
+      "captcha.style = 'display:inline';";
+  ExecuteJavaScriptForTests(show_captcha.c_str());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(fake_driver_.called_inpage_navigation());
+  EXPECT_FALSE(fake_driver_.called_password_form_submitted());
+}
+
 // Tests that no save promt is shown when a form with empty action URL is
 // changed and AJAX completed but the form is still visible.
 TEST_F(PasswordAutofillAgentTest,
@@ -2331,6 +2423,37 @@
   EXPECT_FALSE(fake_driver_.called_password_form_submitted());
 }
 
+TEST_F(PasswordAutofillAgentTest,
+       NoAction_NoPromptForAJAXSubmitWithoutNavigationAndNewElementAppeared_2) {
+  // Form without an action URL.
+  const char kHTMLWithHiddenField[] =
+      "<FORM name='LoginTestForm'>"
+      "  <INPUT type='text' id='username'/>"
+      "  <INPUT type='password' id='password'/>"
+      "  <INPUT type='text' id='captcha' style='display:none'/>"
+      "  <INPUT type='submit' value='Login'/>"
+      "</FORM>";
+  // Set the valid URL so the form action URL can be generated properly.
+  LoadHTMLWithUrlOverride(kHTMLWithHiddenField, "https://www.example.com");
+
+  UpdateUsernameAndPasswordElements();
+  WebElement captcha_element = GetMainFrame()->GetDocument().GetElementById(
+      WebString::FromUTF8("captcha"));
+  ASSERT_FALSE(captcha_element.IsNull());
+
+  SimulateUsernameChange("Bob");
+  SimulatePasswordChange("mypassword");
+
+  password_autofill_agent_->AJAXSucceeded();
+
+  // Simulate captcha element show up right after AJAX completed.
+  captcha_element.SetAttribute("style", "display:inline;");
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(fake_driver_.called_inpage_navigation());
+  EXPECT_FALSE(fake_driver_.called_password_form_submitted());
+}
+
 // Tests that credential suggestions are autofilled on a password (and change
 // password) forms having either ambiguous or empty name.
 TEST_F(PasswordAutofillAgentTest,
@@ -2541,8 +2664,12 @@
   SimulateUsernameChange("Alice");
 
   // Hide form elements to simulate successful login.
-  username_element_.SetAttribute("style", "display:none;");
-  password_element_.SetAttribute("style", "display:none;");
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
 
   password_autofill_agent_->AJAXSucceeded();
 
@@ -2552,6 +2679,31 @@
 }
 
 TEST_F(PasswordAutofillAgentTest,
+       UsernameChangedAfterPasswordInput_InPageNavigation_2) {
+  LoadHTML(kNoFormHTML);
+  UpdateUsernameAndPasswordElements();
+
+  SimulateUsernameChange("Bob");
+  SimulatePasswordChange("mypassword");
+  SimulateUsernameChange("Alice");
+
+  password_autofill_agent_->AJAXSucceeded();
+
+  // Hide form elements to simulate successful login.
+  std::string hide_elements =
+      "var password = document.getElementById('password');"
+      "password.style = 'display:none';"
+      "var username = document.getElementById('username');"
+      "username.style = 'display:none';";
+  ExecuteJavaScriptForTests(hide_elements.c_str());
+  base::RunLoop().RunUntilIdle();
+
+  ExpectInPageNavigationWithUsernameAndPasswords(
+      "Alice", "mypassword", "",
+      PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
+}
+
+TEST_F(PasswordAutofillAgentTest,
        UsernameChangedAfterPasswordInput_FormSubmitted) {
   SimulateUsernameChange("Bob");
   SimulatePasswordChange("mypassword");
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
index c76ab7e..dea1cf9 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
@@ -2,16 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
 #include "chrome/service/service_process.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc
index b6b78f02..88b6954e 100644
--- a/chrome/service/service_process.cc
+++ b/chrome/service/service_process.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8610688..86e5608 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1442,6 +1442,7 @@
       "../browser/memory/tab_manager_observer_browsertest.cc",
       "../browser/metrics/metrics_memory_details_browsertest.cc",
       "../browser/metrics/metrics_service_browsertest.cc",
+      "../browser/metrics/process_memory_metrics_emitter_browsertest.cc",
       "../browser/metrics/startup_metrics_browsertest.cc",
       "../browser/metrics/tab_reactivation_tracker_browsertest.cc",
       "../browser/net/cookie_policy_browsertest.cc",
@@ -1459,6 +1460,7 @@
       "../browser/net/spdyproxy/chrome_data_use_group_browsertest.cc",
       "../browser/net/websocket_browsertest.cc",
       "../browser/ntp_snippets/content_suggestions_service_factory_browsertest.cc",
+      "../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc",
       "../browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h",
diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc
index b07b9377..9a75475 100644
--- a/chrome/test/base/chrome_unit_test_suite.cc
+++ b/chrome/test/base/chrome_unit_test_suite.cc
@@ -5,6 +5,7 @@
 #include "chrome/test/base/chrome_unit_test_suite.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/process_handle.h"
 #include "build/build_config.h"
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index c43d29f..aeebf2c7 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc
index 488bc45c..86ba264 100644
--- a/chrome/test/chromedriver/commands_unittest.cc
+++ b/chrome/test/chromedriver/commands_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/files/file_path.h"
 #include "base/location.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/synchronization/lock.h"
diff --git a/chrome/test/data/ads_observer/docwrite_provisional_frame.html b/chrome/test/data/ads_observer/docwrite_provisional_frame.html
new file mode 100644
index 0000000..c2a8cc0
--- /dev/null
+++ b/chrome/test/data/ads_observer/docwrite_provisional_frame.html
@@ -0,0 +1,20 @@
+<html>
+<iframe id="slow_frame" name="google_ads_iframe" src="/slow?100"></iframe>
+
+<script>
+  window.addEventListener('message', function(e) {
+    domAutomationController.setAutomationId(0);
+    window.domAutomationController.send(e.data);
+  });
+
+  // slow takes 100 seconds to load, plenty of time to overwrite the
+  // provisional load.
+  let iframe = document.getElementById("slow_frame");
+  let doc = iframe.contentDocument;
+
+  doc.open();
+  doc.write("<html>Rewritten. <img src=pixel.png> <img src=pixel2.png> <img src=pixel3.png onload='parent.postMessage(&quot;loaded&quot;, &quot;*&quot;);'></html>");
+  doc.close();
+</script>
+
+</html>
diff --git a/chrome/test/data/ads_observer/pixel.png b/chrome/test/data/ads_observer/pixel.png
new file mode 100644
index 0000000..c5916f2
--- /dev/null
+++ b/chrome/test/data/ads_observer/pixel.png
Binary files differ
diff --git a/chrome/test/data/ads_observer/pixel2.png b/chrome/test/data/ads_observer/pixel2.png
new file mode 100644
index 0000000..c5916f2
--- /dev/null
+++ b/chrome/test/data/ads_observer/pixel2.png
Binary files differ
diff --git a/chrome/test/data/ads_observer/pixel3.png b/chrome/test/data/ads_observer/pixel3.png
new file mode 100644
index 0000000..c5916f2
--- /dev/null
+++ b/chrome/test/data/ads_observer/pixel3.png
Binary files differ
diff --git a/chrome/utility/image_writer/image_writer_unittest.cc b/chrome/utility/image_writer/image_writer_unittest.cc
index 7de30b5..0d107c4b 100644
--- a/chrome/utility/image_writer/image_writer_unittest.cc
+++ b/chrome/utility/image_writer/image_writer_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/utility/image_writer/error_messages.h"
 #include "chrome/utility/image_writer/image_writer.h"
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index aab5d07..ea8a603 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -216,8 +216,10 @@
 
 DefaultCommandLineSwitch g_default_switches[] = {
 #if defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CAST_AUDIO_ONLY)
     // Disables Chromecast-specific WiFi-related features on ATV for now.
     {switches::kNoWifi, ""},
+#endif  // !BUILDFLAG(IS_CAST_AUDIO_ONLY)
     // TODO(714676): this should probably set the no restrictions autoplay
     // policy instead.
     {switches::kIgnoreAutoplayRestrictionsForTests, ""},
diff --git a/chromecast/browser/cast_media_blocker_browsertest.cc b/chromecast/browser/cast_media_blocker_browsertest.cc
index c587346..b258843 100644
--- a/chromecast/browser/cast_media_blocker_browsertest.cc
+++ b/chromecast/browser/cast_media_blocker_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/chromecast/media/audio/cast_audio_mixer_unittest.cc b/chromecast/media/audio/cast_audio_mixer_unittest.cc
index 9f668804..6d716f2 100644
--- a/chromecast/media/audio/cast_audio_mixer_unittest.cc
+++ b/chromecast/media/audio/cast_audio_mixer_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chromecast/media/audio/cast_audio_manager.h"
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
index c1f101e..244d119 100644
--- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
+++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chromecast/base/metrics/cast_metrics_test_helper.h"
diff --git a/chromecast/media/cma/backend/alsa/filter_group.cc b/chromecast/media/cma/backend/alsa/filter_group.cc
index 2e798fe..881a4cf28 100644
--- a/chromecast/media/cma/backend/alsa/filter_group.cc
+++ b/chromecast/media/cma/backend/alsa/filter_group.cc
@@ -11,6 +11,7 @@
 #include "base/values.h"
 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h"
 #include "media/base/audio_bus.h"
+#include "media/base/audio_sample_types.h"
 #include "media/base/vector_math.h"
 
 namespace chromecast {
@@ -25,7 +26,6 @@
       device_ids_(device_ids),
       mixed_inputs_(mixed_inputs),
       output_samples_per_second_(0),
-      channels_(num_channels_),
       post_processing_pipeline_(
           PostProcessingPipeline::Create(name_, filter_list, num_channels_)) {}
 
@@ -66,8 +66,8 @@
   if (active_inputs_.empty() && volume == 0.0f &&
       !post_processing_pipeline_->IsRinging()) {
     if (frames_zeroed_ < chunk_size) {
-      // Ensure mixed_ is zeros. This is necessary if |mixed_| is read later.
-      mixed_->ZeroFramesPartial(0, chunk_size);
+      // Ensure interleaved_ is zeros.
+      std::fill_n(interleaved(), chunk_size * num_channels_, 0);
       frames_zeroed_ = chunk_size;
     }
     return 0.0f;  // Output will be silence, no need to mix.
@@ -80,20 +80,20 @@
   for (StreamMixerAlsa::InputQueue* input : active_inputs_) {
     input->GetResampledData(temp_.get(), chunk_size);
     for (int c = 0; c < num_channels_; ++c) {
-      DCHECK(channels_[c]);
       input->VolumeScaleAccumulate(c != 0, temp_->channel(c), chunk_size,
-                                   channels_[c]);
+                                   mixed_->channel(c));
     }
     volume = std::max(volume, input->EffectiveVolume());
   }
 
+  mixed_->ToInterleaved<::media::FloatSampleTypeTraits<float>>(chunk_size,
+                                                               interleaved());
+
   // Mix FilterGroups
   for (FilterGroup* group : mixed_inputs_) {
     if (group->last_volume() > 0.0f) {
-      for (int c = 0; c < num_channels_; ++c) {
-        ::media::vector_math::FMAC(group->data()->channel(c), 1.0f, chunk_size,
-                                   channels_[c]);
-      }
+      ::media::vector_math::FMAC(group->interleaved(), 1.0f,
+                                 chunk_size * num_channels_, interleaved());
     }
   }
 
@@ -107,7 +107,7 @@
   }
 
   delay_frames_ = post_processing_pipeline_->ProcessFrames(
-      channels_, chunk_size, last_volume_, is_silence);
+      interleaved(), chunk_size, last_volume_, is_silence);
   return last_volume_;
 }
 
@@ -123,12 +123,10 @@
 void FilterGroup::ResizeBuffersIfNecessary(int chunk_size) {
   if (!mixed_ || mixed_->frames() < chunk_size) {
     mixed_ = ::media::AudioBus::Create(num_channels_, chunk_size);
-    for (int c = 0; c < num_channels_; ++c) {
-      channels_[c] = mixed_->channel(c);
-    }
-  }
-  if (!temp_ || temp_->frames() < chunk_size) {
     temp_ = ::media::AudioBus::Create(num_channels_, chunk_size);
+    interleaved_.reset(static_cast<float*>(
+        base::AlignedAlloc(chunk_size * num_channels_ * sizeof(float),
+                           ::media::AudioBus::kChannelAlignment)));
   }
 }
 
diff --git a/chromecast/media/cma/backend/alsa/filter_group.h b/chromecast/media/cma/backend/alsa/filter_group.h
index 5b7c753..6c9f2ae 100644
--- a/chromecast/media/cma/backend/alsa/filter_group.h
+++ b/chromecast/media/cma/backend/alsa/filter_group.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/aligned_memory.h"
 #include "base/values.h"
 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h"
 #include "chromecast/public/volume_control.h"
@@ -77,7 +78,7 @@
   void ClearActiveInputs();
 
   // Retrieves a pointer to the output buffer.
-  ::media::AudioBus* data() { return mixed_.get(); }
+  float* interleaved() { return interleaved_.get(); }
 
   // Get the last used volume.
   float last_volume() const { return last_volume_; }
@@ -103,7 +104,9 @@
   // allocations.
   std::unique_ptr<::media::AudioBus> temp_;
   std::unique_ptr<::media::AudioBus> mixed_;
-  std::vector<float*> channels_;
+
+  // Interleaved data must be aligned to 16 bytes.
+  std::unique_ptr<float, base::AlignedFreeDeleter> interleaved_;
 
   std::unique_ptr<PostProcessingPipeline> post_processing_pipeline_;
 
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline.h b/chromecast/media/cma/backend/alsa/post_processing_pipeline.h
index 9b46c221..a3c89add 100644
--- a/chromecast/media/cma/backend/alsa/post_processing_pipeline.h
+++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline.h
@@ -18,7 +18,7 @@
 class PostProcessingPipeline {
  public:
   virtual ~PostProcessingPipeline() = default;
-  virtual int ProcessFrames(const std::vector<float*>& data,
+  virtual int ProcessFrames(float* data,
                             int num_frames,
                             float current_volume,
                             bool is_silence) = 0;
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc
index 2fd9a83..8a8d0d8a 100644
--- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc
+++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.cc
@@ -76,7 +76,7 @@
 
 PostProcessingPipelineImpl::~PostProcessingPipelineImpl() = default;
 
-int PostProcessingPipelineImpl::ProcessFrames(const std::vector<float*>& data,
+int PostProcessingPipelineImpl::ProcessFrames(float* data,
                                               int num_frames,
                                               float current_multiplier,
                                               bool is_silence) {
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h
index aee1271..f3930dc 100644
--- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h
+++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_impl.h
@@ -31,7 +31,7 @@
                              int channels);
   ~PostProcessingPipelineImpl() override;
 
-  int ProcessFrames(const std::vector<float*>& data,
+  int ProcessFrames(float* data,
                     int num_frames,
                     float current_volume,
                     bool is_silence) override;
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc
index 8f2e8b80..d4128e1 100644
--- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc
+++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.cc
@@ -17,9 +17,7 @@
 
 namespace {
 
-const base::FilePath::CharType kPostProcessingPipelineFilePath[] =
-    FILE_PATH_LITERAL("/etc/cast_audio.json");
-
+const char kPostProcessorsKey[] = "postprocessors";
 const char kOutputStreamsKey[] = "output_streams";
 const char kMixPipelineKey[] = "mix";
 const char kLinearizePipelineKey[] = "linearize";
@@ -28,8 +26,10 @@
 
 }  // namespace
 
+const char kCastAudioConfigFilePath[] = "/etc/cast_audio.json";
+
 StreamPipelineDescriptor::StreamPipelineDescriptor(
-    base::ListValue* pipeline_in,
+    const base::ListValue* pipeline_in,
     const std::unordered_set<std::string>& stream_types_in)
     : pipeline(pipeline_in), stream_types(stream_types_in) {}
 
@@ -40,45 +40,50 @@
     : StreamPipelineDescriptor(other.pipeline, other.stream_types) {}
 
 PostProcessingPipelineParser::PostProcessingPipelineParser(
-    const std::string& json) {
+    const std::string& json)
+    : postprocessor_config_(nullptr) {
   if (json.empty() &&
-      !base::PathExists(base::FilePath(kPostProcessingPipelineFilePath))) {
+      !base::PathExists(base::FilePath(kCastAudioConfigFilePath))) {
     LOG(WARNING) << "Could not open post-processing config in "
-                 << kPostProcessingPipelineFilePath << ".";
+                 << kCastAudioConfigFilePath << ".";
     return;
   }
 
   if (json.empty()) {
-    config_dict_ = base::DictionaryValue::From(DeserializeJsonFromFile(
-        base::FilePath(kPostProcessingPipelineFilePath)));
+    config_dict_ = base::DictionaryValue::From(
+        DeserializeJsonFromFile(base::FilePath(kCastAudioConfigFilePath)));
   } else {
     config_dict_ = base::DictionaryValue::From(DeserializeFromJson(json));
   }
 
-  CHECK(config_dict_) << "Invalid JSON in " << kPostProcessingPipelineFilePath;
+  CHECK(config_dict_) << "Invalid JSON in " << kCastAudioConfigFilePath;
+  if (!config_dict_->GetDictionary(kPostProcessorsKey,
+                                   &postprocessor_config_)) {
+    LOG(WARNING) << "No post-processor config found.";
+  }
 }
 
 PostProcessingPipelineParser::~PostProcessingPipelineParser() = default;
 
 std::vector<StreamPipelineDescriptor>
 PostProcessingPipelineParser::GetStreamPipelines() {
-  base::ListValue* pipelines_list;
   std::vector<StreamPipelineDescriptor> descriptors;
-  if (!config_dict_ ||
-      !config_dict_->GetList(kOutputStreamsKey, &pipelines_list)) {
+  const base::ListValue* pipelines_list;
+  if (!postprocessor_config_ ||
+      !postprocessor_config_->GetList(kOutputStreamsKey, &pipelines_list)) {
     LOG(WARNING) << "No post-processors found for streams (key = "
                  << kOutputStreamsKey
                  << ").\n No stream-specific processing will occur.";
     return descriptors;
   }
   for (size_t i = 0; i < pipelines_list->GetSize(); ++i) {
-    base::DictionaryValue* pipeline_description_dict;
+    const base::DictionaryValue* pipeline_description_dict;
     CHECK(pipelines_list->GetDictionary(i, &pipeline_description_dict));
 
-    base::ListValue* processors_list;
+    const base::ListValue* processors_list;
     CHECK(pipeline_description_dict->GetList(kProcessorsKey, &processors_list));
 
-    base::ListValue* streams_list;
+    const base::ListValue* streams_list;
     CHECK(pipeline_description_dict->GetList(kStreamsKey, &streams_list));
     std::unordered_set<std::string> streams_set;
     for (size_t stream = 0; stream < streams_list->GetSize(); ++stream) {
@@ -94,27 +99,28 @@
 }
 
 std::string PostProcessingPipelineParser::GetFilePath() {
-  return kPostProcessingPipelineFilePath;
+  return kCastAudioConfigFilePath;
 }
 
-base::ListValue* PostProcessingPipelineParser::GetMixPipeline() {
+const base::ListValue* PostProcessingPipelineParser::GetMixPipeline() {
   return GetPipelineByKey(kMixPipelineKey);
 }
 
-base::ListValue* PostProcessingPipelineParser::GetLinearizePipeline() {
+const base::ListValue* PostProcessingPipelineParser::GetLinearizePipeline() {
   return GetPipelineByKey(kLinearizePipelineKey);
 }
 
-base::ListValue* PostProcessingPipelineParser::GetPipelineByKey(
+const base::ListValue* PostProcessingPipelineParser::GetPipelineByKey(
     const std::string& key) {
-  base::DictionaryValue* stream_dict;
-  if (!config_dict_ || !config_dict_->GetDictionary(key, &stream_dict)) {
+  const base::DictionaryValue* stream_dict;
+  if (!postprocessor_config_ ||
+      !postprocessor_config_->GetDictionary(key, &stream_dict)) {
     LOG(WARNING) << "No post-processor description found for \"" << key
-                 << "\" in " << kPostProcessingPipelineFilePath
+                 << "\" in " << kCastAudioConfigFilePath
                  << ". Using passthrough.";
     return nullptr;
   }
-  base::ListValue* out_list;
+  const base::ListValue* out_list;
   CHECK(stream_dict->GetList(kProcessorsKey, &out_list));
 
   return out_list;
diff --git a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h
index 97500aa..76f11bbf1 100644
--- a/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h
+++ b/chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h
@@ -28,11 +28,11 @@
   //   {"processor": "PATH_TO_SHARED_OBJECT",
   //    "config": "CONFIGURATION_STRING"},
   //    ... ]
-  base::ListValue* pipeline;
+  const base::ListValue* pipeline;
   std::unordered_set<std::string> stream_types;
 
   StreamPipelineDescriptor(
-      base::ListValue* pipeline_in,
+      const base::ListValue* pipeline_in,
       const std::unordered_set<std::string>& stream_types_in);
   ~StreamPipelineDescriptor();
   StreamPipelineDescriptor(const StreamPipelineDescriptor& other);
@@ -52,15 +52,16 @@
 
   // Gets the list of processors for the mix/linearize stages.
   // Same format as StreamPipelineDescriptor.pipeline
-  base::ListValue* GetMixPipeline();
-  base::ListValue* GetLinearizePipeline();
+  const base::ListValue* GetMixPipeline();
+  const base::ListValue* GetLinearizePipeline();
 
   static std::string GetFilePath();
 
  private:
-  base::ListValue* GetPipelineByKey(const std::string& key);
+  const base::ListValue* GetPipelineByKey(const std::string& key);
 
   std::unique_ptr<base::DictionaryValue> config_dict_;
+  const base::DictionaryValue* postprocessor_config_;
 
   DISALLOW_COPY_AND_ASSIGN(PostProcessingPipelineParser);
 };
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor.cc b/chromecast/media/cma/backend/alsa/post_processors/governor.cc
index 19ab8c78..83299966 100644
--- a/chromecast/media/cma/backend/alsa/post_processors/governor.cc
+++ b/chromecast/media/cma/backend/alsa/post_processors/governor.cc
@@ -34,7 +34,6 @@
   CHECK(config_dict) << "Governor config is not valid json: " << config;
   CHECK(config_dict->GetDouble(kOnsetVolumeKey, &onset_volume_));
   CHECK(config_dict->GetDouble(kClampMultiplierKey, &clamp_multiplier_));
-  DCHECK_EQ(channels_, 2);
   slew_volume_.SetVolume(1.0);
   LOG(INFO) << "Created a governor: onset_volume = " << onset_volume_
             << ", clamp_multiplier = " << clamp_multiplier_;
@@ -48,21 +47,13 @@
   return true;
 }
 
-int Governor::ProcessFrames(const std::vector<float*>& data,
-                            int frames,
-                            float volume) {
-  DCHECK_EQ(data.size(), static_cast<size_t>(channels_));
-
+int Governor::ProcessFrames(float* data, int frames, float volume) {
   if (volume != volume_) {
     volume_ = volume;
     slew_volume_.SetVolume(GetGovernorMultiplier());
   }
 
-  for (int c = 0; c < channels_; ++c) {
-    DCHECK(data[c]);
-    slew_volume_.ProcessFMUL(c != 0 /* repeat_transition */, data[c], frames,
-                             data[c]);
-  }
+  slew_volume_.ProcessFMUL(false, data, frames, channels_, data);
 
   return 0;  // No delay in this pipeline.
 }
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor.h b/chromecast/media/cma/backend/alsa/post_processors/governor.h
index 8607a22..26741567 100644
--- a/chromecast/media/cma/backend/alsa/post_processors/governor.h
+++ b/chromecast/media/cma/backend/alsa/post_processors/governor.h
@@ -29,9 +29,7 @@
 
   // AudioPostProcessor implementation:
   bool SetSampleRate(int sample_rate) override;
-  int ProcessFrames(const std::vector<float*>& data,
-                    int frames,
-                    float volume) override;
+  int ProcessFrames(float* data, int frames, float volume) override;
   int GetRingingTimeInFrames() override;
 
   void SetSlewTimeMsForTest(int slew_time_ms);
diff --git a/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc b/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc
index 30598cc6..201573b 100644
--- a/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc
+++ b/chromecast/media/cma/backend/alsa/post_processors/governor_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/stringprintf.h"
 #include "chromecast/media/cma/backend/alsa/post_processors/governor.h"
 #include "media/base/audio_bus.h"
+#include "media/base/audio_sample_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromecast {
@@ -48,31 +49,18 @@
   return data;
 }
 
-std::vector<float*> GetDataChannels(::media::AudioBus* audio) {
-  std::vector<float*> data(kNumChannels);
-  for (int i = 0; i < kNumChannels; ++i) {
-    data[i] = audio->channel(i);
-  }
-  return data;
-}
-
-void ScaleData(const std::vector<float*>& data, int frames, float scale) {
-  for (size_t ch = 0; ch < data.size(); ++ch) {
-    for (int f = 0; f < frames; ++f) {
-      data[ch][f] *= scale;
-    }
+void ScaleData(float* data, int frames, float scale) {
+  for (int f = 0; f < frames; ++f) {
+    data[f] *= scale;
   }
 }
 
-void CompareData(const std::vector<float*>& expected,
-                 const std::vector<float*>& actual,
+void CompareData(const std::vector<float>& expected,
+                 const std::vector<float>& actual,
                  int frames) {
   ASSERT_EQ(expected.size(), actual.size());
-  for (size_t ch = 0; ch < expected.size(); ++ch) {
-    for (int f = 0; f < frames; ++f) {
-      EXPECT_FLOAT_EQ(expected[ch][f], actual[ch][f])
-          << "ch: " << ch << " f: " << f;
-    }
+  for (int f = 0; f < frames; ++f) {
+    EXPECT_FLOAT_EQ(expected[f], actual[f]) << "f: " << f;
   }
 }
 
@@ -90,25 +78,29 @@
     governor_->SetSlewTimeMsForTest(0);
     governor_->SetSampleRate(kSampleRate);
 
-    data_bus_ = GetSineData(kNumFrames, kFrequency);
-    expected_bus_ = GetSineData(kNumFrames, kFrequency);
-    data_ = GetDataChannels(data_bus_.get());
-    expected_ = GetDataChannels(expected_bus_.get());
+    auto data_bus = GetSineData(kNumFrames, kFrequency);
+    auto expected_bus = GetSineData(kNumFrames, kFrequency);
+    data_.resize(kNumFrames * kNumChannels);
+    expected_.resize(kNumFrames * kNumChannels);
+    data_bus->ToInterleaved<::media::FloatSampleTypeTraits<float>>(
+        kNumFrames, data_.data());
+    expected_bus->ToInterleaved<::media::FloatSampleTypeTraits<float>>(
+        kNumFrames, expected_.data());
   }
 
-  void CompareBuffers() { CompareData(expected_, data_, kNumFrames); }
+  void CompareBuffers() {
+    CompareData(expected_, data_, kNumFrames * kNumChannels);
+  }
 
   void ProcessFrames(float volume) {
-    EXPECT_EQ(governor_->ProcessFrames(data_, kNumFrames, volume), 0);
+    EXPECT_EQ(governor_->ProcessFrames(data_.data(), kNumFrames, volume), 0);
   }
 
   float clamp_;
   float onset_volume_;
   std::unique_ptr<Governor> governor_;
-  std::unique_ptr<::media::AudioBus> data_bus_;
-  std::unique_ptr<::media::AudioBus> expected_bus_;
-  std::vector<float*> data_;
-  std::vector<float*> expected_;
+  std::vector<float> data_;
+  std::vector<float> expected_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(GovernorTest);
@@ -117,7 +109,7 @@
 TEST_P(GovernorTest, ZeroVolume) {
   ProcessFrames(0.0f);
   if (onset_volume_ <= 0.0f) {
-    ScaleData(expected_, kNumFrames, clamp_);
+    ScaleData(expected_.data(), kNumFrames * kNumChannels, clamp_);
   }
   CompareBuffers();
 }
@@ -131,14 +123,14 @@
 TEST_P(GovernorTest, EpsilonAboveOnset) {
   float volume = onset_volume_ + std::numeric_limits<float>::epsilon();
   ProcessFrames(volume);
-  ScaleData(expected_, kNumFrames, clamp_);
+  ScaleData(expected_.data(), kNumFrames * kNumChannels, clamp_);
   CompareBuffers();
 }
 
 TEST_P(GovernorTest, MaxVolume) {
   ProcessFrames(1.0);
   if (onset_volume_ <= 1.0) {
-    ScaleData(expected_, kNumFrames, clamp_);
+    ScaleData(expected_.data(), kNumFrames * kNumChannels, clamp_);
   }
   CompareBuffers();
 }
diff --git a/chromecast/media/cma/backend/alsa/slew_volume.cc b/chromecast/media/cma/backend/alsa/slew_volume.cc
index 6dd29c5..25b67bbe50 100644
--- a/chromecast/media/cma/backend/alsa/slew_volume.cc
+++ b/chromecast/media/cma/backend/alsa/slew_volume.cc
@@ -107,21 +107,24 @@
 void SlewVolume::ProcessFMAC(bool repeat_transition,
                              const float* src,
                              int frames,
+                             int channels,
                              float* dest) {
-  ProcessData<FMACTraits>(repeat_transition, src, frames, dest);
+  ProcessData<FMACTraits>(repeat_transition, src, frames, channels, dest);
 }
 
 void SlewVolume::ProcessFMUL(bool repeat_transition,
                              const float* src,
                              int frames,
+                             int channels,
                              float* dest) {
-  ProcessData<FMULTraits>(repeat_transition, src, frames, dest);
+  ProcessData<FMULTraits>(repeat_transition, src, frames, channels, dest);
 }
 
 template <typename Traits>
 void SlewVolume::ProcessData(bool repeat_transition,
                              const float* src,
                              int frames,
+                             int channels,
                              float* dest) {
   DCHECK(src);
   DCHECK(dest);
@@ -144,31 +147,35 @@
 
   if (current_volume_ == volume_scale_) {
     if (current_volume_ == 0.0) {
-      Traits::ProcessZeroVolume(src, frames, dest);
+      Traits::ProcessZeroVolume(src, frames * channels, dest);
       return;
     }
     if (current_volume_ == 1.0) {
-      Traits::ProcessUnityVolume(src, frames, dest);
+      Traits::ProcessUnityVolume(src, frames * channels, dest);
       return;
     }
-    Traits::ProcessBulkData(src, current_volume_, frames, dest);
+    Traits::ProcessBulkData(src, current_volume_, frames * channels, dest);
     return;
   }
 
   if (current_volume_ < volume_scale_) {
     do {
-      Traits::ProcessSingleDatum(src, current_volume_, dest);
-      ++src;
-      ++dest;
+      for (int i = 0; i < channels; ++i) {
+        Traits::ProcessSingleDatum(src, current_volume_, dest);
+        ++src;
+        ++dest;
+      }
       --frames;
       current_volume_ += max_slew_per_sample_;
     } while (current_volume_ < volume_scale_ && frames);
     current_volume_ = std::min(current_volume_, volume_scale_);
   } else {  // current_volume_ > volume_scale_
     do {
-      Traits::ProcessSingleDatum(src, current_volume_, dest);
-      ++src;
-      ++dest;
+      for (int i = 0; i < channels; ++i) {
+        Traits::ProcessSingleDatum(src, current_volume_, dest);
+        ++src;
+        ++dest;
+      }
       --frames;
       current_volume_ -= max_slew_per_sample_;
     } while (current_volume_ > volume_scale_ && frames);
@@ -176,15 +183,17 @@
   }
   while (frames && (reinterpret_cast<uintptr_t>(src) &
                     (::media::vector_math::kRequiredAlignment - 1))) {
-    Traits::ProcessSingleDatum(src, current_volume_, dest);
-    ++src;
-    ++dest;
+    for (int i = 0; i < channels; ++i) {
+      Traits::ProcessSingleDatum(src, current_volume_, dest);
+      ++src;
+      ++dest;
+    }
     --frames;
   }
   if (!frames) {
     return;
   }
-  Traits::ProcessBulkData(src, current_volume_, frames, dest);
+  Traits::ProcessBulkData(src, current_volume_, frames * channels, dest);
 }
 
 }  // namespace media
diff --git a/chromecast/media/cma/backend/alsa/slew_volume.h b/chromecast/media/cma/backend/alsa/slew_volume.h
index 81152d2..88a1abb 100644
--- a/chromecast/media/cma/backend/alsa/slew_volume.h
+++ b/chromecast/media/cma/backend/alsa/slew_volume.h
@@ -28,23 +28,32 @@
   // applied immediately.
   void Interrupted();
 
-  // Assumes 1 channel float data that is 16-byte aligned. Smoothly calculates
-  // dest[i] += src[i] * volume_scaling
-  // ProcessFMAC will be called once for each channel of audio present and
-  // |repeat_transition| will be true for channels 2 through n.
+  // Smoothly calculates dest[i] += src[i] * |volume_scale|.
+  // |volume_scale| will always be consistent across a frame.
+  // |src| and |dest| are interleaved buffers with |channels| channels and at
+  // least |frames| frames (|channels| * |frames| total size).
+  // |src| and |dest| may be the same.
+  // |src| and |dest| must be 16-byte aligned.
+  // If using planar data, |repeat_transition| should be true for channels 2
+  // through n, which will cause the slewing process to be repeated.
   void ProcessFMAC(bool repeat_transition,
                    const float* src,
                    int frames,
+                   int channels,
                    float* dest);
 
-  // Processes a single channel of float data
-  // dest[i] = src[i] * volume_scaling.
-  // ProcessFMUL will be called once for each channel of audio present.
-  // |repeat_transition| should be true for channels 2 through n.
-  // Assumes 2 channels.
+  // Smoothly calculates dest[i] = src[i] * |volume_scale|.
+  // |volume_scale| will always be consistent across a frame.
+  // |src| and |dest| are interleaved buffers with |channels| channels and at
+  // least |frames| frames (|channels| * |frames| total size).
+  // |src| and |dest| may be the same.
+  // |src| and |dest| must be 16-byte aligned.
+  // If using planar data, |repeat_transition| should be true for channels 2
+  // through n, which will cause the slewing process to be repeated.
   void ProcessFMUL(bool repeat_transition,
                    const float* src,
                    int frames,
+                   int channels,
                    float* dest);
 
  private:
@@ -52,6 +61,7 @@
   void ProcessData(bool repeat_transition,
                    const float* src,
                    int frames,
+                   int channels,
                    float* dest);
 
   double sample_rate_;
diff --git a/chromecast/media/cma/backend/alsa/slew_volume_unittests.cc b/chromecast/media/cma/backend/alsa/slew_volume_unittests.cc
index 38bf6b7..e82379f 100644
--- a/chromecast/media/cma/backend/alsa/slew_volume_unittests.cc
+++ b/chromecast/media/cma/backend/alsa/slew_volume_unittests.cc
@@ -25,7 +25,7 @@
 const float kSinFrequency = 1.0f / kNumFrames;
 const int kBytesPerSample = sizeof(int32_t);
 
-// Frequency is in frames (frequency = frequency_in_hz / sample rate)
+// Frequency is in frames (frequency = frequency_in_hz / sample rate).
 std::unique_ptr<::media::AudioBus> GetSineData(size_t frames, float frequency) {
   auto data = ::media::AudioBus::Create(kNumChannels, frames);
   std::vector<int32_t> sine(frames * 2);
@@ -113,7 +113,7 @@
 
   void ClearInterrupted() {
     float throwaway __attribute__((__aligned__(16))) = 0.0f;
-    slew_volume_->ProcessFMUL(false, &throwaway, 1, &throwaway);
+    slew_volume_->ProcessFMUL(false, &throwaway, 1, 1, &throwaway);
   }
 
   int num_frames_;
@@ -156,9 +156,9 @@
   slew_volume_->SetVolume(1.0f);
 
   slew_volume_->ProcessFMUL(false /* repeat transition */, data_[0],
-                            num_frames_, data_[0]);
+                            num_frames_, 1, data_[0]);
   slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1], num_frames_,
-                            data_[1]);
+                            1, data_[1]);
   CompareBuffers();
 }
 
@@ -166,18 +166,17 @@
   slew_volume_->SetVolume(1.0f);
 
   slew_volume_->ProcessFMUL(false /* repeat transition */, data_2_[0],
-                            num_frames_, data_[0]);
+                            num_frames_, 1, data_[0]);
   slew_volume_->ProcessFMUL(true /* repeat transition */, data_2_[1],
-                            num_frames_, data_[1]);
+                            num_frames_, 1, data_[1]);
   CompareDataPartial(data_2_, data_, 0, num_frames_);
 }
 
 TEST_F(SlewVolumeSteadyStateTest, FMULZero) {
   slew_volume_->SetVolume(0.0f);
   slew_volume_->ProcessFMUL(false, /* repeat transition */
-                            data_[0], num_frames_, data_[0]);
-  slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1], num_frames_,
-                            data_[1]);
+                            data_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, 1, data_[1]);
 
   for (size_t ch = 0; ch < data_.size(); ++ch) {
     for (int f = 0; f < num_frames_; ++f) {
@@ -190,23 +189,16 @@
   float volume = 0.6f;
   slew_volume_->SetVolume(volume);
 
-  slew_volume_->ProcessFMUL(false /* repeat transition */,
-                            data_[0] /* source */, num_frames_,
-                            data_[0] /* dst */);
-  slew_volume_->ProcessFMUL(true /* repeat transition */, data_[1] /* source */,
-                            num_frames_, data_[1] /* dst */);
+  slew_volume_->ProcessFMUL(false, data_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, 1, data_[1]);
   ScaleData(expected_, num_frames_, volume);
   CompareBuffers();
 }
 
 TEST_F(SlewVolumeSteadyStateTest, FMACNoOp) {
   slew_volume_->SetVolume(0.0f);
-  slew_volume_->ProcessFMAC(false /* repeat transition */,
-                            data_2_[0] /* source */, num_frames_,
-                            data_[0] /* dst */);
-  slew_volume_->ProcessFMAC(false /* repeat transition */,
-                            data_2_[1] /* source */, num_frames_,
-                            data_[1] /*dst */);
+  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMAC(false, data_2_[1], num_frames_, 1, data_[1]);
   CompareBuffers();
 }
 
@@ -219,47 +211,86 @@
 
   void SetUp() override {
     SlewVolumeBaseTest::SetUp();
+    channels_ = 2;
     sample_rate_ = std::get<0>(GetParam());
     slew_time_ms_ = std::get<1>(GetParam());
     slew_time_frames_ = sample_rate_ * slew_time_ms_ / 1000;
     slew_volume_->SetSampleRate(sample_rate_);
     slew_volume_->SetMaxSlewTimeMs(slew_time_ms_);
-
-    int num_frames = slew_time_frames_ + 2;  // +2 frames for numeric errors.
+    // +2 frames for numeric errors.
+    int num_frames = slew_time_frames_ + 2;
+    max_frame_ = num_frames - 1;
     ASSERT_GE(num_frames, 1);
     MakeData(num_frames);
   }
 
-  // Checks data_ = slew_volume_(expected_)
+  // Checks data_ = slew_volume_(expected_).
   void CheckSlewMUL(double start_vol, double end_vol) {
     for (size_t ch = 0; ch < data_.size(); ++ch) {
       // First value should have original scaling applied.
-      EXPECT_FLOAT_EQ(expected_[ch][0] * start_vol, data_[ch][0]) << ch;
-
-      // Steady state have final scaling applied
-      int f = num_frames_ - 1;
-      EXPECT_FLOAT_EQ(expected_[ch][f] * end_vol, data_[ch][f]) << ch;
+      EXPECT_FLOAT_EQ(Expected(ch, 0) * start_vol, Data(ch, 0)) << ch;
+      for (int f = 1; f < slew_time_frames_; ++f) {
+        // Can't calculate gain if input is 0.
+        if (Expected(ch, f) == 0.0)
+          continue;
+        double actual_gain = Data(ch, f) / Expected(ch, f);
+        // Interpolate to get expected gain.
+        double frame_gain_change = (end_vol - start_vol) / (slew_time_frames_);
+        double expected_gain = frame_gain_change * f + start_vol;
+        EXPECT_LE(std::abs(actual_gain - expected_gain),
+                  std::abs(frame_gain_change))
+            << ch << " " << f;
+      }
+      // Steady state should have final scaling applied.
+      int f = max_frame_;
+      EXPECT_FLOAT_EQ(Expected(ch, f) * end_vol, Data(ch, f))
+          << ch << " " << f
+          << " Actual gain = " << Data(ch, f) / Expected(ch, f);
     }
   }
 
-  // Checks data_ = expected_ + slew_volume_(data_2_)
+  // Checks data_ = expected_ + slew_volume_(data_2_).
   void CheckSlewMAC(double start_vol, double end_vol) {
-    for (size_t ch = 0; ch < data_.size(); ++ch) {
+    for (int ch = 0; ch < channels_; ++ch) {
       // First value should have original scaling applied.
-      EXPECT_FLOAT_EQ(expected_[ch][0] + data_2_[ch][0] * start_vol,
-                      data_[ch][0])
+      EXPECT_FLOAT_EQ(Expected(ch, 0) + Data2(ch, 0) * start_vol, Data(ch, 0))
           << ch;
-
-      // Steady state have final scaling applied
-      int f = num_frames_ - 1;
-      EXPECT_FLOAT_EQ(expected_[ch][f] + data_2_[ch][f] * end_vol, data_[ch][f])
-          << ch << " " << f;
+      for (int f = 1; f < slew_time_frames_; ++f) {
+        // Can't calculate gain if input is 0.
+        if (Data2(ch, f) == 0.0)
+          continue;
+        double actual_gain = (Data(ch, f) - Expected(ch, f)) / Data2(ch, f);
+        // Interpolate to get expected gain.
+        double frame_gain_change = (end_vol - start_vol) / (slew_time_frames_);
+        double expected_gain = frame_gain_change * f + start_vol;
+        EXPECT_LE(std::abs(actual_gain - expected_gain),
+                  std::abs(frame_gain_change))
+            << f;
+      }
+      // Steady state should have final gain applied.
+      int f = max_frame_;
+      EXPECT_FLOAT_EQ(Expected(ch, f) + Data2(ch, f) * end_vol, Data(ch, f))
+          << ch << " " << f << " Actual gain = "
+          << (Data(ch, f) - Expected(ch, f)) / Data2(ch, f);
     }
   }
 
+  // Data accessors. Override to change access method of CheckSlewM[AC/UL].
+  virtual float Data(int channel, int frame) { return data_[channel][frame]; }
+
+  virtual float Data2(int channel, int frame) {
+    return data_2_[channel][frame];
+  }
+
+  virtual float Expected(int channel, int frame) {
+    return expected_[channel][frame];
+  }
+
   int sample_rate_;
   int slew_time_ms_;
   int slew_time_frames_;
+  int channels_;
+  int max_frame_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SlewVolumeDynamicTest);
@@ -272,8 +303,8 @@
   ClearInterrupted();
 
   slew_volume_->SetVolume(end);
-  slew_volume_->ProcessFMUL(false, data_[0], num_frames_, data_[0]);
-  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, data_[1]);
+  slew_volume_->ProcessFMUL(false, data_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, 1, data_[1]);
   CheckSlewMUL(start, end);
 }
 
@@ -284,8 +315,8 @@
   ClearInterrupted();
 
   slew_volume_->SetVolume(end);
-  slew_volume_->ProcessFMUL(false, data_[0], num_frames_, data_[0]);
-  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, data_[1]);
+  slew_volume_->ProcessFMUL(false, data_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMUL(true, data_[1], num_frames_, 1, data_[1]);
   CheckSlewMUL(start, end);
 }
 
@@ -304,9 +335,10 @@
     if (num_frames_ - f < frame_step * 2) {
       frame_step = num_frames_ - f;
     }
-    slew_volume_->ProcessFMUL(false, expected_[0] + f, frame_step,
+    slew_volume_->ProcessFMUL(false, expected_[0] + f, frame_step, 1,
                               data_[0] + f);
-    slew_volume_->ProcessFMUL(true, expected_[1] + f, frame_step, data_[1] + f);
+    slew_volume_->ProcessFMUL(true, expected_[1] + f, frame_step, 1,
+                              data_[1] + f);
   }
   ASSERT_EQ(num_frames_, f);
   CheckSlewMUL(start, end);
@@ -319,8 +351,8 @@
   ClearInterrupted();
 
   slew_volume_->SetVolume(end);
-  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, data_[0]);
-  slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, data_[1]);
+  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, 1, data_[1]);
   CheckSlewMAC(start, end);
 }
 
@@ -331,8 +363,8 @@
   ClearInterrupted();
 
   slew_volume_->SetVolume(end);
-  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, data_[0]);
-  slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, data_[1]);
+  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_, 1, data_[0]);
+  slew_volume_->ProcessFMAC(true, data_2_[1], num_frames_, 1, data_[1]);
   CheckSlewMAC(start, end);
 }
 
@@ -351,8 +383,10 @@
     if (num_frames_ - f < frame_step * 2) {
       frame_step = num_frames_ - f;
     }
-    slew_volume_->ProcessFMAC(false, data_2_[0] + f, frame_step, data_[0] + f);
-    slew_volume_->ProcessFMAC(true, data_2_[1] + f, frame_step, data_[1] + f);
+    slew_volume_->ProcessFMAC(false, data_2_[0] + f, frame_step, 1,
+                              data_[0] + f);
+    slew_volume_->ProcessFMAC(true, data_2_[1] + f, frame_step, 1,
+                              data_[1] + f);
   }
   ASSERT_EQ(num_frames_, f);
   CheckSlewMAC(start, end);
@@ -362,5 +396,96 @@
                         SlewVolumeDynamicTest,
                         ::testing::Combine(::testing::Values(44100, 48000),
                                            ::testing::Values(0, 15, 100)));
+
+class SlewVolumeInterleavedTest : public SlewVolumeDynamicTest {
+ protected:
+  SlewVolumeInterleavedTest() = default;
+  ~SlewVolumeInterleavedTest() override = default;
+
+  void SetUp() override {
+    slew_volume_ = base::MakeUnique<SlewVolume>();
+    slew_volume_->Interrupted();
+
+    channels_ = std::get<0>(GetParam());
+    sample_rate_ = 16000;
+    slew_time_ms_ = 20;
+    slew_time_frames_ = sample_rate_ * slew_time_ms_ / 1000;
+    slew_volume_->SetMaxSlewTimeMs(slew_time_ms_);
+    slew_volume_->SetSampleRate(sample_rate_);
+    num_frames_ = (2 + slew_time_frames_) * channels_;
+    max_frame_ = num_frames_ / channels_ - 1;
+    MakeData(num_frames_);
+  }
+
+  float Data(int channel, int frame) override {
+    return data_[0][channels_ * frame + channel];
+  }
+
+  float Data2(int channel, int frame) override {
+    return data_2_[0][channels_ * frame + channel];
+  }
+
+  float Expected(int channel, int frame) override {
+    return expected_[0][channels_ * frame + channel];
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SlewVolumeInterleavedTest);
+};
+
+TEST_P(SlewVolumeInterleavedTest, FMACRampDown) {
+  double start = 1.0;
+  double end = 0.0;
+  slew_volume_->SetVolume(start);
+  ClearInterrupted();
+
+  slew_volume_->SetVolume(end);
+  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_ / channels_,
+                            channels_, data_[0]);
+  CheckSlewMAC(start, end);
+}
+
+TEST_P(SlewVolumeInterleavedTest, FMACRampUp) {
+  double start = 0.0;
+  double end = 1.0;
+  slew_volume_->SetVolume(start);
+  ClearInterrupted();
+
+  slew_volume_->SetVolume(end);
+  slew_volume_->ProcessFMAC(false, data_2_[0], num_frames_ / channels_,
+                            channels_, data_[0]);
+  CheckSlewMAC(start, end);
+}
+
+TEST_P(SlewVolumeInterleavedTest, FMULRampDown) {
+  double start = 1.0;
+  double end = 0.0;
+  slew_volume_->SetVolume(start);
+  ClearInterrupted();
+
+  slew_volume_->SetVolume(end);
+  slew_volume_->ProcessFMUL(false, data_[0], num_frames_ / channels_, channels_,
+                            data_[0]);
+
+  CheckSlewMUL(start, end);
+}
+
+TEST_P(SlewVolumeInterleavedTest, FMULRampUp) {
+  double start = 0.0;
+  double end = 1.0;
+  slew_volume_->SetVolume(start);
+  ClearInterrupted();
+
+  slew_volume_->SetVolume(end);
+  slew_volume_->ProcessFMUL(false, data_[0], num_frames_ / channels_, channels_,
+                            data_[0]);
+  CheckSlewMUL(start, end);
+}
+
+INSTANTIATE_TEST_CASE_P(Interleaved,
+                        SlewVolumeInterleavedTest,
+                        ::testing::Combine(::testing::Values(2, 4),
+                                           ::testing::Values(0)));
+
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
index a8f67eeb..b75ceae 100644
--- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
+++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa.cc
@@ -28,6 +28,7 @@
 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/audio_bus.h"
+#include "media/base/audio_sample_types.h"
 #include "media/base/media_switches.h"
 
 #define RETURN_REPORT_ERROR(snd_func, ...)                        \
@@ -115,8 +116,8 @@
 
 // These sample formats will be tried in order. 32 bit samples is ideal, but
 // some devices do not support 32 bit samples.
-const snd_pcm_format_t kPreferredSampleFormats[] = {SND_PCM_FORMAT_S32,
-                                                    SND_PCM_FORMAT_S16};
+const snd_pcm_format_t kPreferredSampleFormats[] = {
+    SND_PCM_FORMAT_FLOAT, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_S16};
 
 const int64_t kNoTimestamp = std::numeric_limits<int64_t>::min();
 
@@ -149,6 +150,38 @@
 base::LazyInstance<StreamMixerAlsaInstance>::DestructorAtExit g_mixer_instance =
     LAZY_INSTANCE_INITIALIZER;
 
+template <class TargetSampleTypeTraits>
+void ToFixedPoint(const float* input,
+                  int frames,
+                  typename TargetSampleTypeTraits::ValueType* dest_buffer) {
+  for (int f = 0; f < frames; ++f) {
+    dest_buffer[f] = TargetSampleTypeTraits::FromFloat(input[f]);
+  }
+}
+
+void ToFixedPoint(const float* input,
+                  int frames,
+                  int bytes_per_sample,
+                  uint8_t* dest_buffer) {
+  switch (bytes_per_sample) {
+    case 1:
+      ToFixedPoint<::media::UnsignedInt8SampleTypeTraits>(
+          input, frames, reinterpret_cast<uint8_t*>(dest_buffer));
+      break;
+    case 2:
+      ToFixedPoint<::media::SignedInt16SampleTypeTraits>(
+          input, frames, reinterpret_cast<int16_t*>(dest_buffer));
+      break;
+    case 4:
+      ToFixedPoint<::media::SignedInt32SampleTypeTraits>(
+          input, frames, reinterpret_cast<int32_t*>(dest_buffer));
+      break;
+    default:
+      NOTREACHED() << "Unsupported bytes per sample encountered: "
+                   << bytes_per_sample;
+  }
+}
+
 }  // namespace
 
 float StreamMixerAlsa::VolumeInfo::GetEffectiveVolume() {
@@ -531,20 +564,10 @@
   // b/24747205
   int err = SetAlsaPlaybackParams();
   if (err < 0) {
-    LOG(WARNING) << "32-bit playback is not supported on this device, falling "
-                 "back to 16-bit playback. This can degrade audio quality.";
-    pcm_format_ = SND_PCM_FORMAT_S16;
-    // Free pcm_hw_params_, which is re-allocated in SetAlsaPlaybackParams().
-    // See b/25572466.
-    alsa_->PcmHwParamsFree(pcm_hw_params_);
-    pcm_hw_params_ = nullptr;
-    int err = SetAlsaPlaybackParams();
-    if (err < 0) {
-      LOG(ERROR) << "Error setting ALSA playback parameters: "
-                 << alsa_->StrError(err);
-      SignalError();
-      return;
-    }
+    LOG(ERROR) << "Error setting ALSA playback parameters: "
+               << alsa_->StrError(err);
+    SignalError();
+    return;
   }
 
   // Initialize filters
@@ -885,13 +908,6 @@
   // Resize interleaved if necessary.
   size_t interleaved_size = static_cast<size_t>(frames) * kNumOutputChannels *
                             BytesPerOutputFormatSample();
-  if (interleaved_.size() < interleaved_size) {
-    interleaved_.resize(interleaved_size);
-  }
-
-  // Get data for loopback.
-  mix_filter_->data()->ToInterleaved(frames, BytesPerOutputFormatSample(),
-                                     interleaved_.data());
 
   int64_t expected_playback_time;
   if (alsa_rendering_delay_.timestamp_microseconds == kNoTimestamp) {
@@ -902,15 +918,36 @@
                              linearize_filter_->GetRenderingDelayMicroseconds();
   }
 
-  for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
-    observer->OnLoopbackAudio(expected_playback_time, kSampleFormatS32,
-                              output_samples_per_second_, kNumOutputChannels,
-                              interleaved_.data(), InterleavedSize(frames));
+  // Hard limit to [1.0, -1.0]
+  for (int i = 0; i < frames * kNumOutputChannels; ++i) {
+    mix_filter_->interleaved()[i] =
+        std::min(1.0f, std::max(-1.0f, mix_filter_->interleaved()[i]));
   }
 
-  // Get data for playout.
-  linearize_filter_->data()->ToInterleaved(frames, BytesPerOutputFormatSample(),
-                                           interleaved_.data());
+  for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
+    observer->OnLoopbackAudio(
+        expected_playback_time, kSampleFormatF32, output_samples_per_second_,
+        kNumOutputChannels,
+        reinterpret_cast<uint8_t*>(mix_filter_->interleaved()),
+        InterleavedSize(frames));
+  }
+
+  uint8_t* data;
+  if (pcm_format_ == SND_PCM_FORMAT_FLOAT) {
+    // Hard limit to [1.0, -1.0]. ToFixedPoint handles this for other cases.
+    for (int i = 0; i < frames * kNumOutputChannels; ++i) {
+      linearize_filter_->interleaved()[i] =
+          std::min(1.0f, std::max(-1.0f, linearize_filter_->interleaved()[i]));
+    }
+    data = reinterpret_cast<uint8_t*>(linearize_filter_->interleaved());
+  } else {
+    if (interleaved_.size() < interleaved_size) {
+      interleaved_.resize(interleaved_size);
+    }
+    ToFixedPoint(linearize_filter_->interleaved(), frames * kNumOutputChannels,
+                 BytesPerOutputFormatSample(), interleaved_.data());
+    data = interleaved_.data();
+  }
 
   // If the PCM has been drained it will be in SND_PCM_STATE_SETUP and need
   // to be prepared in order for playback to work.
@@ -919,7 +956,6 @@
   }
 
   int frames_left = frames;
-  uint8_t* data = interleaved_.data();
   while (frames_left) {
     int frames_or_error;
     while ((frames_or_error = alsa_->PcmWritei(pcm_, data, frames_left)) < 0) {
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc
index 2172c4d..62652bff 100644
--- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc
+++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_input_impl.cc
@@ -596,7 +596,7 @@
                                                      const float* src,
                                                      int frames,
                                                      float* dest) {
-  slew_volume_.ProcessFMAC(repeat_transition, src, frames, dest);
+  slew_volume_.ProcessFMAC(repeat_transition, src, frames, 1, dest);
 }
 
 }  // namespace media
diff --git a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_unittest.cc b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_unittest.cc
index 2bc5314..f60759fa 100644
--- a/chromecast/media/cma/backend/alsa/stream_mixer_alsa_unittest.cc
+++ b/chromecast/media/cma/backend/alsa/stream_mixer_alsa_unittest.cc
@@ -21,6 +21,7 @@
 #include "chromecast/media/cma/backend/alsa/post_processing_pipeline.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/audio_bus.h"
+#include "media/base/audio_sample_types.h"
 #include "media/base/vector_math.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,6 +33,8 @@
 
 namespace {
 
+using FloatType = ::media::Float32SampleTypeTraits;
+
 // Testing constants that are common to multiple test cases.
 const size_t kBytesPerSample = sizeof(int32_t);
 const int kNumChannels = 2;
@@ -133,33 +136,35 @@
 const int kNumPostProcessors = 5;
 const char kTestPipelineJsonTemplate[] = R"json(
 {
-  "output_streams": [{
-    "streams": [ "default" ],
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": %d }
-    }]
-  }, {
-    "streams": [ "assistant-tts" ],
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": %d }
-    }]
-  }, {
-    "streams": [ "communications" ],
-    "processors": []
-  }],
-  "mix": {
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": %d }
-     }]
-  },
-  "linearize": {
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": %d }
-    }]
+  "postprocessors": {
+    "output_streams": [{
+      "streams": [ "default" ],
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": %d }
+      }]
+    }, {
+      "streams": [ "assistant-tts" ],
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": %d }
+      }]
+    }, {
+      "streams": [ "communications" ],
+      "processors": []
+    }],
+    "mix": {
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": %d }
+       }]
+    },
+    "linearize": {
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": %d }
+      }]
+    }
   }
 }
 )json";
@@ -326,11 +331,9 @@
             testing::Invoke(this, &MockPostProcessor::DoProcessFrames));
   }
   ~MockPostProcessor() override { instances_.erase(name_); }
-  MOCK_METHOD4(ProcessFrames,
-               int(const std::vector<float*>& data,
-                   int num_frames,
-                   float current_volume,
-                   bool is_silence));
+  MOCK_METHOD4(
+      ProcessFrames,
+      int(float* data, int num_frames, float current_volume, bool is_silence));
   bool SetSampleRate(int sample_rate) override { return false; }
   bool IsRinging() override { return ringing_; }
   int delay() { return rendering_delay_; }
@@ -341,7 +344,7 @@
   }
 
  private:
-  int DoProcessFrames(const std::vector<float*>& data,
+  int DoProcessFrames(float* data,
                       int num_frames,
                       float current_volume,
                       bool is_sience) {
@@ -402,6 +405,15 @@
       std::vector<testing::StrictMock<MockInputQueue>*>(1, input));
 }
 
+void ToPlanar(const uint8_t* interleaved,
+              int num_frames,
+              ::media::AudioBus* planar) {
+  ASSERT_GE(planar->frames(), num_frames);
+
+  planar->FromInterleaved<FloatType>(
+      reinterpret_cast<const float*>(interleaved), num_frames);
+}
+
 // Asserts that |expected| matches |actual| exactly.
 void CompareAudioData(const ::media::AudioBus& expected,
                       const ::media::AudioBus& actual) {
@@ -612,8 +624,7 @@
   // expected stream. The stream should match exactly.
   auto actual = ::media::AudioBus::Create(kNumChannels, kNumFrames);
   ASSERT_GT(mock_alsa()->data().size(), 0u);
-  actual->FromInterleaved(
-      &(mock_alsa()->data()[0]), kNumFrames, kBytesPerSample);
+  ToPlanar(&(mock_alsa()->data()[0]), kNumFrames, actual.get());
   CompareAudioData(input->data(), *actual);
 }
 
@@ -644,8 +655,7 @@
 
   // Check that the retrieved stream is scaled correctly.
   auto actual = ::media::AudioBus::Create(kNumChannels, kNumFrames);
-  actual->FromInterleaved(
-      &(mock_alsa()->data()[0]), kNumFrames, kBytesPerSample);
+  ToPlanar(&(mock_alsa()->data()[0]), kNumFrames, actual.get());
   auto expected = GetMixedAudioData(input);
   CompareAudioData(*expected, *actual);
 }
@@ -685,8 +695,7 @@
   // Get the actual stream rendered to ALSA, and compare it against the
   // expected stream. The stream should match exactly.
   auto actual = ::media::AudioBus::Create(kNumChannels, kNumFrames);
-  actual->FromInterleaved(&(mock_alsa()->data()[0]), kNumFrames,
-                          kBytesPerSample);
+  ToPlanar(&(mock_alsa()->data()[0]), kNumFrames, actual.get());
   CompareAudioData(*expected, *actual);
 }
 
@@ -727,8 +736,7 @@
   // Get the actual stream rendered to ALSA, and compare it against the
   // expected stream. The stream should match exactly.
   auto actual = ::media::AudioBus::Create(kNumChannels, kNumFrames);
-  actual->FromInterleaved(
-      &(mock_alsa()->data()[0]), kNumFrames, kBytesPerSample);
+  ToPlanar(&(mock_alsa()->data()[0]), kNumFrames, actual.get());
   CompareAudioData(*expected, *actual);
 }
 
@@ -802,8 +810,7 @@
   // Get the actual stream rendered to ALSA, and compare it against the
   // expected stream. The stream should match exactly.
   auto actual = ::media::AudioBus::Create(kNumChannels, kNumFrames);
-  actual->FromInterleaved(
-      &(mock_alsa()->data()[0]), kNumFrames, kBytesPerSample);
+  ToPlanar(&(mock_alsa()->data()[0]), kNumFrames, actual.get());
   CompareAudioData(*expected, *actual);
 }
 
@@ -1056,19 +1063,21 @@
 TEST_F(StreamMixerAlsaTest, PostProcessorRingingWithoutInput) {
   const char kTestPipelineJson[] = R"json(
 {
-  "output_streams": [{
-    "streams": [ "default" ],
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": 0, "ringing": true}
+  "postprocessors": {
+    "output_streams": [{
+      "streams": [ "default" ],
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": 0, "ringing": true}
+      }]
+    }, {
+      "streams": [ "assistant-tts" ],
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": 0, "ringing": true}
+      }]
     }]
-  }, {
-    "streams": [ "assistant-tts" ],
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": 0, "ringing": true}
-    }]
-  }]
+  }
 }
 )json";
 
@@ -1116,13 +1125,15 @@
 TEST_F(StreamMixerAlsaTest, InvalidStreamTypeCrashes) {
   const char json[] = R"json(
 {
-  "output_streams": [{
-    "streams": [ "foobar" ],
-    "processors": [{
-      "processor": "dont_care.so",
-      "config": { "delay": 0 }
+  "postprocessors": {
+    "output_streams": [{
+      "streams": [ "foobar" ],
+      "processors": [{
+        "processor": "dont_care.so",
+        "config": { "delay": 0 }
+      }]
     }]
-  }]
+  }
 }
 )json";
 
@@ -1139,24 +1150,26 @@
 TEST_F(StreamMixerAlsaTest, MultiplePostProcessorsInOneStream) {
   const char kJsonTemplate[] = R"json(
 {
-  "output_streams": [{
-    "streams": [ "default" ],
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": 10 }
-    }, {
-      "processor": "%s",
-      "config": { "delay": 100 }
-    }]
-  }],
-  "mix": {
-    "processors": [{
-      "processor": "%s",
-      "config": { "delay": 1000 }
-    }, {
-      "processor": "%s",
-      "config": { "delay": 10000 }
-    }]
+  "postprocessors": {
+    "output_streams": [{
+      "streams": [ "default" ],
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": 10 }
+      }, {
+        "processor": "%s",
+        "config": { "delay": 100 }
+      }]
+    }],
+    "mix": {
+      "processors": [{
+        "processor": "%s",
+        "config": { "delay": 1000 }
+      }, {
+        "processor": "%s",
+        "config": { "delay": 10000 }
+      }]
+    }
   }
 }
 )json";
diff --git a/chromecast/media/cma/backend/alsa/volume_control.cc b/chromecast/media/cma/backend/alsa/volume_control.cc
index 872b4f43..f030c54 100644
--- a/chromecast/media/cma/backend/alsa/volume_control.cc
+++ b/chromecast/media/cma/backend/alsa/volume_control.cc
@@ -21,6 +21,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
@@ -29,6 +30,7 @@
 #include "chromecast/base/serializers.h"
 #include "chromecast/media/cma/backend/alsa/alsa_features.h"
 #include "chromecast/media/cma/backend/alsa/alsa_volume_control.h"
+#include "chromecast/media/cma/backend/alsa/post_processing_pipeline_parser.h"
 #include "chromecast/media/cma/backend/alsa/stream_mixer_alsa.h"
 
 namespace chromecast {
@@ -36,26 +38,29 @@
 
 namespace {
 
-const float kDefaultMediaDbFS = -25.0f;
-const float kDefaultAlarmDbFS = -20.0f;
-const float kDefaultCommunicationDbFS = -25.0f;
+constexpr float kDefaultMediaDbFS = -25.0f;
+constexpr float kDefaultAlarmDbFS = -20.0f;
+constexpr float kDefaultCommunicationDbFS = -25.0f;
 
-const float kMinDbFS = -120.0f;
+constexpr float kMinDbFS = -120.0f;
 
-const char kKeyMediaDbFS[] = "dbfs.media";
-const char kKeyAlarmDbFS[] = "dbfs.alarm";
-const char kKeyCommunicationDbFS[] = "dbfs.communication";
+constexpr char kKeyMediaDbFS[] = "dbfs.media";
+constexpr char kKeyAlarmDbFS[] = "dbfs.alarm";
+constexpr char kKeyCommunicationDbFS[] = "dbfs.communication";
+constexpr char kKeyVolumeMap[] = "volume_map";
+constexpr char kKeyLevel[] = "level";
+constexpr char kKeyDb[] = "db";
 
 struct LevelToDb {
   float level;
   float db;
 };
 
-const LevelToDb kVolumeMap[] = {{0.0f, kMinDbFS},
-                                {0.01f, -58.0f},
-                                {0.090909f, -48.0f},
-                                {0.818182f, -8.0f},
-                                {1.0f, 0.0f}};
+const LevelToDb kDefaultVolumeMap[] = {{0.0f, kMinDbFS},
+                                       {0.01f, -58.0f},
+                                       {0.090909f, -48.0f},
+                                       {0.818182f, -8.0f},
+                                       {1.0f, 0.0f}};
 
 float DbFsToScale(float db) {
   if (db <= kMinDbFS) {
@@ -75,6 +80,105 @@
   }
 }
 
+class VolumeMap {
+ public:
+  VolumeMap() {
+    auto cast_audio_config = DeserializeJsonFromFile(
+        base::FilePath(PostProcessingPipelineParser::GetFilePath()));
+    const base::DictionaryValue* cast_audio_dict;
+    if (!cast_audio_config ||
+        !cast_audio_config->GetAsDictionary(&cast_audio_dict)) {
+      LOG(WARNING) << "No cast audio config found; using default volume map.";
+      volume_map_.insert(volume_map_.end(), kDefaultVolumeMap,
+                         kDefaultVolumeMap + arraysize(kDefaultVolumeMap));
+      return;
+    }
+
+    const base::ListValue* volume_map_list;
+    if (!cast_audio_dict->GetList(kKeyVolumeMap, &volume_map_list)) {
+      LOG(WARNING) << "No volume map found; using default volume map.";
+      volume_map_.insert(volume_map_.end(), kDefaultVolumeMap,
+                         kDefaultVolumeMap + arraysize(kDefaultVolumeMap));
+      return;
+    }
+
+    double prev_level = -1.0;
+    for (size_t i = 0; i < volume_map_list->GetSize(); ++i) {
+      const base::DictionaryValue* volume_map_entry;
+      CHECK(volume_map_list->GetDictionary(i, &volume_map_entry));
+
+      double level;
+      CHECK(volume_map_entry->GetDouble(kKeyLevel, &level));
+      CHECK_GE(level, 0.0);
+      CHECK_LE(level, 1.0);
+      CHECK_GT(level, prev_level);
+      prev_level = level;
+
+      double db;
+      CHECK(volume_map_entry->GetDouble(kKeyDb, &db));
+      CHECK_LE(db, 0.0);
+      if (level == 1.0) {
+        CHECK_EQ(db, 0.0);
+      }
+
+      volume_map_.push_back({level, db});
+    }
+
+    if (volume_map_.empty()) {
+      LOG(FATAL) << "No entries in volume map.";
+      return;
+    }
+
+    if (volume_map_[0].level > 0.0) {
+      volume_map_.insert(volume_map_.begin(), {0.0, kMinDbFS});
+    }
+
+    if (volume_map_.rbegin()->level < 1.0) {
+      volume_map_.push_back({1.0, 0.0});
+    }
+  }
+
+  float VolumeToDbFS(float volume) {
+    if (volume <= volume_map_[0].level) {
+      return volume_map_[0].db;
+    }
+    for (size_t i = 1; i < volume_map_.size(); ++i) {
+      if (volume < volume_map_[i].level) {
+        const float x_range = volume_map_[i].level - volume_map_[i - 1].level;
+        const float y_range = volume_map_[i].db - volume_map_[i - 1].db;
+        const float x_pos = volume - volume_map_[i - 1].level;
+
+        return volume_map_[i - 1].db + x_pos * y_range / x_range;
+      }
+    }
+    return volume_map_[volume_map_.size() - 1].db;
+  }
+
+  // static
+  float DbFSToVolume(float db) {
+    if (db <= volume_map_[0].db) {
+      return volume_map_[0].level;
+    }
+    for (size_t i = 1; i < volume_map_.size(); ++i) {
+      if (db < volume_map_[i].db) {
+        const float x_range = volume_map_[i].db - volume_map_[i - 1].db;
+        const float y_range = volume_map_[i].level - volume_map_[i - 1].level;
+        const float x_pos = db - volume_map_[i - 1].db;
+
+        return volume_map_[i - 1].level + x_pos * y_range / x_range;
+      }
+    }
+    return volume_map_[volume_map_.size() - 1].level;
+  }
+
+ private:
+  std::vector<LevelToDb> volume_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(VolumeMap);
+};
+
+base::LazyInstance<VolumeMap>::Leaky g_volume_map = LAZY_INSTANCE_INITIALIZER;
+
 class VolumeControlInternal : public AlsaVolumeControl::Delegate {
  public:
   VolumeControlInternal()
@@ -82,6 +186,9 @@
         initialize_complete_event_(
             base::WaitableEvent::ResetPolicy::MANUAL,
             base::WaitableEvent::InitialState::NOT_SIGNALED) {
+    // Load volume map to check that the config file is correct.
+    g_volume_map.Get();
+
     stored_values_.SetDouble(kKeyMediaDbFS, kDefaultMediaDbFS);
     stored_values_.SetDouble(kKeyAlarmDbFS, kDefaultAlarmDbFS);
     stored_values_.SetDouble(kKeyCommunicationDbFS, kDefaultCommunicationDbFS);
@@ -335,36 +442,12 @@
 
 // static
 float VolumeControl::VolumeToDbFS(float volume) {
-  if (volume <= kVolumeMap[0].level) {
-    return kVolumeMap[0].db;
-  }
-  for (size_t i = 1; i < arraysize(kVolumeMap); ++i) {
-    if (volume < kVolumeMap[i].level) {
-      const float x_diff = kVolumeMap[i].level - kVolumeMap[i - 1].level;
-      const float y_diff = kVolumeMap[i].db - kVolumeMap[i - 1].db;
-
-      return kVolumeMap[i - 1].db +
-             (volume - kVolumeMap[i - 1].level) * y_diff / x_diff;
-    }
-  }
-  return kVolumeMap[arraysize(kVolumeMap) - 1].db;
+  return g_volume_map.Get().VolumeToDbFS(volume);
 }
 
 // static
 float VolumeControl::DbFSToVolume(float db) {
-  if (db <= kVolumeMap[0].db) {
-    return kVolumeMap[0].level;
-  }
-  for (size_t i = 1; i < arraysize(kVolumeMap); ++i) {
-    if (db < kVolumeMap[i].db) {
-      const float x_diff = kVolumeMap[i].db - kVolumeMap[i - 1].db;
-      const float y_diff = kVolumeMap[i].level - kVolumeMap[i - 1].level;
-
-      return kVolumeMap[i - 1].level +
-             (db - kVolumeMap[i - 1].db) * y_diff / x_diff;
-    }
-  }
-  return kVolumeMap[arraysize(kVolumeMap) - 1].level;
+  return g_volume_map.Get().DbFSToVolume(db);
 }
 
 }  // namespace media
diff --git a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
index 4d335ce..2e643d1 100644
--- a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
+++ b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
index 0793744..5ca7ed5 100644
--- a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
+++ b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
index 23aaacc4..f8f18ea 100644
--- a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
+++ b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
index fad13bf..3b7ade2 100644
--- a/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
+++ b/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/chromecast/public/media/audio_post_processor_shlib.h b/chromecast/public/media/audio_post_processor_shlib.h
index 1326b7f..db66093 100644
--- a/chromecast/public/media/audio_post_processor_shlib.h
+++ b/chromecast/public/media/audio_post_processor_shlib.h
@@ -41,7 +41,7 @@
   virtual bool SetSampleRate(int sample_rate) = 0;
 
   // Processes audio frames from |data|, overwriting contents.
-  // |data| will always be 32-bit planar float.
+  // |data| will always be 32-bit interleaved float.
   // |frames| is the number of audio frames in data and is
   // always non-zero and less than or equal to 20ms of audio.
   // AudioPostProcessor must always provide |frames| frames of data back
@@ -51,9 +51,7 @@
   // Returns the current rendering delay of the filter in frames,
   // or negative if an error occurred during processing.
   // If an error occurred during processing, |data| should be unchanged.
-  virtual int ProcessFrames(const std::vector<float*>& data,
-                            int frames,
-                            float volume) = 0;
+  virtual int ProcessFrames(float* data, int frames, float volume) = 0;
 
   // Returns the number of frames of silence it will take for the
   // processor to come to rest.
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 95ce805..0f7624f 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -427,9 +427,12 @@
 // Interval at which we check for total time on OOBE.
 const char kOobeTimerInterval[] = "oobe-timer-interval";
 
-// If true, the md login and lock screens will be shown.
+// If true, the views-based md login and lock screens will be shown.
 const char kShowMdLogin[] = "show-md-login";
 
+// If true, the non-views-based md login and lock screens will be shown.
+const char kShowNonViewMdLogin[] = "show-non-view-md-login";
+
 // Specifies power stub behavior:
 //  'cycle=2' - Cycles power states every 2 seconds.
 // See FakeDBusThreadManager::ParsePowerCommandLineSwitch for full details.
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 1716cb9..805ee06 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -129,6 +129,7 @@
 CHROMEOS_EXPORT extern const char kOobeSkipPostLogin[];
 CHROMEOS_EXPORT extern const char kOobeTimerInterval[];
 CHROMEOS_EXPORT extern const char kShowMdLogin[];
+CHROMEOS_EXPORT extern const char kShowNonViewMdLogin[];
 CHROMEOS_EXPORT extern const char kPowerStub[];
 CHROMEOS_EXPORT extern const char kShillStub[];
 CHROMEOS_EXPORT extern const char kSmsTestMessages[];
diff --git a/chromeos/dbus/biod/biod_client_unittest.cc b/chromeos/dbus/biod/biod_client_unittest.cc
index b81c2ab..23f3383 100644
--- a/chromeos/dbus/biod/biod_client_unittest.cc
+++ b/chromeos/dbus/biod/biod_client_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "chromeos/dbus/biod/messages.pb.h"
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index fcb59a0..8bf9af5 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -8,6 +8,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/sys_info.h"
 #include "base/threading/thread.h"
 #include "chromeos/chromeos_switches.h"
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc
index c36266fd..19a1773 100644
--- a/chromeos/network/client_cert_resolver_unittest.cc
+++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_task_scheduler.h"
diff --git a/chromeos/network/host_resolver_impl_chromeos_unittest.cc b/chromeos/network/host_resolver_impl_chromeos_unittest.cc
index ca48394..9b200e7 100644
--- a/chromeos/network/host_resolver_impl_chromeos_unittest.cc
+++ b/chromeos/network/host_resolver_impl_chromeos_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
diff --git a/chromeos/network/network_cert_migrator_unittest.cc b/chromeos/network/network_cert_migrator_unittest.cc
index 8ea0d04..0f6f7c7e 100644
--- a/chromeos/network/network_cert_migrator_unittest.cc
+++ b/chromeos/network/network_cert_migrator_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_task_scheduler.h"
diff --git a/chromeos/process_proxy/process_output_watcher_unittest.cc b/chromeos/process_proxy/process_output_watcher_unittest.cc
index 107ce2d..73c566d 100644
--- a/chromeos/process_proxy/process_output_watcher_unittest.cc
+++ b/chromeos/process_proxy/process_output_watcher_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/callback.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/chromeos/process_proxy/process_proxy_registry.cc b/chromeos/process_proxy/process_proxy_registry.cc
index 2bd82df..fbc0442 100644
--- a/chromeos/process_proxy/process_proxy_registry.cc
+++ b/chromeos/process_proxy/process_proxy_registry.cc
@@ -5,6 +5,7 @@
 #include "chromeos/process_proxy/process_proxy_registry.h"
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 
 namespace chromeos {
 
diff --git a/chromeos/process_proxy/process_proxy_unittest.cc b/chromeos/process_proxy/process_proxy_unittest.cc
index 76e3c6d..45cae00 100644
--- a/chromeos/process_proxy/process_proxy_unittest.cc
+++ b/chromeos/process_proxy/process_proxy_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/kill.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
diff --git a/components/autofill/content/DEPS b/components/autofill/content/DEPS
index 97138c92..0baa569 100644
--- a/components/autofill/content/DEPS
+++ b/components/autofill/content/DEPS
@@ -1,8 +1,5 @@
 include_rules = [
   "+content/public/common",
-  # Allow inclusion of WebKit API files.
-  "+third_party/WebKit/public/platform",
-  "+third_party/WebKit/public/web",
   "+mojo/common",
   "+mojo/public",
   "+services/service_manager/public/cpp",
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS
index b9cba25..474cd74 100644
--- a/components/autofill/content/browser/DEPS
+++ b/components/autofill/content/browser/DEPS
@@ -8,6 +8,7 @@
   "+gpu/config/gpu_info.h",
   "+sql",
   "+third_party/libphonenumber",  # For phone number i18n.
+  "+third_party/WebKit/public/platform/WebRect.h",
 ]
 
 specific_include_rules = {
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom
index bb3be97..be4b139 100644
--- a/components/autofill/content/common/autofill_types.mojom
+++ b/components/autofill/content/common/autofill_types.mojom
@@ -60,6 +60,7 @@
     XHR_SUCCEEDED,
     FRAME_DETACHED,
     MANUAL_SAVE,
+    DOM_MUTATION_AFTER_XHR,
     SUBMISSION_INDICATOR_EVENT_COUNT
 };
 
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc
index 7a4b19a..52373e332 100644
--- a/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -261,6 +261,9 @@
       return mojom::PasswordFormSubmissionIndicatorEvent::FRAME_DETACHED;
     case PasswordForm::SubmissionIndicatorEvent::MANUAL_SAVE:
       return mojom::PasswordFormSubmissionIndicatorEvent::MANUAL_SAVE;
+    case PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR:
+      return mojom::PasswordFormSubmissionIndicatorEvent::
+          DOM_MUTATION_AFTER_XHR;
     case PasswordForm::SubmissionIndicatorEvent::
         SUBMISSION_INDICATOR_EVENT_COUNT:
       return mojom::PasswordFormSubmissionIndicatorEvent::
@@ -296,6 +299,9 @@
     case mojom::PasswordFormSubmissionIndicatorEvent::MANUAL_SAVE:
       *output = PasswordForm::SubmissionIndicatorEvent::MANUAL_SAVE;
       return true;
+    case mojom::PasswordFormSubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR:
+      *output = PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR;
+      return true;
     case mojom::PasswordFormSubmissionIndicatorEvent::
         SUBMISSION_INDICATOR_EVENT_COUNT:
       *output = PasswordForm::SubmissionIndicatorEvent::
diff --git a/components/autofill/content/renderer/DEPS b/components/autofill/content/renderer/DEPS
index 83ce085..e8db31c 100644
--- a/components/autofill/content/renderer/DEPS
+++ b/components/autofill/content/renderer/DEPS
@@ -2,6 +2,9 @@
   "+content/public/common",
   "+content/public/renderer",
   "+third_party/re2",
+  # Allow inclusion of WebKit API files.
+  "+third_party/WebKit/public/platform",
+  "+third_party/WebKit/public/web",
 ]
 
 specific_include_rules = {
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 23cdb1a1..e301934 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -48,6 +48,8 @@
 #include "third_party/WebKit/public/web/WebNode.h"
 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 #include "third_party/WebKit/public/web/WebView.h"
+#include "third_party/WebKit/public/web/modules/password_manager/WebFormElementObserver.h"
+#include "third_party/WebKit/public/web/modules/password_manager/WebFormElementObserverCallback.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "url/gurl.h"
@@ -618,6 +620,24 @@
 
 }  // namespace
 
+class PasswordAutofillAgent::FormElementObserverCallback
+    : public blink::WebFormElementObserverCallback {
+ public:
+  explicit FormElementObserverCallback(PasswordAutofillAgent* agent)
+      : agent_(agent) {}
+  ~FormElementObserverCallback() override = default;
+
+  void ElementWasHiddenOrRemoved() override {
+    agent_->OnSameDocumentNavigationCompleted(
+        PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
+  }
+
+ private:
+  PasswordAutofillAgent* agent_;
+
+  DISALLOW_COPY_AND_ASSIGN(FormElementObserverCallback);
+};
+
 ////////////////////////////////////////////////////////////////////////////////
 // PasswordAutofillAgent, public:
 
@@ -628,13 +648,18 @@
       was_password_autofilled_(false),
       sent_request_to_store_(false),
       checked_safe_browsing_reputation_(false),
-      binding_(this) {
+      binding_(this),
+      form_element_observer_(nullptr) {
   // PasswordAutofillAgent is guaranteed to outlive |render_frame|.
   render_frame->GetInterfaceRegistry()->AddInterface(
       base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
 }
 
 PasswordAutofillAgent::~PasswordAutofillAgent() {
+  if (form_element_observer_) {
+    form_element_observer_->Disconnect();
+    form_element_observer_ = nullptr;
+  }
 }
 
 void PasswordAutofillAgent::BindRequest(
@@ -1032,37 +1057,50 @@
 }
 
 void PasswordAutofillAgent::AJAXSucceeded() {
-  OnSameDocumentNavigationCompleted(false);
+  OnSameDocumentNavigationCompleted(
+      PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
 }
 
 void PasswordAutofillAgent::OnSameDocumentNavigationCompleted(
-    bool is_inpage_navigation) {
+    PasswordForm::SubmissionIndicatorEvent event) {
   if (!provisionally_saved_form_.IsPasswordValid())
     return;
 
-  provisionally_saved_form_.SetSubmissionIndicatorEvent(
-      is_inpage_navigation
-          ? PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION
-          : PasswordForm::SubmissionIndicatorEvent::XHR_SUCCEEDED);
-
   // Prompt to save only if the form is now gone, either invisible or
   // removed from the DOM.
   blink::WebFrame* frame = render_frame()->GetWebFrame();
   const auto& password_form = provisionally_saved_form_.password_form();
   // TODO(crbug.com/720347): This method could be called often and checking form
   // visibility could be expesive. Add performance metrics for this.
-  if (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(),
-                               password_form.action, password_form.origin,
-                               password_form.form_data) ||
-      (provisionally_saved_form_.form_element().IsNull() &&
-       IsUnownedPasswordFormVisible(
-           frame, provisionally_saved_form_.input_element(),
-           password_form.action, password_form.origin, password_form.form_data,
-           form_predictions_))) {
+  if (event != PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR &&
+      (form_util::IsFormVisible(frame, provisionally_saved_form_.form_element(),
+                                password_form.action, password_form.origin,
+                                password_form.form_data) ||
+       (provisionally_saved_form_.form_element().IsNull() &&
+        IsUnownedPasswordFormVisible(
+            frame, provisionally_saved_form_.input_element(),
+            password_form.action, password_form.origin, password_form.form_data,
+            form_predictions_)))) {
+    if (!form_element_observer_) {
+      std::unique_ptr<FormElementObserverCallback> callback(
+          new FormElementObserverCallback(this));
+      if (provisionally_saved_form_.form_element().IsNull()) {
+        form_element_observer_ = blink::WebFormElementObserver::Create(
+            provisionally_saved_form_.input_element(), std::move(callback));
+      } else {
+        form_element_observer_ = blink::WebFormElementObserver::Create(
+            provisionally_saved_form_.form_element(), std::move(callback));
+      }
+    }
     return;
   }
 
+  provisionally_saved_form_.SetSubmissionIndicatorEvent(event);
   GetPasswordManagerDriver()->InPageNavigation(password_form);
+  if (form_element_observer_) {
+    form_element_observer_->Disconnect();
+    form_element_observer_ = nullptr;
+  }
   provisionally_saved_form_.Reset();
 }
 
@@ -1217,7 +1255,8 @@
     bool is_new_navigation,
     bool is_same_document_navigation) {
   if (is_same_document_navigation) {
-    OnSameDocumentNavigationCompleted(true);
+    OnSameDocumentNavigationCompleted(
+        PasswordForm::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION);
   } else {
     checked_safe_browsing_reputation_ = false;
   }
@@ -1299,6 +1338,10 @@
     // RenderView to be instantiated (such as redirects to the WebStore)
     // we will never get to finish the load.
     GetPasswordManagerDriver()->PasswordFormSubmitted(*submitted_form);
+    if (form_element_observer_) {
+      form_element_observer_->Disconnect();
+      form_element_observer_ = nullptr;
+    }
     provisionally_saved_form_.Reset();
   } else if (logger) {
     logger->LogMessage(Logger::STRING_FORM_IS_NOT_PASSWORD);
@@ -1346,6 +1389,10 @@
       }
       GetPasswordManagerDriver()->PasswordFormSubmitted(
           provisionally_saved_form_.password_form());
+      if (form_element_observer_) {
+        form_element_observer_->Disconnect();
+        form_element_observer_ = nullptr;
+      }
       provisionally_saved_form_.Reset();
     } else {
       std::vector<std::unique_ptr<PasswordForm>> possible_submitted_forms;
@@ -1629,6 +1676,10 @@
     password_to_username_.erase(iter.second.password_field);
   }
   web_input_to_password_info_.clear();
+  if (form_element_observer_) {
+    form_element_observer_->Disconnect();
+    form_element_observer_ = nullptr;
+  }
   provisionally_saved_form_.Reset();
   field_value_and_properties_map_.clear();
   sent_request_to_store_ = false;
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 86485be9..0b846e0 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -26,6 +26,7 @@
 #include "third_party/WebKit/public/web/WebInputElement.h"
 
 namespace blink {
+class WebFormElementObserver;
 class WebInputElement;
 class WebSecurityOrigin;
 }
@@ -147,6 +148,8 @@
       const blink::WebSecurityOrigin& origin);
 
  private:
+  class FormElementObserverCallback;
+
   // Ways to restrict which passwords are saved in ProvisionallySavePassword.
   enum ProvisionallySaveRestriction {
     RESTRICTION_NONE,
@@ -258,7 +261,8 @@
                                  ProvisionallySaveRestriction restriction);
 
   // Helper function called when same-document navigation completed
-  void OnSameDocumentNavigationCompleted(bool is_inpage_navigation);
+  void OnSameDocumentNavigationCompleted(
+      PasswordForm::SubmissionIndicatorEvent event);
 
   const mojom::AutofillDriverPtr& GetAutofillDriver();
 
@@ -308,6 +312,8 @@
 
   mojo::Binding<mojom::PasswordAutofillAgent> binding_;
 
+  blink::WebFormElementObserver* form_element_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgent);
 };
 
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index 1a0f3d7..5d56dc54 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -19,6 +19,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
+#include "components/autofill/core/common/autofill_regex_constants.h"
+#include "components/autofill/core/common/autofill_regexes.h"
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_field_prediction_map.h"
@@ -429,6 +431,8 @@
 
     if (HasCreditCardAutocompleteAttributes(*input_element))
       continue;
+    if (IsCreditCardVerificationPasswordField(*input_element))
+      continue;
 
     bool element_is_invisible = !form_util::IsWebElementVisible(*input_element);
     if (input_element->IsTextField()) {
@@ -766,4 +770,15 @@
   return false;
 }
 
+bool IsCreditCardVerificationPasswordField(
+    const blink::WebInputElement& field) {
+  if (!field.IsPasswordField())
+    return false;
+
+  static const base::string16 kCardCvcReCached = base::UTF8ToUTF16(kCardCvcRe);
+
+  return MatchesPattern(field.GetAttribute("id").Utf16(), kCardCvcReCached) ||
+         MatchesPattern(field.GetAttribute("name").Utf16(), kCardCvcReCached);
+}
+
 }  // namespace autofill
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.h b/components/autofill/content/renderer/password_form_conversion_utils.h
index 0529ac2c..77358e4 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -68,6 +68,10 @@
 // the given |element| are present.
 bool HasCreditCardAutocompleteAttributes(const blink::WebInputElement& element);
 
+// Returns whether the form |field| has a "password" type, but looks like a
+// credit card verification field.
+bool IsCreditCardVerificationPasswordField(const blink::WebInputElement& field);
+
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CONTENT_RENDERER_PASSWORD_FORM_CONVERSION_UTILS_H__
diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 2d3ceda..699caa9 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -1291,7 +1291,7 @@
 
   std::unique_ptr<PasswordForm> password_form =
       LoadHTMLAndConvertForm(html, &predictions, false);
-  EXPECT_TRUE(password_form);
+  EXPECT_FALSE(password_form);
 }
 
 TEST_F(MAYBE_PasswordFormConversionUtilsTest, IsGaiaReauthFormIgnored) {
diff --git a/components/autofill/content/renderer/provisionally_saved_password_form.h b/components/autofill/content/renderer/provisionally_saved_password_form.h
index 177cf48f..68af7b4 100644
--- a/components/autofill/content/renderer/provisionally_saved_password_form.h
+++ b/components/autofill/content/renderer/provisionally_saved_password_form.h
@@ -39,8 +39,8 @@
     DCHECK(IsSet());
     return *password_form_;
   }
-  const blink::WebFormElement& form_element() const { return form_element_; }
-  const blink::WebInputElement& input_element() const { return input_element_; }
+  blink::WebFormElement& form_element() { return form_element_; }
+  blink::WebInputElement& input_element() { return input_element_; }
 
   void SetSubmissionIndicatorEvent(
       PasswordForm::SubmissionIndicatorEvent event);
diff --git a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index 37efe46e..558b7fc 100644
--- a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
+
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "components/autofill/content/common/autofill_driver.mojom.h"
-#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
 #include "mojo/public/cpp/bindings/binding.h"
-
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc
index 73768ad..74ce62b4 100644
--- a/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc
index 6ca3204c..1a905491 100644
--- a/components/autofill/core/browser/autofill_experiments.cc
+++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/suggestion.h"
 #include "components/autofill/core/common/autofill_pref_names.h"
@@ -39,6 +40,9 @@
 const base::Feature kAutofillUpstreamUseAutofillProfileComparatorForName{
     "AutofillUpstreamUseAutofillProfileComparatorForName",
     base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillUpstreamUseNotRecentlyUsedAutofillProfile{
+    "AutofillUpstreamUseNotRecentlyUsedAutofillProfile",
+    base::FEATURE_DISABLED_BY_DEFAULT};
 const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
 const char kAutofillCreditCardPopupBackgroundColorKey[] = "background_color";
 const char kAutofillCreditCardPopupDividerColorKey[] = "dropdown_divider_color";
@@ -51,6 +55,8 @@
 const char kAutofillPopupMarginKey[] = "margin";
 const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[] =
     "show_expiration_date";
+const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[] =
+    "max_minutes_since_autofill_profile_use";
 
 namespace {
 
@@ -242,4 +248,14 @@
 #endif
 }
 
+base::TimeDelta GetMaxTimeSinceAutofillProfileUseForCardUpload() {
+  int value;
+  const std::string param_value = variations::GetVariationParamValueByFeature(
+      kAutofillUpstreamUseNotRecentlyUsedAutofillProfile,
+      kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey);
+  if (!param_value.empty() && base::StringToInt(param_value, &value))
+    return base::TimeDelta::FromMinutes(value);
+  return base::TimeDelta();
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_experiments.h b/components/autofill/core/browser/autofill_experiments.h
index 94289f1..5e3ef073 100644
--- a/components/autofill/core/browser/autofill_experiments.h
+++ b/components/autofill/core/browser/autofill_experiments.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/strings/string16.h"
+#include "base/time/time.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 class PrefService;
@@ -31,9 +32,10 @@
 extern const base::Feature kAutofillUkmLogging;
 extern const base::Feature kAutofillUpstreamRequestCvcIfMissing;
 extern const base::Feature kAutofillUpstreamUseAutofillProfileComparatorForName;
+extern const base::Feature kAutofillUpstreamUseNotRecentlyUsedAutofillProfile;
 extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
-extern const char kAutofillCreditCardPopupSettingsSuggestionValueKey[];
 extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
+extern const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[];
 
 // Returns true if autofill should be enabled. See also
 // IsInAutofillSuggestionsDisabledExperiment below.
@@ -110,6 +112,11 @@
 // in the offer to save bubble if it was not detected during the checkout flow.
 bool IsAutofillUpstreamRequestCvcIfMissingExperimentEnabled();
 
+// Returns the maximum time that could have elapsed since an address profile's
+// most recent use for the adress profile to be included in the candidate set
+// for card upload. Returns 0 if the experiment is not enabled.
+base::TimeDelta GetMaxTimeSinceAutofillProfileUseForCardUpload();
+
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_EXPERIMENTS_H_
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 9f5a3b6..1a6f82ff 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -33,6 +33,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autocomplete_history_manager.h"
 #include "components/autofill/core/browser/autofill_client.h"
@@ -1349,6 +1350,20 @@
   AutofillMetrics::LogHasModifiedProfileOnCreditCardFormSubmission(
       has_modified_profile);
 
+  // If there are no recently used or modified profiles and experiment to use
+  // profiles that were not recently is enabled, collect the profiles that were
+  // not recently used but used within the maximum time specified in the
+  // experiment.
+  if (candidate_profiles.empty()) {
+    const base::TimeDelta max_time_since_use =
+        GetMaxTimeSinceAutofillProfileUseForCardUpload();
+    if (!max_time_since_use.is_zero())
+      for (AutofillProfile* profile : personal_data_->GetProfiles())
+        if ((now - profile->modification_date()) < max_time_since_use ||
+            (now - profile->use_date()) < max_time_since_use)
+          candidate_profiles.push_back(*profile);
+  }
+
   if (candidate_profiles.empty()) {
     upload_decision_metrics |=
         has_profile
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 80ad0320..0c56863 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -61,6 +61,7 @@
 #include "components/ukm/ukm_entry.h"
 #include "components/ukm/ukm_source.h"
 #include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_params_manager.h"
 #include "net/base/url_util.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
@@ -849,7 +850,7 @@
 
 class AutofillManagerTest : public testing::Test {
  public:
-  AutofillManagerTest() : field_trial_list_(nullptr) {}
+  AutofillManagerTest() {}
 
   void SetUp() override {
     autofill_client_.SetPrefs(test::PrefServiceForTesting());
@@ -869,8 +870,7 @@
         autofill_manager_.get(), autofill_driver_.get()));
     autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
-    // Clear all the things.
-    variations::testing::ClearAllVariationParams();
+    variation_params_.ClearAllVariationParams();
   }
 
   void TearDown() override {
@@ -1180,8 +1180,8 @@
   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
   TestAutofillDownloadManager* download_manager_;
   TestPersonalDataManager personal_data_;
-  base::FieldTrialList field_trial_list_;
   base::test::ScopedFeatureList scoped_feature_list_;
+  variations::testing::VariationParamsManager variation_params_;
 
  private:
   int ToHistogramSample(AutofillMetrics::CardUploadDecisionMetric metric) {
@@ -4986,15 +4986,8 @@
   ExpectCardUploadDecisionUkm(AutofillMetrics::CVC_FIELD_NOT_FOUND);
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField \
-  DISABLED_UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField
-#else
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField \
-  UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField
-#endif
 TEST_F(AutofillManagerTest,
-       MAYBE_UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField) {
+       UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField) {
   EnableUkmLogging();
   autofill_manager_->set_credit_card_upload_enabled(true);
 
@@ -5052,15 +5045,8 @@
   ExpectCardUploadDecisionUkm(AutofillMetrics::CVC_FIELD_NOT_FOUND);
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField \
-  DISABLED_UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField
-#else
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField \
-  UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField
-#endif
 TEST_F(AutofillManagerTest,
-       MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField) {
+       UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField) {
   EnableUkmLogging();
   autofill_manager_->set_credit_card_upload_enabled(true);
 
@@ -5120,15 +5106,8 @@
       AutofillMetrics::FOUND_POSSIBLE_CVC_VALUE_IN_NON_CVC_FIELD);
 }
 
-#if defined(OS_ANDROID)
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField \
-  DISABLED_UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField
-#else
-#define MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField \
-  UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField
-#endif
 TEST_F(AutofillManagerTest,
-       MAYBE_UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField) {
+       UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField) {
   EnableUkmLogging();
   autofill_manager_->set_credit_card_upload_enabled(true);
 
@@ -5416,6 +5395,59 @@
 }
 
 TEST_F(AutofillManagerTest,
+       UploadCreditCard_NoRecentlyUsedProfile_CanUseOldProfile) {
+  variation_params_.SetVariationParamsWithFeatureAssociations(
+      kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name,
+      {{kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey,
+        base::IntToString((kMuchLaterTime - kArbitraryTime).InMinutes() + 1)}},
+      {kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name});
+
+  // Create the test clock and set the time to a specific value.
+  TestAutofillClock test_clock;
+  test_clock.SetNow(kArbitraryTime);
+
+  personal_data_.ClearAutofillProfiles();
+  autofill_manager_->set_credit_card_upload_enabled(true);
+
+  // Create, fill and submit an address form in order to establish a profile.
+  FormData address_form;
+  test::CreateTestAddressFormData(&address_form);
+  FormsSeen({address_form});
+
+  ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+  FormSubmitted(address_form);
+
+  // Advance the current time. Although |address_form| is not a recently used
+  // address profile, we will include it in the candidate profiles because
+  // there are no recently used address profiles and the feature to use older
+  // profiles is enabled.
+  test_clock.SetNow(kMuchLaterTime);
+
+  // Set up our credit card form data.
+  FormData credit_card_form;
+  CreateTestCreditCardFormData(&credit_card_form, true, false);
+  FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+  // Edit the data, and submit.
+  credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
+  credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+  credit_card_form.fields[2].value = ASCIIToUTF16("11");
+  credit_card_form.fields[3].value = ASCIIToUTF16("2017");
+  credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+  base::HistogramTester histogram_tester;
+
+  // Upload should be offered.
+  EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
+  FormSubmitted(credit_card_form);
+  EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+
+  // Verify that the correct histogram entry (and only that) was logged.
+  ExpectUniqueCardUploadDecision(histogram_tester,
+                                 AutofillMetrics::UPLOAD_OFFERED);
+}
+
+TEST_F(AutofillManagerTest,
        UploadCreditCard_CvcUnavailableAndNoProfileAvailable) {
   EnableUkmLogging();
   personal_data_.ClearAutofillProfiles();
@@ -6056,6 +6088,62 @@
 }
 
 TEST_F(AutofillManagerTest,
+       UploadCreditCard_IgnoreOldProfiles_CanUseOldProfiles) {
+  variation_params_.SetVariationParamsWithFeatureAssociations(
+      kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name,
+      {{kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey,
+        base::IntToString((kMuchLaterTime - kArbitraryTime).InMinutes() + 1)}},
+      {kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name});
+
+  // Create the test clock and set the time to a specific value.
+  TestAutofillClock test_clock;
+  test_clock.SetNow(kArbitraryTime);
+
+  personal_data_.ClearAutofillProfiles();
+  autofill_manager_->set_credit_card_upload_enabled(true);
+
+  // Create, fill and submit two address forms with different names.
+  FormData address_form1, address_form2;
+  test::CreateTestAddressFormData(&address_form1);
+  test::CreateTestAddressFormData(&address_form2);
+  FormsSeen({address_form1, address_form2});
+
+  ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form1);
+  FormSubmitted(address_form1);
+
+  // Advance the current time. Since |address_form1| will not be a recently
+  // used address profile, we will not include it in the candidate profiles
+  // because we have a recently used address.
+  test_clock.SetNow(kMuchLaterTime);
+
+  ManuallyFillAddressForm("Master", "Blaster", "77401", "US", &address_form2);
+  FormSubmitted(address_form2);
+
+  // Set up our credit card form data.
+  FormData credit_card_form;
+  CreateTestCreditCardFormData(&credit_card_form, true, false);
+  FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+  // Edit the data, but use yet another name, and submit.
+  credit_card_form.fields[0].value = ASCIIToUTF16("Master Blaster");
+  credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+  credit_card_form.fields[2].value = ASCIIToUTF16("11");
+  credit_card_form.fields[3].value = ASCIIToUTF16("2017");
+  credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+  base::HistogramTester histogram_tester;
+
+  // Name matches recently used profile, should offer upload.
+  EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
+  FormSubmitted(credit_card_form);
+  EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+
+  // Verify that the correct histogram entry (and only that) was logged.
+  ExpectUniqueCardUploadDecision(histogram_tester,
+                                 AutofillMetrics::UPLOAD_OFFERED);
+}
+
+TEST_F(AutofillManagerTest,
        UploadCreditCard_NamesHaveToMatch_DisableComparator) {
   DisableAutofillUpstreamUseAutofillProfileComparatorForName();
   personal_data_.ClearAutofillProfiles();
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 52e396e..faadedd 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/guid.h"
 #include "base/i18n/time_formatting.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
index 68e8dd0..f0abd6f 100644
--- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc
+++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
diff --git a/components/autofill/core/common/password_form.cc b/components/autofill/core/common/password_form.cc
index ee5f8112..5adca72 100644
--- a/components/autofill/core/common/password_form.cc
+++ b/components/autofill/core/common/password_form.cc
@@ -242,6 +242,9 @@
     case PasswordForm::SubmissionIndicatorEvent::MANUAL_SAVE:
       os << "MANUAL_SAVE";
       break;
+    case PasswordForm::SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR:
+      os << "DOM_MUTATION_AFTER_XHR";
+      break;
     default:
       os << "NO_SUBMISSION";
       break;
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h
index bb4611e..79599542 100644
--- a/components/autofill/core/common/password_form.h
+++ b/components/autofill/core/common/password_form.h
@@ -95,6 +95,7 @@
     XHR_SUCCEEDED,
     FRAME_DETACHED,
     MANUAL_SAVE,
+    DOM_MUTATION_AFTER_XHR,
     SUBMISSION_INDICATOR_EVENT_COUNT
   };
 
diff --git a/components/bookmarks/test/bookmark_test_helpers.cc b/components/bookmarks/test/bookmark_test_helpers.cc
index 18a7a9f..fa435d4d 100644
--- a/components/bookmarks/test/bookmark_test_helpers.cc
+++ b/components/bookmarks/test/bookmark_test_helpers.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/bookmarks/browser/base_bookmark_model_observer.h"
diff --git a/components/browser_sync/profile_sync_service_startup_unittest.cc b/components/browser_sync/profile_sync_service_startup_unittest.cc
index 3f63fc4..9d3e951e 100644
--- a/components/browser_sync/profile_sync_service_startup_unittest.cc
+++ b/components/browser_sync/profile_sync_service_startup_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/browser_sync/profile_sync_test_util.h"
diff --git a/components/browser_sync/profile_sync_service_typed_url_unittest.cc b/components/browser_sync/profile_sync_service_typed_url_unittest.cc
index c408d6c..f13b748 100644
--- a/components/browser_sync/profile_sync_service_typed_url_unittest.cc
+++ b/components/browser_sync/profile_sync_service_typed_url_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/browser_sync/test_profile_sync_service.cc b/components/browser_sync/test_profile_sync_service.cc
index a4bc8d08..9eab474 100644
--- a/components/browser_sync/test_profile_sync_service.cc
+++ b/components/browser_sync/test_profile_sync_service.cc
@@ -6,6 +6,8 @@
 
 #include <utility>
 
+#include "base/message_loop/message_loop.h"
+
 namespace browser_sync {
 
 syncer::TestIdFactory* TestProfileSyncService::id_factory() {
diff --git a/components/browser_watcher/window_hang_monitor_win_unittest.cc b/components/browser_watcher/window_hang_monitor_win_unittest.cc
index a8ce37a..2df2a7b 100644
--- a/components/browser_watcher/window_hang_monitor_win_unittest.cc
+++ b/components/browser_watcher/window_hang_monitor_win_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/base_paths.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/launch.h"
 #include "base/process/process.h"
diff --git a/components/certificate_reporting/error_report_unittest.cc b/components/certificate_reporting/error_report_unittest.cc
index f2deb56..18c548c 100644
--- a/components/certificate_reporting/error_report_unittest.cc
+++ b/components/certificate_reporting/error_report_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/threading/thread.h"
 #include "base/time/default_clock.h"
diff --git a/components/certificate_transparency/ct_policy_manager_unittest.cc b/components/certificate_transparency/ct_policy_manager_unittest.cc
index e535f98..6a2d53b 100644
--- a/components/certificate_transparency/ct_policy_manager_unittest.cc
+++ b/components/certificate_transparency/ct_policy_manager_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <iterator>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
diff --git a/components/component_updater/component_updater_service_unittest.cc b/components/component_updater/component_updater_service_unittest.cc
index d833d200..8cf3130 100644
--- a/components/component_updater/component_updater_service_unittest.cc
+++ b/components/component_updater/component_updater_service_unittest.cc
@@ -17,8 +17,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/test/histogram_tester.h"
-#include "base/test/sequenced_worker_pool_owner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/component_updater/component_updater_service_internal.h"
@@ -115,14 +116,10 @@
   void RunThreads();
 
  private:
-  static const int kNumWorkerThreads_ = 2;
-
-  base::MessageLoopForUI message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::RunLoop runloop_;
   base::Closure quit_closure_;
 
-  std::unique_ptr<base::SequencedWorkerPoolOwner> worker_pool_;
-
   scoped_refptr<TestConfigurator> config_;
   scoped_refptr<MockUpdateClient> update_client_;
   std::unique_ptr<ComponentUpdateService> component_updater_;
@@ -177,14 +174,13 @@
 }
 
 ComponentUpdaterTest::ComponentUpdaterTest()
-    : worker_pool_(
-          new base::SequencedWorkerPoolOwner(kNumWorkerThreads_, "test")) {
+    : scoped_task_environment_(
+          base::test::ScopedTaskEnvironment::MainThreadType::UI) {
   quit_closure_ = runloop_.QuitClosure();
 
-  auto pool = worker_pool_->pool();
   config_ = new TestConfigurator(
-      pool->GetSequencedTaskRunner(pool->GetSequenceToken()),
-      message_loop_.task_runner());
+      base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}),
+      base::ThreadTaskRunnerHandle::Get());
 
   update_client_ = new MockUpdateClient();
   EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc
index 515b5ed..bd1ab8a 100644
--- a/components/cronet/android/test/quic_test_server.cc
+++ b/components/cronet/android/test/quic_test_server.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/test_support_android.h"
 #include "base/threading/thread.h"
 #include "components/cronet/android/test/cronet_test_util.h"
diff --git a/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc b/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
index 1c65f26..44429e3 100644
--- a/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/content_resource_type_provider_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
index c8922c5..7aa01480 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/test/histogram_tester.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index f301943..2c798fa 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index b2bf43a0..a0d1cbd 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/strings/safe_sprintf.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
index 4497aeb..5790d44 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -25,6 +25,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
 #include "components/prefs/pref_service.h"
+#include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_response_headers.h"
@@ -545,13 +546,7 @@
   EXPECT_EQ(std::vector<GURL>(1, GURL("http://foo.com")), request->url_chain());
 }
 
-// https://crbug.com/668197: Flaky on android_n5x_swarming_rel bot.
-#if defined(OS_ANDROID)
-#define MAYBE_RedirectChainToHttps DISABLED_RedirectChainToHttps
-#else
-#define MAYBE_RedirectChainToHttps RedirectChainToHttps
-#endif
-TEST_F(DataReductionProxyInterceptorEndToEndTest, MAYBE_RedirectChainToHttps) {
+TEST_F(DataReductionProxyInterceptorEndToEndTest, RedirectChainToHttps) {
   // First, a redirect is successfully received through the Data Reduction
   // Proxy. HSTS is forced for play.google.com and prebaked into Chrome, so
   // http://play.google.com will automatically be redirected to
@@ -583,6 +578,9 @@
 
   std::unique_ptr<net::URLRequest> request =
       CreateAndExecuteRequest(GURL("http://music.google.com"));
+  request->SetLoadFlags(net::LOAD_DISABLE_CACHE |
+                        net::LOAD_DO_NOT_SEND_COOKIES |
+                        net::LOAD_DO_NOT_SAVE_COOKIES);
   EXPECT_FALSE(delegate().request_failed());
   EXPECT_EQ(kBody, delegate().data_received());
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index 67deac59..fb75ff2e 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_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/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
index da8d668..2a4d4b01 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
index 1e58b8a..73a2390 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/command_line.h"
 #include "base/md5.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
index 8af34b7..e111c5a 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/md5.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_samples.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/dom_distiller/core/task_tracker_unittest.cc b/components/dom_distiller/core/task_tracker_unittest.cc
index b760b4ab..4f317e5a 100644
--- a/components/dom_distiller/core/task_tracker_unittest.cc
+++ b/components/dom_distiller/core/task_tracker_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/dom_distiller/core/article_distillation_update.h"
 #include "components/dom_distiller/core/article_entry.h"
diff --git a/components/dom_distiller/standalone/content_extractor_browsertest.cc b/components/dom_distiller/standalone/content_extractor_browsertest.cc
index 86aae71..c81a6530 100644
--- a/components/dom_distiller/standalone/content_extractor_browsertest.cc
+++ b/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/id_map.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/components/domain_reliability/util.cc b/components/domain_reliability/util.cc
index 1b3431a0..9c4406f 100644
--- a/components/domain_reliability/util.cc
+++ b/components/domain_reliability/util.cc
@@ -127,6 +127,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
       return "QUIC";
     case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
diff --git a/components/download/internal/BUILD.gn b/components/download/internal/BUILD.gn
index 189bf07..1eda30f 100644
--- a/components/download/internal/BUILD.gn
+++ b/components/download/internal/BUILD.gn
@@ -20,11 +20,14 @@
     "download_service_impl.h",
     "scheduler/battery_listener.cc",
     "scheduler/battery_listener.h",
+    "scheduler/network_listener.cc",
+    "scheduler/network_listener.h",
   ]
 
   deps = [
     "//base",
     "//components/download/public",
+    "//net",
   ]
 }
 
@@ -36,6 +39,7 @@
   sources = [
     "download_service_impl_unittest.cc",
     "scheduler/battery_listener_unittest.cc",
+    "scheduler/network_listener_unittest.cc",
   ]
 
   deps = [
diff --git a/components/download/internal/DEPS b/components/download/internal/DEPS
index c5ed643..a348cdf 100644
--- a/components/download/internal/DEPS
+++ b/components/download/internal/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "-content",
   "+base",
+  "+net",
 ]
diff --git a/components/download/internal/scheduler/network_listener.cc b/components/download/internal/scheduler/network_listener.cc
new file mode 100644
index 0000000..d09d527
--- /dev/null
+++ b/components/download/internal/scheduler/network_listener.cc
@@ -0,0 +1,84 @@
+// 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/download/internal/scheduler/network_listener.h"
+
+namespace download {
+
+namespace {
+
+// Converts a ConnectionType to NetworkListener::NetworkStatus.
+NetworkListener::NetworkStatus ToNetworkStatus(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  switch (type) {
+    case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
+    case net::NetworkChangeNotifier::CONNECTION_WIFI:
+      return NetworkListener::NetworkStatus::UNMETERED;
+    case net::NetworkChangeNotifier::CONNECTION_2G:
+    case net::NetworkChangeNotifier::CONNECTION_3G:
+    case net::NetworkChangeNotifier::CONNECTION_4G:
+      return NetworkListener::NetworkStatus::METERED;
+    case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
+    case net::NetworkChangeNotifier::CONNECTION_NONE:
+    case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
+      return NetworkListener::NetworkStatus::DISCONNECTED;
+  }
+  NOTREACHED();
+  return NetworkListener::NetworkStatus::DISCONNECTED;
+}
+
+}  // namespace
+
+NetworkListener::NetworkListener()
+    : status_(NetworkStatus::DISCONNECTED), listening_(false) {}
+
+NetworkListener::~NetworkListener() {
+  Stop();
+}
+
+NetworkListener::NetworkStatus NetworkListener::CurrentNetworkStatus() const {
+  return ToNetworkStatus(net::NetworkChangeNotifier::GetConnectionType());
+}
+
+void NetworkListener::Start() {
+  if (listening_)
+    return;
+
+  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+  status_ = ToNetworkStatus(net::NetworkChangeNotifier::GetConnectionType());
+  listening_ = true;
+}
+
+void NetworkListener::Stop() {
+  if (!listening_)
+    return;
+
+  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+  status_ = ToNetworkStatus(net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
+  listening_ = false;
+}
+
+void NetworkListener::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void NetworkListener::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void NetworkListener::OnConnectionTypeChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  NetworkStatus new_status = ToNetworkStatus(type);
+  if (status_ != new_status) {
+    status_ = new_status;
+    NotifyNetworkChange(status_);
+  }
+}
+
+void NetworkListener::NotifyNetworkChange(NetworkStatus network_status) {
+  for (auto& observer : observers_)
+    observer.OnNetworkChange(network_status);
+}
+
+}  // namespace download
diff --git a/components/download/internal/scheduler/network_listener.h b/components/download/internal/scheduler/network_listener.h
new file mode 100644
index 0000000..6b05ffb1
--- /dev/null
+++ b/components/download/internal/scheduler/network_listener.h
@@ -0,0 +1,66 @@
+// 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_DOWNLOAD_INTERNAL_SCHEDULER_NETWORK_LISTENER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_NETWORK_LISTENER_H_
+
+#include "net/base/network_change_notifier.h"
+
+namespace download {
+
+// Listens to network status change and notifies observers in download service.
+class NetworkListener
+    : public net::NetworkChangeNotifier::ConnectionTypeObserver {
+ public:
+  // NetworkStatus should mostly one to one map to
+  // SchedulingParams::NetworkRequirements. Has coarser granularity than
+  // network connection type.
+  enum class NetworkStatus {
+    DISCONNECTED = 0,
+    UNMETERED = 1,  // WIFI or Ethernet.
+    METERED = 2,    // Mobile networks.
+  };
+
+  class Observer {
+   public:
+    // Called when network status is changed.
+    virtual void OnNetworkChange(NetworkStatus network_status) = 0;
+  };
+
+  NetworkListener();
+  ~NetworkListener() override;
+
+  // Returns the current network status for download scheduling.
+  NetworkStatus CurrentNetworkStatus() const;
+
+  // Starts/stops to listen network change events.
+  void Start();
+  void Stop();
+
+  // Adds/Removes observers.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+ private:
+  // net::NetworkChangeNotifier implementation.
+  void OnConnectionTypeChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override;
+
+  // Notifies |observers_| about network status change. See |NetworkStatus|.
+  void NotifyNetworkChange(NetworkStatus network_status);
+
+  // The current network status.
+  NetworkStatus status_;
+
+  // If we are actively listening to network change events.
+  bool listening_;
+
+  base::ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkListener);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_SCHEDULER_NETWORK_LISTENER_H_
diff --git a/components/download/internal/scheduler/network_listener_unittest.cc b/components/download/internal/scheduler/network_listener_unittest.cc
new file mode 100644
index 0000000..189fa611
--- /dev/null
+++ b/components/download/internal/scheduler/network_listener_unittest.cc
@@ -0,0 +1,97 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/internal/scheduler/network_listener.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ConnectionTypeObserver =
+    net::NetworkChangeNotifier::ConnectionTypeObserver;
+using ConnectionType = net::NetworkChangeNotifier::ConnectionType;
+
+namespace download {
+
+// NetworkChangeNotifier that can change network type in tests.
+class TestNetworkChangeNotifier : public net::NetworkChangeNotifier {
+ public:
+  TestNetworkChangeNotifier()
+      : net::NetworkChangeNotifier(),
+        conn_type_(ConnectionType::CONNECTION_UNKNOWN) {}
+
+  // net::NetworkChangeNotifier implementation.
+  ConnectionType GetCurrentConnectionType() const override {
+    return conn_type_;
+  }
+
+  // Change the network type.
+  void ChangeNetworkType(ConnectionType type) {
+    conn_type_ = type;
+    net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
+        type);
+    base::RunLoop().RunUntilIdle();
+  }
+
+ private:
+  ConnectionType conn_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier);
+};
+
+class MockObserver : public NetworkListener::Observer {
+ public:
+  MOCK_METHOD1(OnNetworkChange, void(NetworkListener::NetworkStatus));
+};
+
+class NetworkListenerTest : public testing::Test {
+ public:
+  // Simulates a network change call.
+  void ChangeNetworkType(ConnectionType type) {
+    test_network_notifier_.ChangeNetworkType(type);
+  }
+
+ protected:
+  NetworkListener network_listener_;
+  MockObserver mock_observer_;
+
+  // Needed for network change notifier.
+  base::MessageLoop message_loop_;
+  TestNetworkChangeNotifier test_network_notifier_;
+};
+
+TEST_F(NetworkListenerTest, NotifyObserverNetworkChange) {
+  network_listener_.Start();
+  network_listener_.AddObserver(&mock_observer_);
+
+  // Initial states check.
+  EXPECT_EQ(NetworkListener::NetworkStatus::DISCONNECTED,
+            network_listener_.CurrentNetworkStatus());
+
+  // Network switch between mobile networks, the observer should be notified
+  // only once.
+  EXPECT_CALL(mock_observer_,
+              OnNetworkChange(NetworkListener::NetworkStatus::METERED))
+      .Times(1)
+      .RetiresOnSaturation();
+
+  ChangeNetworkType(ConnectionType::CONNECTION_4G);
+  ChangeNetworkType(ConnectionType::CONNECTION_3G);
+  ChangeNetworkType(ConnectionType::CONNECTION_2G);
+  EXPECT_EQ(NetworkListener::NetworkStatus::METERED,
+            network_listener_.CurrentNetworkStatus());
+
+  // Network is switched between wifi and ethernet, the observer should be
+  // notified only once.
+  EXPECT_CALL(mock_observer_,
+              OnNetworkChange(NetworkListener::NetworkStatus::UNMETERED))
+      .Times(1)
+      .RetiresOnSaturation();
+
+  ChangeNetworkType(ConnectionType::CONNECTION_WIFI);
+  ChangeNetworkType(ConnectionType::CONNECTION_ETHERNET);
+}
+
+}  // namespace download
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index f9e941d..bf00c8ee 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -40,6 +40,7 @@
 #include "base/memory/free_deleter.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread.h"
diff --git a/components/feature_engagement_tracker/components_unittests.filter b/components/feature_engagement_tracker/components_unittests.filter
index 8b84948..e5d36ca 100644
--- a/components/feature_engagement_tracker/components_unittests.filter
+++ b/components/feature_engagement_tracker/components_unittests.filter
@@ -3,6 +3,7 @@
 ConditionValidatorResultTest.*
 EditableConfigurationTest.*
 FailingInitFeatureEngagementTrackerImplTest.*
+FeatureConfigConditionValidatorTest.*
 FeatureConfigStorageValidatorTest.*
 FeatureEngagementTrackerImplTest.*
 InMemoryStoreTest.*
diff --git a/components/feature_engagement_tracker/internal/BUILD.gn b/components/feature_engagement_tracker/internal/BUILD.gn
index 566d3103..3e67970 100644
--- a/components/feature_engagement_tracker/internal/BUILD.gn
+++ b/components/feature_engagement_tracker/internal/BUILD.gn
@@ -22,6 +22,8 @@
     "configuration.h",
     "editable_configuration.cc",
     "editable_configuration.h",
+    "feature_config_condition_validator.cc",
+    "feature_config_condition_validator.h",
     "feature_config_storage_validator.cc",
     "feature_config_storage_validator.h",
     "feature_engagement_tracker_impl.cc",
@@ -82,6 +84,7 @@
     "condition_validator_unittest.cc",
     "configuration_unittest.cc",
     "editable_configuration_unittest.cc",
+    "feature_config_condition_validator_unittest.cc",
     "feature_config_storage_validator_unittest.cc",
     "feature_engagement_tracker_impl_unittest.cc",
     "in_memory_store_unittest.cc",
diff --git a/components/feature_engagement_tracker/internal/condition_validator.cc b/components/feature_engagement_tracker/internal/condition_validator.cc
index ff79b62..de944c9 100644
--- a/components/feature_engagement_tracker/internal/condition_validator.cc
+++ b/components/feature_engagement_tracker/internal/condition_validator.cc
@@ -9,6 +9,7 @@
 ConditionValidator::Result::Result(bool initial_values)
     : model_ready_ok(initial_values),
       currently_showing_ok(initial_values),
+      feature_enabled_ok(initial_values),
       config_ok(initial_values),
       used_ok(initial_values),
       trigger_ok(initial_values),
@@ -16,8 +17,9 @@
       session_rate_ok(initial_values) {}
 
 bool ConditionValidator::Result::NoErrors() {
-  return model_ready_ok && currently_showing_ok && config_ok && used_ok &&
-         trigger_ok && preconditions_ok && session_rate_ok;
+  return model_ready_ok && currently_showing_ok && feature_enabled_ok &&
+         config_ok && used_ok && trigger_ok && preconditions_ok &&
+         session_rate_ok;
 }
 
 }  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/condition_validator.h b/components/feature_engagement_tracker/internal/condition_validator.h
index 46eb68ec..d1129aed 100644
--- a/components/feature_engagement_tracker/internal/condition_validator.h
+++ b/components/feature_engagement_tracker/internal/condition_validator.h
@@ -37,6 +37,9 @@
     // Whether no other in-product helps were shown at the time.
     bool currently_showing_ok;
 
+    // Whether the feature is enabled.
+    bool feature_enabled_ok;
+
     // Whether the feature configuration was valid.
     bool config_ok;
 
diff --git a/components/feature_engagement_tracker/internal/condition_validator_unittest.cc b/components/feature_engagement_tracker/internal/condition_validator_unittest.cc
index 2c7f4ab2..10dd581e 100644
--- a/components/feature_engagement_tracker/internal/condition_validator_unittest.cc
+++ b/components/feature_engagement_tracker/internal/condition_validator_unittest.cc
@@ -28,6 +28,12 @@
   EXPECT_FALSE(result.NoErrors());
 }
 
+TEST(ConditionValidatorResultTest, TestFeatureEnabled) {
+  ConditionValidator::Result result(true);
+  result.feature_enabled_ok = false;
+  EXPECT_FALSE(result.NoErrors());
+}
+
 TEST(ConditionValidatorResultTest, TestInvalidConfig) {
   ConditionValidator::Result result(true);
   result.config_ok = false;
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator.cc b/components/feature_engagement_tracker/internal/feature_config_condition_validator.cc
new file mode 100644
index 0000000..fc3e378b
--- /dev/null
+++ b/components/feature_engagement_tracker/internal/feature_config_condition_validator.cc
@@ -0,0 +1,94 @@
+// 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/feature_engagement_tracker/internal/feature_config_condition_validator.h"
+
+#include "base/feature_list.h"
+#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement_tracker/internal/model.h"
+#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement_tracker/public/feature_list.h"
+
+namespace feature_engagement_tracker {
+
+FeatureConfigConditionValidator::FeatureConfigConditionValidator()
+    : currently_showing_(false), times_shown_(0u) {}
+
+FeatureConfigConditionValidator::~FeatureConfigConditionValidator() = default;
+
+ConditionValidator::Result FeatureConfigConditionValidator::MeetsConditions(
+    const base::Feature& feature,
+    const FeatureConfig& config,
+    const Model& model,
+    uint32_t current_day) const {
+  ConditionValidator::Result result(true);
+  result.model_ready_ok = model.IsReady();
+  result.currently_showing_ok = !currently_showing_;
+  result.feature_enabled_ok = base::FeatureList::IsEnabled(feature);
+  result.config_ok = config.valid;
+  result.used_ok = EventConfigMeetsConditions(config.used, model, current_day);
+  result.trigger_ok =
+      EventConfigMeetsConditions(config.trigger, model, current_day);
+
+  for (const auto& event_config : config.event_configs) {
+    result.preconditions_ok &=
+        EventConfigMeetsConditions(event_config, model, current_day);
+  }
+
+  result.session_rate_ok = config.session_rate.MeetsCriteria(times_shown_);
+
+  // TODO(nyquist): Add support for tracking and checking availability.
+
+  return result;
+}
+
+void FeatureConfigConditionValidator::NotifyIsShowing(
+    const base::Feature& feature) {
+  DCHECK(!currently_showing_);
+  DCHECK(base::FeatureList::IsEnabled(feature));
+
+  currently_showing_ = true;
+  ++times_shown_;
+}
+
+void FeatureConfigConditionValidator::NotifyDismissed(
+    const base::Feature& feature) {
+  currently_showing_ = false;
+}
+
+bool FeatureConfigConditionValidator::EventConfigMeetsConditions(
+    const EventConfig& event_config,
+    const Model& model,
+    uint32_t current_day) const {
+  const Event* event = model.GetEvent(event_config.name);
+
+  // If no events are found, the requirement must be met with 0 elements.
+  // Also, if the window is 0 days, there will never be any events.
+  if (event == nullptr || event_config.window == 0u)
+    return event_config.comparator.MeetsCriteria(0u);
+
+  DCHECK(event_config.window >= 0);
+
+  // A window of N=0:  Nothing should be counted.
+  // A window of N=1:  |current_day| should be counted.
+  // A window of N=2+: |current_day| plus |N-1| more days should be counted.
+  uint32_t oldest_accepted_day = current_day - event_config.window + 1;
+
+  // Cap |oldest_accepted_day| to UNIX epoch.
+  if (event_config.window > current_day)
+    oldest_accepted_day = 0u;
+
+  // Calculate the number of events within the window.
+  uint32_t event_count = 0;
+  for (const auto& event_day : event->events()) {
+    if (event_day.day() < oldest_accepted_day)
+      continue;
+
+    event_count += event_day.count();
+  }
+
+  return event_config.comparator.MeetsCriteria(event_count);
+}
+
+}  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator.h b/components/feature_engagement_tracker/internal/feature_config_condition_validator.h
new file mode 100644
index 0000000..2120ece
--- /dev/null
+++ b/components/feature_engagement_tracker/internal/feature_config_condition_validator.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "components/feature_engagement_tracker/internal/condition_validator.h"
+
+namespace feature_engagement_tracker {
+struct EventConfig;
+class Model;
+
+// A ConditionValidator that uses the FeatureConfigs as the source of truth.
+class FeatureConfigConditionValidator : public ConditionValidator {
+ public:
+  FeatureConfigConditionValidator();
+  ~FeatureConfigConditionValidator() override;
+
+  // ConditionValidator implementation.
+  ConditionValidator::Result MeetsConditions(
+      const base::Feature& feature,
+      const FeatureConfig& config,
+      const Model& model,
+      uint32_t current_day) const override;
+  void NotifyIsShowing(const base::Feature& feature) override;
+  void NotifyDismissed(const base::Feature& feature) override;
+
+ private:
+  bool EventConfigMeetsConditions(const EventConfig& event_config,
+                                  const Model& model,
+                                  uint32_t current_day) const;
+
+  // Whether in-product help is currently being shown.
+  bool currently_showing_;
+
+  // Number of times in-product help has been shown within the current session.
+  uint32_t times_shown_;
+
+  DISALLOW_COPY_AND_ASSIGN(FeatureConfigConditionValidator);
+};
+
+}  // namespace feature_engagement_tracker
+
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc b/components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc
new file mode 100644
index 0000000..9873bebc
--- /dev/null
+++ b/components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc
@@ -0,0 +1,433 @@
+// 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/feature_engagement_tracker/internal/feature_config_condition_validator.h"
+
+#include <string>
+
+#include "base/feature_list.h"
+#include "base/metrics/field_trial.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement_tracker/internal/model.h"
+#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace feature_engagement_tracker {
+
+namespace {
+
+const base::Feature kTestFeatureFoo{"test_foo",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kTestFeatureBar{"test_bar",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
+FeatureConfig GetValidFeatureConfig() {
+  FeatureConfig config;
+  config.valid = true;
+  return config;
+}
+
+FeatureConfig GetAcceptingFeatureConfig() {
+  FeatureConfig config;
+  config.valid = true;
+  config.used = EventConfig("used", Comparator(ANY, 0), 0, 0);
+  config.trigger = EventConfig("trigger", Comparator(ANY, 0), 0, 0);
+  config.session_rate = Comparator(ANY, 0);
+  config.availability = Comparator(ANY, 0);
+  return config;
+}
+
+class TestModel : public Model {
+ public:
+  TestModel() : ready_(true) {}
+
+  void Initialize(const OnModelInitializationFinished& callback,
+                  uint32_t current_day) override {}
+
+  bool IsReady() const override { return ready_; }
+
+  void SetIsReady(bool ready) { ready_ = ready; }
+
+  const Event* GetEvent(const std::string& event_name) const override {
+    auto search = events_.find(event_name);
+    if (search == events_.end())
+      return nullptr;
+
+    return &search->second;
+  }
+
+  void SetEvent(const Event& event) { events_[event.name()] = event; }
+
+  void IncrementEvent(const std::string& event_name, uint32_t day) override {}
+
+ private:
+  std::map<std::string, Event> events_;
+  bool ready_;
+};
+
+class FeatureConfigConditionValidatorTest : public ::testing::Test {
+ public:
+  FeatureConfigConditionValidatorTest() = default;
+
+ protected:
+  ConditionValidator::Result GetResultForDay(Comparator comparator,
+                                             uint32_t window,
+                                             uint32_t current_day) {
+    FeatureConfig config = GetAcceptingFeatureConfig();
+    config.event_configs.insert(EventConfig("event1", comparator, window, 0));
+    return validator_.MeetsConditions(kTestFeatureFoo, config, model_,
+                                      current_day);
+  }
+
+  ConditionValidator::Result GetResultForDayZero(const FeatureConfig& config) {
+    return validator_.MeetsConditions(kTestFeatureFoo, config, model_, 0);
+  }
+
+  TestModel model_;
+  FeatureConfigConditionValidator validator_;
+  uint32_t current_day_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FeatureConfigConditionValidatorTest);
+};
+
+}  // namespace
+
+TEST_F(FeatureConfigConditionValidatorTest, ModelNotReadyShouldFail) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  model_.SetIsReady(false);
+
+  ConditionValidator::Result result =
+      GetResultForDayZero(GetValidFeatureConfig());
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.model_ready_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, ConfigInvalidShouldFail) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  ConditionValidator::Result result = GetResultForDayZero(FeatureConfig());
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.config_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, MultipleErrorsShouldBeSet) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  model_.SetIsReady(false);
+
+  ConditionValidator::Result result = GetResultForDayZero(FeatureConfig());
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.model_ready_ok);
+  EXPECT_FALSE(result.config_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, ReadyModelEmptyConfig) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  EXPECT_TRUE(GetResultForDayZero(GetValidFeatureConfig()).NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, ReadyModelAcceptingConfig) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  EXPECT_TRUE(GetResultForDayZero(GetAcceptingFeatureConfig()).NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, CurrentlyShowing) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo, kTestFeatureBar}, {});
+
+  validator_.NotifyIsShowing(kTestFeatureBar);
+  ConditionValidator::Result result =
+      GetResultForDayZero(GetAcceptingFeatureConfig());
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.currently_showing_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, Used) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.used = EventConfig("used", Comparator(LESS_THAN, 0), 0, 0);
+
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.used_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, Trigger) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.trigger = EventConfig("trigger", Comparator(LESS_THAN, 0), 0, 0);
+
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.trigger_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, SingleOKPrecondition) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(EventConfig("event1", Comparator(ANY, 0), 0, 0));
+
+  EXPECT_TRUE(GetResultForDayZero(config).NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, MultipleOKPreconditions) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(EventConfig("event1", Comparator(ANY, 0), 0, 0));
+  config.event_configs.insert(EventConfig("event2", Comparator(ANY, 0), 0, 0));
+
+  EXPECT_TRUE(GetResultForDayZero(config).NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, OneOKThenOneFailingPrecondition) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(EventConfig("event1", Comparator(ANY, 0), 0, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(LESS_THAN, 0), 0, 0));
+
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, OneFailingThenOneOKPrecondition) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(EventConfig("event1", Comparator(ANY, 0), 0, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(LESS_THAN, 0), 0, 0));
+
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, TwoFailingPreconditions) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(LESS_THAN, 0), 0, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(LESS_THAN, 0), 0, 0));
+
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, SessionRate) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo, kTestFeatureBar}, {});
+
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.session_rate = Comparator(LESS_THAN, 2u);
+
+  EXPECT_TRUE(GetResultForDayZero(config).NoErrors());
+
+  validator_.NotifyIsShowing(kTestFeatureBar);
+  validator_.NotifyDismissed(kTestFeatureBar);
+  EXPECT_TRUE(GetResultForDayZero(config).NoErrors());
+
+  validator_.NotifyIsShowing(kTestFeatureBar);
+  validator_.NotifyDismissed(kTestFeatureBar);
+  ConditionValidator::Result result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.session_rate_ok);
+
+  validator_.NotifyIsShowing(kTestFeatureBar);
+  validator_.NotifyDismissed(kTestFeatureBar);
+  result = GetResultForDayZero(config);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.session_rate_ok);
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, SingleEventChangingComparator) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  uint32_t current_day = 102u;
+  uint32_t window = 10u;
+
+  // Create event with 10 events per day for three days.
+  Event event1;
+  event1.set_name("event1");
+  test::SetEventCountForDay(&event1, 100u, 10u);
+  test::SetEventCountForDay(&event1, 101u, 10u);
+  test::SetEventCountForDay(&event1, 102u, 10u);
+  model_.SetEvent(event1);
+
+  EXPECT_TRUE(GetResultForDay(Comparator(LESS_THAN, 50u), window, current_day)
+                  .NoErrors());
+  EXPECT_TRUE(
+      GetResultForDay(Comparator(EQUAL, 30u), window, current_day).NoErrors());
+  EXPECT_FALSE(GetResultForDay(Comparator(LESS_THAN, 30u), window, current_day)
+                   .NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, SingleEventChangingWindow) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  Event event1;
+  event1.set_name("event1");
+  test::SetEventCountForDay(&event1, 100u, 10u);
+  test::SetEventCountForDay(&event1, 101u, 10u);
+  test::SetEventCountForDay(&event1, 102u, 10u);
+  test::SetEventCountForDay(&event1, 103u, 10u);
+  test::SetEventCountForDay(&event1, 104u, 10u);
+  model_.SetEvent(event1);
+
+  uint32_t current_day = 104u;
+
+  EXPECT_FALSE(GetResultForDay(Comparator(GREATER_THAN, 30u), 0, current_day)
+                   .NoErrors());
+  EXPECT_FALSE(GetResultForDay(Comparator(GREATER_THAN, 30u), 1u, current_day)
+                   .NoErrors());
+  EXPECT_FALSE(GetResultForDay(Comparator(GREATER_THAN, 30u), 2u, current_day)
+                   .NoErrors());
+  EXPECT_FALSE(GetResultForDay(Comparator(GREATER_THAN, 30u), 3u, current_day)
+                   .NoErrors());
+  EXPECT_TRUE(GetResultForDay(Comparator(GREATER_THAN, 30u), 4u, current_day)
+                  .NoErrors());
+  EXPECT_TRUE(GetResultForDay(Comparator(GREATER_THAN, 30u), 5u, current_day)
+                  .NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, CapEarliestAcceptedDayAtEpoch) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  Event event1;
+  event1.set_name("event1");
+  test::SetEventCountForDay(&event1, 0, 10u);
+  test::SetEventCountForDay(&event1, 1u, 10u);
+  test::SetEventCountForDay(&event1, 2u, 10u);
+  model_.SetEvent(event1);
+
+  uint32_t current_day = 100u;
+
+  EXPECT_TRUE(
+      GetResultForDay(Comparator(EQUAL, 10u), 99u, current_day).NoErrors());
+  EXPECT_TRUE(
+      GetResultForDay(Comparator(EQUAL, 20u), 100u, current_day).NoErrors());
+  EXPECT_TRUE(
+      GetResultForDay(Comparator(EQUAL, 30u), 101u, current_day).NoErrors());
+  EXPECT_TRUE(
+      GetResultForDay(Comparator(EQUAL, 30u), 1000u, current_day).NoErrors());
+}
+
+TEST_F(FeatureConfigConditionValidatorTest, TestMultipleEvents) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures({kTestFeatureFoo}, {});
+
+  Event event1;
+  event1.set_name("event1");
+  test::SetEventCountForDay(&event1, 0, 10u);
+  test::SetEventCountForDay(&event1, 1u, 10u);
+  test::SetEventCountForDay(&event1, 2u, 10u);
+  model_.SetEvent(event1);
+
+  Event event2;
+  event2.set_name("event2");
+  test::SetEventCountForDay(&event2, 0, 5u);
+  test::SetEventCountForDay(&event2, 1u, 5u);
+  test::SetEventCountForDay(&event2, 2u, 5u);
+  model_.SetEvent(event2);
+
+  uint32_t current_day = 100u;
+
+  // Verify validator counts correctly for two events last 99 days.
+  FeatureConfig config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 10u), 99u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 5u), 99u, 0));
+  ConditionValidator::Result result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_TRUE(result.NoErrors());
+
+  // Verify validator counts correctly for two events last 100 days.
+  config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 20u), 100u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 10u), 100u, 0));
+  result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_TRUE(result.NoErrors());
+
+  // Verify validator counts correctly for two events last 101 days.
+  config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 30u), 101u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 15u), 101u, 0));
+  result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_TRUE(result.NoErrors());
+
+  // Verify validator counts correctly for two events last 101 days, and returns
+  // error when first event fails.
+  config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 0), 101u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 15u), 101u, 0));
+  result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+
+  // Verify validator counts correctly for two events last 101 days, and returns
+  // error when second event fails.
+  config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 30u), 101u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 0), 101u, 0));
+  result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+
+  // Verify validator counts correctly for two events last 101 days, and returns
+  // error when both events fail.
+  config = GetAcceptingFeatureConfig();
+  config.event_configs.insert(
+      EventConfig("event1", Comparator(EQUAL, 0), 101u, 0));
+  config.event_configs.insert(
+      EventConfig("event2", Comparator(EQUAL, 0), 101u, 0));
+  result =
+      validator_.MeetsConditions(kTestFeatureFoo, config, model_, current_day);
+  EXPECT_FALSE(result.NoErrors());
+  EXPECT_FALSE(result.preconditions_ok);
+}
+
+}  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/feature_config_storage_validator.cc b/components/feature_engagement_tracker/internal/feature_config_storage_validator.cc
index 4cc0be74..5dc27e3 100644
--- a/components/feature_engagement_tracker/internal/feature_config_storage_validator.cc
+++ b/components/feature_engagement_tracker/internal/feature_config_storage_validator.cc
@@ -17,14 +17,15 @@
 
 FeatureConfigStorageValidator::~FeatureConfigStorageValidator() = default;
 
-bool FeatureConfigStorageValidator::ShouldStore(const std::string& event_name) {
+bool FeatureConfigStorageValidator::ShouldStore(
+    const std::string& event_name) const {
   return should_store_event_names_.find(event_name) !=
          should_store_event_names_.end();
 }
 
 bool FeatureConfigStorageValidator::ShouldKeep(const std::string& event_name,
                                                uint32_t event_day,
-                                               uint32_t current_day) {
+                                               uint32_t current_day) const {
   // Should not keep events that will happen in the future.
   if (event_day > current_day)
     return false;
diff --git a/components/feature_engagement_tracker/internal/feature_config_storage_validator.h b/components/feature_engagement_tracker/internal/feature_config_storage_validator.h
index c511548..c4a4fc55 100644
--- a/components/feature_engagement_tracker/internal/feature_config_storage_validator.h
+++ b/components/feature_engagement_tracker/internal/feature_config_storage_validator.h
@@ -25,10 +25,10 @@
   ~FeatureConfigStorageValidator() override;
 
   // StorageValidator implementation.
-  bool ShouldStore(const std::string& event_name) override;
+  bool ShouldStore(const std::string& event_name) const override;
   bool ShouldKeep(const std::string& event_name,
                   uint32_t event_day,
-                  uint32_t current_day) override;
+                  uint32_t current_day) const override;
 
   // Set up internal configuration required for the given |features|.
   void InitializeFeatures(FeatureVector features,
diff --git a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc b/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc
index 0be0a9f..a29976c 100644
--- a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc
+++ b/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc
@@ -95,7 +95,8 @@
                                        std::move(storage_validator));
   model_->Initialize(
       base::Bind(&FeatureEngagementTrackerImpl::OnModelInitializationFinished,
-                 weak_ptr_factory_.GetWeakPtr()));
+                 weak_ptr_factory_.GetWeakPtr()),
+      time_provider_->GetCurrentDay());
 }
 
 FeatureEngagementTrackerImpl::~FeatureEngagementTrackerImpl() = default;
diff --git a/components/feature_engagement_tracker/internal/in_memory_store.cc b/components/feature_engagement_tracker/internal/in_memory_store.cc
index 0c9fa6e4..2e78551 100644
--- a/components/feature_engagement_tracker/internal/in_memory_store.cc
+++ b/components/feature_engagement_tracker/internal/in_memory_store.cc
@@ -36,6 +36,10 @@
   // Intentionally ignore all writes.
 }
 
+void InMemoryStore::DeleteEvent(const std::string& event_name) {
+  // Intentionally ignore all deletes.
+}
+
 void InMemoryStore::HandleLoadResult(const OnLoadedCallback& callback,
                                      bool success) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/components/feature_engagement_tracker/internal/in_memory_store.h b/components/feature_engagement_tracker/internal/in_memory_store.h
index 939037c..45652d6 100644
--- a/components/feature_engagement_tracker/internal/in_memory_store.h
+++ b/components/feature_engagement_tracker/internal/in_memory_store.h
@@ -24,6 +24,7 @@
   void Load(const OnLoadedCallback& callback) override;
   bool IsReady() const override;
   void WriteEvent(const Event& event) override;
+  void DeleteEvent(const std::string& event_name) override;
 
  protected:
   // Posts the result of loading and sets up the ready state.
diff --git a/components/feature_engagement_tracker/internal/model.h b/components/feature_engagement_tracker/internal/model.h
index 47173238..3f73f44 100644
--- a/components/feature_engagement_tracker/internal/model.h
+++ b/components/feature_engagement_tracker/internal/model.h
@@ -25,7 +25,8 @@
 
   // Initialize the model, including all underlying sub systems. When all
   // required operations have been finished, a callback is posted.
-  virtual void Initialize(const OnModelInitializationFinished& callback) = 0;
+  virtual void Initialize(const OnModelInitializationFinished& callback,
+                          uint32_t current_day) = 0;
 
   // Returns whether the model is ready, i.e. whether it has been successfully
   // initialized.
diff --git a/components/feature_engagement_tracker/internal/model_impl.cc b/components/feature_engagement_tracker/internal/model_impl.cc
index e3bf8b3..9badfe3 100644
--- a/components/feature_engagement_tracker/internal/model_impl.cc
+++ b/components/feature_engagement_tracker/internal/model_impl.cc
@@ -30,9 +30,10 @@
 
 ModelImpl::~ModelImpl() = default;
 
-void ModelImpl::Initialize(const OnModelInitializationFinished& callback) {
+void ModelImpl::Initialize(const OnModelInitializationFinished& callback,
+                           uint32_t current_day) {
   store_->Load(base::Bind(&ModelImpl::OnStoreLoaded, weak_factory_.GetWeakPtr(),
-                          callback));
+                          callback, current_day));
 }
 
 bool ModelImpl::IsReady() const {
@@ -49,10 +50,12 @@
 
 void ModelImpl::IncrementEvent(const std::string& event_name,
                                uint32_t current_day) {
-  // TODO(nyquist): Add support for pending events, and also add UMA.
+  // TODO(nyquist): Add support for pending events.
+  // TODO(nyquist): Track this event in UMA.
   DCHECK(ready_);
 
-  // TODO(nyquist): Use StorageValidator to check if the event should be stored.
+  if (!storage_validator_->ShouldStore(event_name))
+    return;
 
   Event& event = GetNonConstEvent(event_name);
   for (int i = 0; i < event.events_size(); ++i) {
@@ -74,6 +77,7 @@
 }
 
 void ModelImpl::OnStoreLoaded(const OnModelInitializationFinished& callback,
+                              uint32_t current_day,
                               bool success,
                               std::unique_ptr<std::vector<Event>> events) {
   if (!success) {
@@ -84,10 +88,32 @@
 
   for (auto& event : *events) {
     DCHECK_NE("", event.name());
-    events_[event.name()] = event;
-  }
 
-  // TODO(nyquist): Use StorageValidator to only keep relevant event data.
+    Event new_event;
+    for (const auto& event_count : event.events()) {
+      if (!storage_validator_->ShouldKeep(event.name(), event_count.day(),
+                                          current_day)) {
+        continue;
+      }
+
+      Event_Count* new_event_count = new_event.add_events();
+      new_event_count->set_day(event_count.day());
+      new_event_count->set_count(event_count.count());
+    }
+
+    // Only keep Event object that have days with activity.
+    if (new_event.events_size() > 0) {
+      new_event.set_name(event.name());
+      events_[event.name()] = new_event;
+
+      // If the number of events is not the same, overwrite DB entry.
+      if (new_event.events_size() != event.events_size())
+        store_->WriteEvent(new_event);
+    } else {
+      // If there are no more activity for an Event, delete the whole event.
+      store_->DeleteEvent(event.name());
+    }
+  }
 
   ready_ = true;
 
diff --git a/components/feature_engagement_tracker/internal/model_impl.h b/components/feature_engagement_tracker/internal/model_impl.h
index 315cfbbc..adef3e0 100644
--- a/components/feature_engagement_tracker/internal/model_impl.h
+++ b/components/feature_engagement_tracker/internal/model_impl.h
@@ -27,7 +27,8 @@
   ~ModelImpl() override;
 
   // Model implementation.
-  void Initialize(const OnModelInitializationFinished& callback) override;
+  void Initialize(const OnModelInitializationFinished& callback,
+                  uint32_t current_day) override;
   bool IsReady() const override;
   const Event* GetEvent(const std::string& event_name) const override;
   void IncrementEvent(const std::string& event_name,
@@ -36,6 +37,7 @@
  private:
   // Callback for loading the underlying store.
   void OnStoreLoaded(const OnModelInitializationFinished& callback,
+                     uint32_t current_day,
                      bool success,
                      std::unique_ptr<std::vector<Event>> events);
 
diff --git a/components/feature_engagement_tracker/internal/model_impl_unittest.cc b/components/feature_engagement_tracker/internal/model_impl_unittest.cc
index 3a35ae5..49b85d77 100644
--- a/components/feature_engagement_tracker/internal/model_impl_unittest.cc
+++ b/components/feature_engagement_tracker/internal/model_impl_unittest.cc
@@ -27,9 +27,10 @@
 // WriteEvent(...).
 class TestInMemoryStore : public InMemoryStore {
  public:
-  explicit TestInMemoryStore(std::unique_ptr<std::vector<Event>> events,
-                             bool load_should_succeed)
+  TestInMemoryStore(std::unique_ptr<std::vector<Event>> events,
+                    bool load_should_succeed)
       : InMemoryStore(std::move(events)),
+        store_operation_count_(0),
         load_should_succeed_(load_should_succeed) {}
 
   void Load(const OnLoadedCallback& callback) override {
@@ -37,20 +38,67 @@
   }
 
   void WriteEvent(const Event& event) override {
+    ++store_operation_count_;
     last_written_event_.reset(new Event(event));
   }
 
+  void DeleteEvent(const std::string& event_name) override {
+    ++store_operation_count_;
+    last_deleted_event_ = event_name;
+  }
+
   const Event* GetLastWrittenEvent() { return last_written_event_.get(); }
 
+  const std::string GetLastDeletedEvent() { return last_deleted_event_; }
+
+  uint32_t GetStoreOperationCount() { return store_operation_count_; }
+
  private:
   // Temporary store the last written event.
   std::unique_ptr<Event> last_written_event_;
 
+  // Temporary store the last deleted event.
+  std::string last_deleted_event_;
+
+  // Tracks the number of operations performed on the store.
+  uint32_t store_operation_count_;
+
   // Denotes whether the call to Load(...) should succeed or not. This impacts
   // both the ready-state and the result for the OnLoadedCallback.
   bool load_should_succeed_;
 };
 
+class TestStorageValidator : public StorageValidator {
+ public:
+  TestStorageValidator() : should_store_(true) {}
+
+  bool ShouldStore(const std::string& event_name) const override {
+    return should_store_;
+  }
+
+  bool ShouldKeep(const std::string& event_name,
+                  uint32_t event_day,
+                  uint32_t current_day) const override {
+    auto search = max_keep_ages_.find(event_name);
+    if (search == max_keep_ages_.end())
+      return false;
+
+    return (current_day - event_day) < search->second;
+  }
+
+  void SetShouldStore(bool should_store) { should_store_ = should_store; }
+
+  void SetMaxKeepAge(const std::string& event_name, uint32_t age) {
+    max_keep_ages_[event_name] = age;
+  }
+
+ private:
+  bool should_store_;
+  std::map<std::string, uint32_t> max_keep_ages_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestStorageValidator);
+};
+
 // Creates a TestInMemoryStore containing three hard coded events.
 std::unique_ptr<TestInMemoryStore> CreatePrefilledStore() {
   std::unique_ptr<std::vector<Event>> events =
@@ -87,8 +135,15 @@
     std::unique_ptr<TestInMemoryStore> store = CreateStore();
     store_ = store.get();
 
-    model_.reset(new ModelImpl(std::move(store),
-                               base::MakeUnique<NeverStorageValidator>()));
+    auto storage_validator = base::MakeUnique<TestStorageValidator>();
+    storage_validator_ = storage_validator.get();
+
+    model_.reset(new ModelImpl(std::move(store), std::move(storage_validator)));
+
+    // By default store all events for a very long time.
+    storage_validator_->SetMaxKeepAge("foo", 10000u);
+    storage_validator_->SetMaxKeepAge("bar", 10000u);
+    storage_validator_->SetMaxKeepAge("qux", 10000u);
   }
 
   virtual std::unique_ptr<TestInMemoryStore> CreateStore() {
@@ -103,6 +158,7 @@
  protected:
   std::unique_ptr<ModelImpl> model_;
   TestInMemoryStore* store_;
+  TestStorageValidator* storage_validator_;
   bool got_initialize_callback_;
   bool initialize_callback_result_;
 
@@ -124,7 +180,8 @@
 
 TEST_F(ModelImplTest, InitializeShouldLoadEntries) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
   EXPECT_TRUE(got_initialize_callback_);
@@ -152,9 +209,54 @@
   test::VerifyEventCount(qux_event, 3u, 2u);
 }
 
+TEST_F(ModelImplTest, InitializeShouldOnlyLoadEntriesThatShouldBeKept) {
+  // Back to day 5, i.e. no entries.
+  storage_validator_->SetMaxKeepAge("foo", 1u);
+
+  // Back to day 2, i.e. 2 events.
+  storage_validator_->SetMaxKeepAge("bar", 4u);
+
+  // Back to day epoch, i.e. all events.
+  storage_validator_->SetMaxKeepAge("qux", 10u);
+
+  model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
+                                base::Unretained(this)),
+                     5u);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(model_->IsReady());
+  EXPECT_TRUE(got_initialize_callback_);
+  EXPECT_TRUE(initialize_callback_result_);
+
+  // Verify that all the data matches what was put into the store in
+  // CreateStore(), minus the events that should no longer exist.
+  const Event* foo_event = model_->GetEvent("foo");
+  EXPECT_EQ(nullptr, foo_event);
+  EXPECT_EQ("foo", store_->GetLastDeletedEvent());
+
+  const Event* bar_event = model_->GetEvent("bar");
+  EXPECT_EQ("bar", bar_event->name());
+  EXPECT_EQ(2, bar_event->events_size());
+  test::VerifyEventCount(bar_event, 2u, 3u);
+  test::VerifyEventCount(bar_event, 5u, 5u);
+  test::VerifyEventsEqual(bar_event, store_->GetLastWrittenEvent());
+
+  // Nothing has changed for 'qux', so nothing will be written to Store.
+  const Event* qux_event = model_->GetEvent("qux");
+  EXPECT_EQ("qux", qux_event->name());
+  EXPECT_EQ(3, qux_event->events_size());
+  test::VerifyEventCount(qux_event, 1u, 5u);
+  test::VerifyEventCount(qux_event, 2u, 1u);
+  test::VerifyEventCount(qux_event, 3u, 2u);
+
+  // In total, only two operations should have happened, the update of "bar",
+  // and the delete of "foo".
+  EXPECT_EQ(2u, store_->GetStoreOperationCount());
+}
+
 TEST_F(ModelImplTest, RetrievingNewEventsShouldYieldNullptr) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -165,13 +267,15 @@
 
 TEST_F(ModelImplTest, IncrementingNonExistingEvent) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
   // Incrementing the event should work even if it does not exist.
   model_->IncrementEvent("nonexisting", 1u);
   const Event* event1 = model_->GetEvent("nonexisting");
+  ASSERT_NE(nullptr, event1);
   EXPECT_EQ("nonexisting", event1->name());
   EXPECT_EQ(1, event1->events_size());
   test::VerifyEventCount(event1, 1u, 1u);
@@ -181,6 +285,7 @@
   // have a count of 2 for the given day.
   model_->IncrementEvent("nonexisting", 1u);
   const Event* event2 = model_->GetEvent("nonexisting");
+  ASSERT_NE(nullptr, event2);
   Event_Count event2_count = event2->events(0);
   EXPECT_EQ(1, event2->events_size());
   test::VerifyEventCount(event2, 1u, 2u);
@@ -189,7 +294,8 @@
 
 TEST_F(ModelImplTest, IncrementingNonExistingEventMultipleDays) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -198,6 +304,7 @@
   model_->IncrementEvent("nonexisting", 2u);
   model_->IncrementEvent("nonexisting", 3u);
   const Event* event = model_->GetEvent("nonexisting");
+  ASSERT_NE(nullptr, event);
   EXPECT_EQ(3, event->events_size());
   test::VerifyEventCount(event, 1u, 1u);
   test::VerifyEventCount(event, 2u, 2u);
@@ -205,9 +312,48 @@
   test::VerifyEventsEqual(event, store_->GetLastWrittenEvent());
 }
 
+TEST_F(ModelImplTest, IncrementingNonExistingEventWithoutStoring) {
+  model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
+                                base::Unretained(this)),
+                     1000u);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(model_->IsReady());
+
+  storage_validator_->SetShouldStore(false);
+
+  // Incrementing the event should not be written or stored in-memory.
+  model_->IncrementEvent("nonexisting", 1u);
+  const Event* event1 = model_->GetEvent("nonexisting");
+  EXPECT_EQ(nullptr, event1);
+  test::VerifyEventsEqual(nullptr, store_->GetLastWrittenEvent());
+}
+
+TEST_F(ModelImplTest, IncrementingExistingEventWithoutStoring) {
+  model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
+                                base::Unretained(this)),
+                     1000u);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(model_->IsReady());
+
+  // Write one event before turning off storage.
+  model_->IncrementEvent("nonexisting", 1u);
+  const Event* first_event = model_->GetEvent("nonexisting");
+  ASSERT_NE(nullptr, first_event);
+  test::VerifyEventsEqual(first_event, store_->GetLastWrittenEvent());
+
+  storage_validator_->SetShouldStore(false);
+
+  // Incrementing the event should no longer be written or stored in-memory.
+  model_->IncrementEvent("nonexisting", 1u);
+  const Event* second_event = model_->GetEvent("nonexisting");
+  EXPECT_EQ(first_event, second_event);
+  test::VerifyEventsEqual(first_event, store_->GetLastWrittenEvent());
+}
+
 TEST_F(ModelImplTest, IncrementingSingleDayExistingEvent) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -227,7 +373,8 @@
 
 TEST_F(ModelImplTest, IncrementingSingleDayExistingEventTwice) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -243,7 +390,8 @@
 
 TEST_F(ModelImplTest, IncrementingExistingMultiDayEvent) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -259,7 +407,8 @@
 
 TEST_F(ModelImplTest, IncrementingExistingMultiDayEventNewDay) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(model_->IsReady());
 
@@ -277,7 +426,8 @@
 
 TEST_F(LoadFailingModelImplTest, FailedInitializeInformsCaller) {
   model_->Initialize(base::Bind(&ModelImplTest::OnModelInitializationFinished,
-                                base::Unretained(this)));
+                                base::Unretained(this)),
+                     1000u);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(model_->IsReady());
   EXPECT_TRUE(got_initialize_callback_);
diff --git a/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc b/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc
index 7991302f1..04885ed 100644
--- a/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc
+++ b/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc
@@ -26,7 +26,8 @@
  public:
   TestModel() = default;
 
-  void Initialize(const OnModelInitializationFinished& callback) override {}
+  void Initialize(const OnModelInitializationFinished& callback,
+                  uint32_t current_day) override {}
 
   bool IsReady() const override { return true; }
 
diff --git a/components/feature_engagement_tracker/internal/never_storage_validator.cc b/components/feature_engagement_tracker/internal/never_storage_validator.cc
index cae38a0..c919dbc 100644
--- a/components/feature_engagement_tracker/internal/never_storage_validator.cc
+++ b/components/feature_engagement_tracker/internal/never_storage_validator.cc
@@ -10,13 +10,13 @@
 
 NeverStorageValidator::~NeverStorageValidator() = default;
 
-bool NeverStorageValidator::ShouldStore(const std::string& event_name) {
+bool NeverStorageValidator::ShouldStore(const std::string& event_name) const {
   return false;
 }
 
 bool NeverStorageValidator::ShouldKeep(const std::string& event_name,
                                        uint32_t event_day,
-                                       uint32_t current_day) {
+                                       uint32_t current_day) const {
   return false;
 }
 
diff --git a/components/feature_engagement_tracker/internal/never_storage_validator.h b/components/feature_engagement_tracker/internal/never_storage_validator.h
index 6dba3cc1..0194bf29 100644
--- a/components/feature_engagement_tracker/internal/never_storage_validator.h
+++ b/components/feature_engagement_tracker/internal/never_storage_validator.h
@@ -20,10 +20,10 @@
   ~NeverStorageValidator() override;
 
   // StorageValidator implementation.
-  bool ShouldStore(const std::string& event_name) override;
+  bool ShouldStore(const std::string& event_name) const override;
   bool ShouldKeep(const std::string& event_name,
                   uint32_t event_day,
-                  uint32_t current_day) override;
+                  uint32_t current_day) const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NeverStorageValidator);
diff --git a/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc b/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc
index cce2bf1..b505063 100644
--- a/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc
+++ b/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc
@@ -29,7 +29,8 @@
  public:
   TestModel() : ready_(false) { kValidFeatureConfig.valid = true; }
 
-  void Initialize(const OnModelInitializationFinished& callback) override {}
+  void Initialize(const OnModelInitializationFinished& callback,
+                  uint32_t current_day) override {}
 
   bool IsReady() const override { return ready_; }
 
diff --git a/components/feature_engagement_tracker/internal/persistent_store.cc b/components/feature_engagement_tracker/internal/persistent_store.cc
index 8841e05a..f884cb5c 100644
--- a/components/feature_engagement_tracker/internal/persistent_store.cc
+++ b/components/feature_engagement_tracker/internal/persistent_store.cc
@@ -54,6 +54,16 @@
                      base::Bind(&NoopUpdateCallback));
 }
 
+void PersistentStore::DeleteEvent(const std::string& event_name) {
+  DCHECK(IsReady());
+  auto deletes = base::MakeUnique<std::vector<std::string>>();
+  deletes->push_back(event_name);
+
+  // TODO(dtrainor, nyquist): Consider tracking failures here and storing UMA.
+  db_->UpdateEntries(base::MakeUnique<KeyEventList>(), std::move(deletes),
+                     base::Bind(&NoopUpdateCallback));
+}
+
 void PersistentStore::OnInitComplete(const OnLoadedCallback& callback,
                                      bool success) {
   if (!success) {
diff --git a/components/feature_engagement_tracker/internal/persistent_store.h b/components/feature_engagement_tracker/internal/persistent_store.h
index 3e259f0..bbbf0fc8 100644
--- a/components/feature_engagement_tracker/internal/persistent_store.h
+++ b/components/feature_engagement_tracker/internal/persistent_store.h
@@ -33,6 +33,7 @@
   void Load(const OnLoadedCallback& callback) override;
   bool IsReady() const override;
   void WriteEvent(const Event& event) override;
+  void DeleteEvent(const std::string& event_name) override;
 
  private:
   void OnInitComplete(const OnLoadedCallback& callback, bool success);
diff --git a/components/feature_engagement_tracker/internal/persistent_store_unittest.cc b/components/feature_engagement_tracker/internal/persistent_store_unittest.cc
index 4068662..92859504 100644
--- a/components/feature_engagement_tracker/internal/persistent_store_unittest.cc
+++ b/components/feature_engagement_tracker/internal/persistent_store_unittest.cc
@@ -190,4 +190,27 @@
   test::VerifyEventsEqual(&event, &it->second);
 }
 
+TEST_F(PersistentStoreTest, WriteAndDeleteEvent) {
+  SetUpDB();
+
+  store_->Load(load_callback_);
+  db_->InitCallback(true);
+  db_->LoadCallback(true);
+
+  Event event;
+  event.set_name("event");
+  test::SetEventCountForDay(&event, 1, 2);
+
+  store_->WriteEvent(event);
+  db_->UpdateCallback(true);
+
+  EXPECT_EQ(1U, db_events_.size());
+
+  store_->DeleteEvent("event");
+  db_->UpdateCallback(true);
+
+  const auto& it = db_events_.find("event");
+  EXPECT_EQ(db_events_.end(), it);
+}
+
 }  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/storage_validator.h b/components/feature_engagement_tracker/internal/storage_validator.h
index a8ef94d..15d2d3dc6 100644
--- a/components/feature_engagement_tracker/internal/storage_validator.h
+++ b/components/feature_engagement_tracker/internal/storage_validator.h
@@ -19,14 +19,14 @@
 
   // Returns true iff new events of this type should be stored.
   // This is typically called before storing each incoming event.
-  virtual bool ShouldStore(const std::string& event_name) = 0;
+  virtual bool ShouldStore(const std::string& event_name) const = 0;
 
   // Returns true iff events of this type should be kept for the given day.
   // This is typically called during load of the internal database state, to
   // possibly throw away old data.
   virtual bool ShouldKeep(const std::string& event_name,
                           uint32_t event_day,
-                          uint32_t current_day) = 0;
+                          uint32_t current_day) const = 0;
 
  protected:
   StorageValidator() = default;
diff --git a/components/feature_engagement_tracker/internal/store.h b/components/feature_engagement_tracker/internal/store.h
index cef9b460..cc546ad3e 100644
--- a/components/feature_engagement_tracker/internal/store.h
+++ b/components/feature_engagement_tracker/internal/store.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STORE_H_
 #define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STORE_H_
 
+#include <string>
+
 #include "base/callback.h"
 #include "base/macros.h"
 #include "components/feature_engagement_tracker/internal/proto/event.pb.h"
@@ -14,7 +16,6 @@
 // Store represents the storage engine behind the FeatureEngagementTracker.
 class Store {
  public:
-  // TODO(nyquist): Add vector of all events to result callback.
   using OnLoadedCallback =
       base::Callback<void(bool success, std::unique_ptr<std::vector<Event>>)>;
 
@@ -32,6 +33,9 @@
   // Stores the given event to persistent storage.
   virtual void WriteEvent(const Event& event) = 0;
 
+  // Deletes the event with the given name.
+  virtual void DeleteEvent(const std::string& event_name) = 0;
+
  protected:
   Store() = default;
 
diff --git a/components/gcm_driver/gcm_driver_desktop_unittest.cc b/components/gcm_driver/gcm_driver_desktop_unittest.cc
index ef83a49..099f273 100644
--- a/components/gcm_driver/gcm_driver_desktop_unittest.cc
+++ b/components/gcm_driver/gcm_driver_desktop_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/components/grpc_support/test/get_stream_engine.cc b/components/grpc_support/test/get_stream_engine.cc
index e447f7d..2d7837a 100644
--- a/components/grpc_support/test/get_stream_engine.cc
+++ b/components/grpc_support/test/get_stream_engine.cc
@@ -6,6 +6,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
diff --git a/components/grpc_support/test/quic_test_server.cc b/components/grpc_support/test/quic_test_server.cc
index b14530d0..6c8571f 100644
--- a/components/grpc_support/test/quic_test_server.cc
+++ b/components/grpc_support/test/quic_test_server.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/components/history/core/test/history_backend_db_base_test.cc b/components/history/core/test/history_backend_db_base_test.cc
index f9598584..36e9d5c 100644
--- a/components/history/core/test/history_backend_db_base_test.cc
+++ b/components/history/core/test/history_backend_db_base_test.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_path.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm b/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
index b54eaf9..27224a2a 100644
--- a/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
+++ b/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm b/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
index b83a127..29da4e9e 100644
--- a/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
+++ b/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc b/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
index 570b97f..7fc9dd90e 100644
--- a/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
+++ b/components/invalidation/impl/gcm_invalidation_bridge_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/invalidation/impl/non_blocking_invalidator_unittest.cc b/components/invalidation/impl/non_blocking_invalidator_unittest.cc
index 2aa6d6f..28c39ba3 100644
--- a/components/invalidation/impl/non_blocking_invalidator_unittest.cc
+++ b/components/invalidation/impl/non_blocking_invalidator_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "components/invalidation/impl/fake_invalidation_handler.h"
diff --git a/components/leveldb_proto/proto_database_impl_unittest.cc b/components/leveldb_proto/proto_database_impl_unittest.cc
index 50f8167..c198b50c 100644
--- a/components/leveldb_proto/proto_database_impl_unittest.cc
+++ b/components/leveldb_proto/proto_database_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "base/trace_event/memory_dump_manager.h"
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc
index 3a9b6d9..713d1edf 100644
--- a/components/nacl/loader/nacl_listener.cc
+++ b/components/nacl/loader/nacl_listener.cc
@@ -19,6 +19,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.cc b/components/nacl/loader/nonsfi/nonsfi_listener.cc
index b7a43aa..5f9b729 100644
--- a/components/nacl/loader/nonsfi/nonsfi_listener.cc
+++ b/components/nacl/loader/nonsfi/nonsfi_listener.cc
@@ -10,6 +10,7 @@
 #include "base/file_descriptor_posix.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
diff --git a/components/network_time/network_time_tracker_unittest.cc b/components/network_time/network_time_tracker_unittest.cc
index 899d190..07b52060 100644
--- a/components/network_time/network_time_tracker_unittest.cc
+++ b/components/network_time/network_time_tracker_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/ntp_tiles/popular_sites_impl_unittest.cc b/components/ntp_tiles/popular_sites_impl_unittest.cc
index 044a5d6d..661cc244 100644
--- a/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn
index 85d9fcb..98044bbc 100644
--- a/components/offline_pages/core/prefetch/BUILD.gn
+++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -5,16 +5,26 @@
 if (is_android) {
   import("//build/config/android/rules.gni")
 }
+import("//third_party/protobuf/proto_library.gni")
 
 static_library("prefetch") {
   sources = [
+    "generate_page_bundle_request.cc",
+    "generate_page_bundle_request.h",
     "prefetch_request_fetcher.cc",
     "prefetch_request_fetcher.h",
     "prefetch_service.h",
     "prefetch_service_impl.cc",
     "prefetch_service_impl.h",
+    "prefetch_types.cc",
+    "prefetch_types.h",
+    "prefetch_utils.cc",
+    "prefetch_utils.h",
   ]
 
+  public_deps = [
+    ":proto",
+  ]
   deps = [
     "//base",
     "//components/keyed_service/core",
@@ -24,10 +34,23 @@
   ]
 }
 
+proto_library("proto") {
+  sources = [
+    "proto/any.proto",
+    "proto/offline_pages.proto",
+    "proto/operation.proto",
+    "proto/status.proto",
+    "proto/timestamp.proto",
+  ]
+}
+
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "generate_page_bundle_request_unittest.cc",
     "prefetch_request_fetcher_unittest.cc",
+    "prefetch_request_test_base.cc",
+    "prefetch_request_test_base.h",
     "prefetch_service_impl_unittest.cc",
   ]
 
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc
new file mode 100644
index 0000000..1f2c173
--- /dev/null
+++ b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc
@@ -0,0 +1,115 @@
+// 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/offline_pages/core/prefetch/generate_page_bundle_request.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "components/offline_pages/core/prefetch/prefetch_request_fetcher.h"
+#include "components/offline_pages/core/prefetch/prefetch_utils.h"
+#include "components/offline_pages/core/prefetch/proto/offline_pages.pb.h"
+#include "components/offline_pages/core/prefetch/proto/operation.pb.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
+
+namespace offline_pages {
+
+namespace {
+// TODO(jianli): Update when server is ready.
+const GURL kOfflinePrefetchServiceUrl(
+    "http://localhost:12345/v1:GeneratePageBundle");
+}
+
+GeneratePageBundleRequest::GeneratePageBundleRequest(
+    const std::string& user_agent,
+    const std::string& gcm_registration_id,
+    int max_bundle_size_bytes,
+    const std::vector<std::string>& page_urls,
+    net::URLRequestContextGetter* request_context_getter,
+    const FinishedCallback& callback)
+    : callback_(callback) {
+  proto::GeneratePageBundleRequest request;
+  request.set_user_agent(user_agent);
+  request.set_max_bundle_size_bytes(max_bundle_size_bytes);
+  request.set_output_format(proto::FORMAT_MHTML);
+  request.set_gcm_registration_id(gcm_registration_id);
+
+  for (const auto& page_url : page_urls) {
+    proto::PageParameters* page = request.add_pages();
+    page->set_url(page_url);
+    page->set_transformation(proto::NO_TRANSFORMATION);
+  }
+
+  std::string upload_data;
+  request.SerializeToString(&upload_data);
+
+  fetcher_.reset(new PrefetchRequestFetcher(
+      kOfflinePrefetchServiceUrl, upload_data, request_context_getter,
+      base::Bind(&GeneratePageBundleRequest::OnCompleted,
+                 // Fetcher is owned by this instance.
+                 base::Unretained(this))));
+}
+
+GeneratePageBundleRequest::~GeneratePageBundleRequest() {}
+
+void GeneratePageBundleRequest::OnCompleted(PrefetchRequestStatus status,
+                                            const std::string& data) {
+  proto::Operation operation;
+  if (!operation.ParseFromString(data)) {
+    DVLOG(1) << "Failed to parse operation";
+    NotifyParsingFailure();
+    return;
+  }
+
+  if (operation.done())
+    ParseDoneOperationResponse(operation);
+  else
+    ParsePendingOperationResponse(operation);
+}
+
+void GeneratePageBundleRequest::ParseDoneOperationResponse(
+    const proto::Operation& operation) {
+  switch (operation.result_case()) {
+    case proto::Operation::kError:
+      DVLOG(1) << "Error found in operation";
+      NotifyParsingFailure();
+      break;
+    case proto::Operation::kResponse:
+      ParseAnyData(operation.response());
+      break;
+    default:
+      DVLOG(1) << "Result not set in operation";
+      NotifyParsingFailure();
+      break;
+  }
+}
+
+void GeneratePageBundleRequest::ParsePendingOperationResponse(
+    const proto::Operation& operation) {
+  if (!operation.has_metadata()) {
+    DVLOG(1) << "metadata not found in GeneratePageBundle response";
+    NotifyParsingFailure();
+    return;
+  }
+
+  ParseAnyData(operation.metadata());
+}
+
+void GeneratePageBundleRequest::ParseAnyData(const proto::Any& any_data) {
+  std::vector<RenderPageInfo> pages;
+  if (!ParsePageBundleInAnyData(any_data, &pages)) {
+    NotifyParsingFailure();
+    return;
+  }
+
+  callback_.Run(PrefetchRequestStatus::SUCCESS, pages);
+}
+
+void GeneratePageBundleRequest::NotifyParsingFailure() {
+  callback_.Run(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+                std::vector<RenderPageInfo>());
+}
+
+}  // offline_pages
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request.h b/components/offline_pages/core/prefetch/generate_page_bundle_request.h
new file mode 100644
index 0000000..4535049
--- /dev/null
+++ b/components/offline_pages/core/prefetch/generate_page_bundle_request.h
@@ -0,0 +1,57 @@
+// 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_OFFLINE_PAGES_CORE_PREFETCH_GENERATE_PAGE_BUNDLE_REQUEST_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_GENERATE_PAGE_BUNDLE_REQUEST_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace offline_pages {
+
+class PrefetchRequestFetcher;
+namespace proto {
+class Any;
+class Operation;
+}  // namespace proto
+
+class GeneratePageBundleRequest {
+ public:
+  using FinishedCallback =
+      base::Callback<void(PrefetchRequestStatus status,
+                          const std::vector<RenderPageInfo>& pages)>;
+
+  GeneratePageBundleRequest(
+      const std::string& user_agent,
+      const std::string& gcm_registration_id,
+      int max_bundle_size_bytes,
+      const std::vector<std::string>& page_urls,
+      net::URLRequestContextGetter* request_context_getter,
+      const FinishedCallback& callback);
+  ~GeneratePageBundleRequest();
+
+ private:
+  void OnCompleted(PrefetchRequestStatus status, const std::string& data);
+  void ParseDoneOperationResponse(const proto::Operation& operation);
+  void ParsePendingOperationResponse(const proto::Operation& operation);
+  void ParseAnyData(const proto::Any& any_data);
+  void NotifyParsingFailure();
+
+  FinishedCallback callback_;
+  std::unique_ptr<PrefetchRequestFetcher> fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(GeneratePageBundleRequest);
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_GENERATE_PAGE_BUNDLE_REQUEST_H_
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc
new file mode 100644
index 0000000..43853dcc
--- /dev/null
+++ b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc
@@ -0,0 +1,309 @@
+// 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/offline_pages/core/prefetch/generate_page_bundle_request.h"
+
+#include "base/test/mock_callback.h"
+#include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
+#include "components/offline_pages/core/prefetch/prefetch_utils.h"
+#include "components/offline_pages/core/prefetch/proto/offline_pages.pb.h"
+#include "components/offline_pages/core/prefetch/proto/operation.pb.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_request_status.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Eq;
+using testing::SaveArg;
+
+namespace offline_pages {
+
+namespace {
+const char kTestURL[] = "http://example.com";
+const char kTestURL2[] = "http://example.com/2";
+const char kTestURL3[] = "http://example.com/3";
+const char kTestURL4[] = "http://example.com/4";
+const char kTestUserAgent[] = "Test User Agent";
+const char kTestGCMID[] = "Test GCM ID";
+const int kTestMaxBundleSize = 100000;
+const char kTestBodyName[] = "body_name";
+const int64_t kTestBodyLength = 12345678LL;
+}  // namespace
+
+class OperationBuilder {
+ public:
+  virtual ~OperationBuilder() {}
+
+  // Builds the opereation with an Any value and returns it in binary serialized
+  // format.
+  virtual std::string BuildFromAny(const std::string& any_type_url,
+                                   const std::string& any_value) = 0;
+
+  // Builds the opereation with with an Any value filled with page bundle data
+  // and returns it in binary serialized format.
+  std::string BuildFromPageBundle(const proto::PageBundle& bundle) {
+    std::string bundle_data;
+    EXPECT_TRUE(bundle.SerializeToString(&bundle_data));
+    return BuildFromAny(kPageBundleTypeURL, bundle_data);
+  }
+
+ protected:
+  // Helper function to build the operation based on |is_done| that controls
+  // where Any value goes.
+  std::string BuildOperation(bool is_done,
+                             const std::string& any_type_url,
+                             const std::string& any_value) {
+    proto::Operation operation;
+    operation.set_done(is_done);
+    proto::Any* any =
+        is_done ? operation.mutable_response() : operation.mutable_metadata();
+    any->set_type_url(any_type_url);
+    any->set_value(any_value);
+    std::string data;
+    EXPECT_TRUE(operation.SerializeToString(&data));
+    return data;
+  }
+};
+
+class DoneOperationBuilder : public OperationBuilder {
+ public:
+  ~DoneOperationBuilder() override {}
+
+  std::string BuildFromAny(const std::string& any_type_url,
+                           const std::string& any_value) override {
+    return BuildOperation(true, any_type_url, any_value);
+  }
+};
+
+class PendingOperationBuilder : public OperationBuilder {
+ public:
+  ~PendingOperationBuilder() override {}
+
+  std::string BuildFromAny(const std::string& any_type_url,
+                           const std::string& any_value) override {
+    return BuildOperation(false, any_type_url, any_value);
+  }
+};
+
+class GeneratePageBundleRequestTest : public PrefetchRequestTestBase {
+ public:
+  // Sends GeneratePageBundleRequest for single page with |page_url| and
+  // gets back the data in |http_response|.
+  PrefetchRequestStatus GeneratePage(const std::string& page_url,
+                                     const std::string& http_response);
+
+  // Sends GeneratePageBundleRequest for multiple pages and  gets back the data
+  // in |http_response|.
+  PrefetchRequestStatus GenerateMultiplePages(
+      const std::vector<std::string>& page_urls,
+      const std::string& http_response);
+
+  const std::vector<RenderPageInfo>& pages() const { return pages_; }
+
+ private:
+  std::vector<RenderPageInfo> pages_;
+};
+
+PrefetchRequestStatus GeneratePageBundleRequestTest::GeneratePage(
+    const std::string& page_url,
+    const std::string& http_response) {
+  std::vector<std::string> page_urls;
+  page_urls.push_back(page_url);
+  return GenerateMultiplePages(page_urls, http_response);
+}
+
+PrefetchRequestStatus GeneratePageBundleRequestTest::GenerateMultiplePages(
+    const std::vector<std::string>& page_urls,
+    const std::string& http_response) {
+  base::MockCallback<GeneratePageBundleRequest::FinishedCallback> callback;
+  std::unique_ptr<GeneratePageBundleRequest> fetcher(
+      new GeneratePageBundleRequest(kTestUserAgent, kTestGCMID,
+                                    kTestMaxBundleSize, page_urls,
+                                    request_context(), callback.Get()));
+
+  PrefetchRequestStatus status;
+  pages_.clear();
+  EXPECT_CALL(callback, Run(_, _))
+      .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages_)));
+  RespondWithData(http_response);
+
+  return status;
+}
+
+TEST_F(GeneratePageBundleRequestTest, FailedToParse) {
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            GeneratePage(kTestURL, "Some data"));
+  EXPECT_TRUE(pages().empty());
+}
+
+TEST_F(GeneratePageBundleRequestTest, NoResultInDoneOperation) {
+  proto::Operation operation;
+  operation.set_done(true);
+  std::string data;
+  EXPECT_TRUE(operation.SerializeToString(&data));
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            GeneratePage(kTestURL, data));
+  EXPECT_TRUE(pages().empty());
+}
+
+TEST_F(GeneratePageBundleRequestTest, ErrorCodeInDoneOperation) {
+  proto::Operation operation;
+  operation.set_done(true);
+  operation.mutable_error()->set_code(1);
+  std::string data;
+  EXPECT_TRUE(operation.SerializeToString(&data));
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            GeneratePage(kTestURL, data));
+  EXPECT_TRUE(pages().empty());
+}
+
+template <typename T>
+class GeneratePageBundleRequestOperationTest
+    : public GeneratePageBundleRequestTest {
+ public:
+  std::string BuildFromAny(const std::string& any_type_url,
+                           const std::string& any_value) {
+    return builder_.BuildFromAny(any_type_url, any_value);
+  }
+
+  std::string BuildFromPageBundle(const proto::PageBundle& bundle) {
+    return builder_.BuildFromPageBundle(bundle);
+  }
+
+ private:
+  T builder_;
+};
+
+typedef testing::Types<DoneOperationBuilder, PendingOperationBuilder> MyTypes;
+TYPED_TEST_CASE(GeneratePageBundleRequestOperationTest, MyTypes);
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, InvalidTypeUrl) {
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL, this->BuildFromAny("foo", "")));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, InvalidValue) {
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL,
+                               this->BuildFromAny(kPageBundleTypeURL, "foo")));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, EmptyPageBundle) {
+  proto::PageBundle bundle;
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL, this->BuildFromPageBundle(bundle)));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, EmptyArchive) {
+  proto::PageBundle bundle;
+  bundle.add_archives();
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL, this->BuildFromPageBundle(bundle)));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, NoPageInfo) {
+  proto::PageBundle bundle;
+  proto::Archive* archive = bundle.add_archives();
+  archive->set_body_name(kTestBodyName);
+  archive->set_body_length(kTestBodyLength);
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL, this->BuildFromPageBundle(bundle)));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, MissingPageInfoUrl) {
+  proto::PageBundle bundle;
+  proto::Archive* archive = bundle.add_archives();
+  proto::PageInfo* page_info = archive->add_page_infos();
+  page_info->set_redirect_url(kTestURL);
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
+            this->GeneratePage(kTestURL, this->BuildFromPageBundle(bundle)));
+  EXPECT_TRUE(this->pages().empty());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, SinglePage) {
+  proto::PageBundle bundle;
+  proto::Archive* archive = bundle.add_archives();
+  archive->set_body_name(kTestBodyName);
+  archive->set_body_length(kTestBodyLength);
+  proto::PageInfo* page_info = archive->add_page_infos();
+  page_info->set_url(kTestURL);
+  page_info->set_redirect_url(kTestURL2);
+  page_info->mutable_status()->set_code(proto::OK);
+  page_info->set_transformation(proto::NO_TRANSFORMATION);
+  int64_t ms_since_epoch = base::Time::Now().ToJavaTime();
+  page_info->mutable_render_time()->set_seconds(ms_since_epoch / 1000);
+  page_info->mutable_render_time()->set_nanos((ms_since_epoch % 1000) *
+                                              1000000);
+  EXPECT_EQ(PrefetchRequestStatus::SUCCESS,
+            this->GeneratePage(kTestURL, this->BuildFromPageBundle(bundle)));
+  ASSERT_EQ(1u, this->pages().size());
+  EXPECT_EQ(kTestURL, this->pages().back().url);
+  EXPECT_EQ(kTestURL2, this->pages().back().redirect_url);
+  EXPECT_EQ(RenderStatus::RENDERED, this->pages().back().status);
+  EXPECT_EQ(kTestBodyName, this->pages().back().body_name);
+  EXPECT_EQ(kTestBodyLength, this->pages().back().body_length);
+  EXPECT_EQ(ms_since_epoch, this->pages().back().render_time.ToJavaTime());
+}
+
+TYPED_TEST(GeneratePageBundleRequestOperationTest, MultiplePages) {
+  proto::PageBundle bundle;
+
+  // Adds a page that is still being rendered.
+  proto::Archive* archive = bundle.add_archives();
+  proto::PageInfo* page_info = archive->add_page_infos();
+  page_info->set_url(kTestURL);
+  page_info->mutable_status()->set_code(proto::NOT_FOUND);
+
+  // Adds a page that failed to render due to bundle size limits.
+  archive = bundle.add_archives();
+  page_info = archive->add_page_infos();
+  page_info->set_url(kTestURL2);
+  page_info->mutable_status()->set_code(proto::FAILED_PRECONDITION);
+
+  // Adds a page that failed to render for any other reason.
+  archive = bundle.add_archives();
+  page_info = archive->add_page_infos();
+  page_info->set_url(kTestURL3);
+  page_info->mutable_status()->set_code(proto::UNKNOWN);
+
+  // Adds a page that was rendered successfully.
+  archive = bundle.add_archives();
+  archive->set_body_name(kTestBodyName);
+  archive->set_body_length(kTestBodyLength);
+  page_info = archive->add_page_infos();
+  page_info->set_url(kTestURL4);
+  page_info->mutable_status()->set_code(proto::OK);
+  page_info->set_transformation(proto::NO_TRANSFORMATION);
+  int64_t ms_since_epoch = base::Time::Now().ToJavaTime();
+  page_info->mutable_render_time()->set_seconds(ms_since_epoch / 1000);
+  page_info->mutable_render_time()->set_nanos((ms_since_epoch % 1000) *
+                                              1000000);
+
+  std::vector<std::string> page_urls = {kTestURL, kTestURL2, kTestURL3};
+  EXPECT_EQ(PrefetchRequestStatus::SUCCESS,
+            this->GenerateMultiplePages(page_urls,
+                                        this->BuildFromPageBundle(bundle)));
+  ASSERT_EQ(4u, this->pages().size());
+  EXPECT_EQ(kTestURL, this->pages().at(0).url);
+  EXPECT_EQ(RenderStatus::PENDING, this->pages().at(0).status);
+  EXPECT_EQ(kTestURL2, this->pages().at(1).url);
+  EXPECT_EQ(RenderStatus::EXCEEDED_LIMIT, this->pages().at(1).status);
+  EXPECT_EQ(kTestURL3, this->pages().at(2).url);
+  EXPECT_EQ(RenderStatus::FAILED, this->pages().at(2).status);
+  EXPECT_EQ(kTestURL4, this->pages().at(3).url);
+  EXPECT_EQ(RenderStatus::RENDERED, this->pages().at(3).status);
+  EXPECT_EQ(kTestBodyName, this->pages().at(3).body_name);
+  EXPECT_EQ(kTestBodyLength, this->pages().at(3).body_length);
+  EXPECT_EQ(ms_since_epoch, this->pages().at(3).render_time.ToJavaTime());
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc b/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
index 10e0de23..039faf1 100644
--- a/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
+++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
@@ -13,7 +13,7 @@
 #include "net/url_request/url_request_status.h"
 #include "url/gurl.h"
 
-namespace offline_prefetch {
+namespace offline_pages {
 
 namespace {
 const char kRequestContentType[] = "application/x-protobuf";
@@ -22,7 +22,7 @@
 PrefetchRequestFetcher::PrefetchRequestFetcher(
     const GURL& url,
     const std::string& message,
-    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+    net::URLRequestContextGetter* request_context_getter,
     const FinishedCallback& callback)
     : request_context_getter_(request_context_getter), callback_(callback) {
   net::NetworkTrafficAnnotationTag traffic_annotation =
@@ -61,22 +61,22 @@
 
 void PrefetchRequestFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
   std::string data;
-  Status status = ParseResponse(source, &data);
+  PrefetchRequestStatus status = ParseResponse(source, &data);
 
   // TODO(jianli): Report UMA.
 
   callback_.Run(status, data);
 }
 
-PrefetchRequestFetcher::Status PrefetchRequestFetcher::ParseResponse(
+PrefetchRequestStatus PrefetchRequestFetcher::ParseResponse(
     const net::URLFetcher* source,
     std::string* data) {
   if (!source->GetStatus().is_success()) {
     net::Error net_error = source->GetStatus().ToNetError();
     DVLOG(1) << "Net error: " << net_error;
     return (net_error == net::ERR_BLOCKED_BY_ADMINISTRATOR)
-               ? Status::SHOULD_SUSPEND
-               : Status::SHOULD_RETRY_WITHOUT_BACKOFF;
+               ? PrefetchRequestStatus::SHOULD_SUSPEND
+               : PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF;
   }
 
   net::HttpStatusCode response_status =
@@ -84,16 +84,16 @@
   if (response_status != net::HTTP_OK) {
     DVLOG(1) << "HTTP status: " << response_status;
     return (response_status == net::HTTP_NOT_IMPLEMENTED)
-               ? Status::SHOULD_SUSPEND
-               : Status::SHOULD_RETRY_WITH_BACKOFF;
+               ? PrefetchRequestStatus::SHOULD_SUSPEND
+               : PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF;
   }
 
   if (!source->GetResponseAsString(data) || data->empty()) {
     DVLOG(1) << "Failed to get response or empty response";
-    return Status::SHOULD_RETRY_WITH_BACKOFF;
+    return PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF;
   }
 
-  return Status::SUCCESS;
+  return PrefetchRequestStatus::SUCCESS;
 }
 
-}  // offline_prefetch
+}  // offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher.h b/components/offline_pages/core/prefetch/prefetch_request_fetcher.h
index 72a10b67..09c543ab 100644
--- a/components/offline_pages/core/prefetch/prefetch_request_fetcher.h
+++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
 #include "net/url_request/url_fetcher_delegate.h"
 
 class GURL;
@@ -15,41 +16,25 @@
 class URLRequestContextGetter;
 }
 
-namespace offline_prefetch {
+namespace offline_pages {
 
 class PrefetchRequestFetcher : public net::URLFetcherDelegate {
  public:
-  enum class Status {
-    // Request completed successfully.
-    SUCCESS,
-    // Request failed due to to local network problem, unrelated to server load
-    // levels. The caller will simply reschedule the retry in the next available
-    // WiFi window after 15 minutes have passed.
-    SHOULD_RETRY_WITHOUT_BACKOFF,
-    // Request failed probably related to transient server problems. The caller
-    // will reschedule the retry with backoff included.
-    SHOULD_RETRY_WITH_BACKOFF,
-    // Request failed with error indicating that the server no longer knows how
-    // to service a request. The caller will prevent network requests for the
-    // period of 1 day.
-    SHOULD_SUSPEND
-  };
+  using FinishedCallback = base::Callback<void(PrefetchRequestStatus status,
+                                               const std::string& data)>;
 
-  using FinishedCallback =
-      base::Callback<void(Status status, const std::string& data)>;
-
-  PrefetchRequestFetcher(
-      const GURL& url,
-      const std::string& message,
-      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
-      const FinishedCallback& callback);
+  PrefetchRequestFetcher(const GURL& url,
+                         const std::string& message,
+                         net::URLRequestContextGetter* request_context_getter,
+                         const FinishedCallback& callback);
   ~PrefetchRequestFetcher() override;
 
   // URLFetcherDelegate implementation.
   void OnURLFetchComplete(const net::URLFetcher* source) override;
 
  private:
-  Status ParseResponse(const net::URLFetcher* source, std::string* data);
+  PrefetchRequestStatus ParseResponse(const net::URLFetcher* source,
+                                      std::string* data);
 
   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
   std::unique_ptr<net::URLFetcher> url_fetcher_;
@@ -58,6 +43,6 @@
   DISALLOW_COPY_AND_ASSIGN(PrefetchRequestFetcher);
 };
 
-}  // namespace offline_prefetch
+}  // namespace offline_pages
 
 #endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
index 4ffe868..e5c5990 100644
--- a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
@@ -4,14 +4,12 @@
 
 #include "components/offline_pages/core/prefetch/prefetch_request_fetcher.h"
 
-#include "base/message_loop/message_loop.h"
 #include "base/test/mock_callback.h"
+#include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
 #include "net/http/http_status_code.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 using testing::_;
@@ -19,68 +17,28 @@
 using testing::Eq;
 using testing::SaveArg;
 
-namespace offline_prefetch {
+namespace offline_pages {
 
 namespace {
 const GURL kTestUrl("http://example.com");
 const char kTestMessage[] = "Testing";
 }  // namespace
 
-class PrefetchRequestFetcherTest : public testing::Test {
+class PrefetchRequestFetcherTest : public PrefetchRequestTestBase {
  public:
-  PrefetchRequestFetcherTest()
-      : request_context_(new net::TestURLRequestContextGetter(
-            base::ThreadTaskRunnerHandle::Get())) {}
-
-  PrefetchRequestFetcher::Status RunFetcherWithNetError(net::Error net_error);
-  PrefetchRequestFetcher::Status RunFetcherWithHttpError(int http_error);
-  PrefetchRequestFetcher::Status RunFetcherWithData(
-      const std::string& response_data,
-      std::string* data_received);
-
- private:
-  void RespondWithNetError(int net_error);
-  void RespondWithHttpError(int http_error);
-  void RespondWithData(const std::string& data);
-
-  base::MessageLoop message_loop_;
-  net::TestURLFetcherFactory url_fetcher_factory_;
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+  PrefetchRequestStatus RunFetcherWithNetError(net::Error net_error);
+  PrefetchRequestStatus RunFetcherWithHttpError(int http_error);
+  PrefetchRequestStatus RunFetcherWithData(const std::string& response_data,
+                                           std::string* data_received);
 };
 
-void PrefetchRequestFetcherTest::RespondWithNetError(int net_error) {
-  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
-  DCHECK(url_fetcher);
-  url_fetcher->set_status(net::URLRequestStatus::FromError(net_error));
-  url_fetcher->SetResponseString("");
-  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
-}
-
-void PrefetchRequestFetcherTest::RespondWithHttpError(int http_error) {
-  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
-  DCHECK(url_fetcher);
-  url_fetcher->set_status(net::URLRequestStatus());
-  url_fetcher->set_response_code(http_error);
-  url_fetcher->SetResponseString("");
-  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
-}
-
-void PrefetchRequestFetcherTest::RespondWithData(const std::string& data) {
-  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
-  DCHECK(url_fetcher);
-  url_fetcher->set_status(net::URLRequestStatus());
-  url_fetcher->set_response_code(net::HTTP_OK);
-  url_fetcher->SetResponseString(data);
-  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
-}
-
-PrefetchRequestFetcher::Status
-PrefetchRequestFetcherTest::RunFetcherWithNetError(net::Error net_error) {
+PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithNetError(
+    net::Error net_error) {
   base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback;
   std::unique_ptr<PrefetchRequestFetcher> fetcher(new PrefetchRequestFetcher(
-      kTestUrl, kTestMessage, request_context_, callback.Get()));
+      kTestUrl, kTestMessage, request_context(), callback.Get()));
 
-  PrefetchRequestFetcher::Status status;
+  PrefetchRequestStatus status;
   std::string data;
   EXPECT_CALL(callback, Run(_, _))
       .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&data)));
@@ -90,13 +48,13 @@
   return status;
 }
 
-PrefetchRequestFetcher::Status
-PrefetchRequestFetcherTest::RunFetcherWithHttpError(int http_error) {
+PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithHttpError(
+    int http_error) {
   base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback;
   std::unique_ptr<PrefetchRequestFetcher> fetcher(new PrefetchRequestFetcher(
-      kTestUrl, kTestMessage, request_context_, callback.Get()));
+      kTestUrl, kTestMessage, request_context(), callback.Get()));
 
-  PrefetchRequestFetcher::Status status;
+  PrefetchRequestStatus status;
   std::string data;
   EXPECT_CALL(callback, Run(_, _))
       .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&data)));
@@ -106,14 +64,14 @@
   return status;
 }
 
-PrefetchRequestFetcher::Status PrefetchRequestFetcherTest::RunFetcherWithData(
+PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithData(
     const std::string& response_data,
     std::string* data_received) {
   base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback;
   std::unique_ptr<PrefetchRequestFetcher> fetcher(new PrefetchRequestFetcher(
-      kTestUrl, kTestMessage, request_context_, callback.Get()));
+      kTestUrl, kTestMessage, request_context(), callback.Get()));
 
-  PrefetchRequestFetcher::Status status;
+  PrefetchRequestStatus status;
   std::string data;
   EXPECT_CALL(callback, Run(_, _))
       .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&data)));
@@ -124,55 +82,55 @@
 }
 
 TEST_F(PrefetchRequestFetcherTest, NetErrors) {
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_SUSPEND,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_SUSPEND,
             RunFetcherWithNetError(net::ERR_BLOCKED_BY_ADMINISTRATOR));
 
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITHOUT_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF,
             RunFetcherWithNetError(net::ERR_INTERNET_DISCONNECTED));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITHOUT_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF,
             RunFetcherWithNetError(net::ERR_NETWORK_CHANGED));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITHOUT_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF,
             RunFetcherWithNetError(net::ERR_CONNECTION_RESET));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITHOUT_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF,
             RunFetcherWithNetError(net::ERR_CONNECTION_CLOSED));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITHOUT_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF,
             RunFetcherWithNetError(net::ERR_CONNECTION_REFUSED));
 }
 
 TEST_F(PrefetchRequestFetcherTest, HttpErrors) {
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_SUSPEND,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_SUSPEND,
             RunFetcherWithHttpError(net::HTTP_NOT_IMPLEMENTED));
 
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_BAD_REQUEST));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_UNAUTHORIZED));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_NOT_FOUND));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_CONFLICT));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_INTERNAL_SERVER_ERROR));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_BAD_GATEWAY));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_SERVICE_UNAVAILABLE));
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithHttpError(net::HTTP_GATEWAY_TIMEOUT));
 }
 
 TEST_F(PrefetchRequestFetcherTest, EmptyResponse) {
   std::string data;
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SHOULD_RETRY_WITH_BACKOFF,
+  EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF,
             RunFetcherWithData("", &data));
   EXPECT_TRUE(data.empty());
 }
 
 TEST_F(PrefetchRequestFetcherTest, Success) {
   std::string data;
-  EXPECT_EQ(PrefetchRequestFetcher::Status::SUCCESS,
+  EXPECT_EQ(PrefetchRequestStatus::SUCCESS,
             RunFetcherWithData("Any data.", &data));
   EXPECT_FALSE(data.empty());
 }
 
-}  // namespace offline_prefetch
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_test_base.cc b/components/offline_pages/core/prefetch/prefetch_request_test_base.cc
new file mode 100644
index 0000000..d8f8a04
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_request_test_base.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace offline_pages {
+
+PrefetchRequestTestBase::PrefetchRequestTestBase()
+    : task_runner_(new base::TestSimpleTaskRunner),
+      task_runner_handle_(task_runner_),
+      request_context_(new net::TestURLRequestContextGetter(
+          base::ThreadTaskRunnerHandle::Get())) {}
+
+PrefetchRequestTestBase::~PrefetchRequestTestBase() {}
+
+void PrefetchRequestTestBase::RespondWithNetError(int net_error) {
+  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  DCHECK(url_fetcher);
+  url_fetcher->set_status(net::URLRequestStatus::FromError(net_error));
+  url_fetcher->SetResponseString("");
+  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
+}
+
+void PrefetchRequestTestBase::RespondWithHttpError(int http_error) {
+  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  DCHECK(url_fetcher);
+  url_fetcher->set_status(net::URLRequestStatus());
+  url_fetcher->set_response_code(http_error);
+  url_fetcher->SetResponseString("");
+  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
+}
+
+void PrefetchRequestTestBase::RespondWithData(const std::string& data) {
+  net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  DCHECK(url_fetcher);
+  url_fetcher->set_status(net::URLRequestStatus());
+  url_fetcher->set_response_code(net::HTTP_OK);
+  url_fetcher->SetResponseString(data);
+  url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_test_base.h b/components/offline_pages/core/prefetch/prefetch_request_test_base.h
new file mode 100644
index 0000000..516db7cc
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_request_test_base.h
@@ -0,0 +1,40 @@
+// 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_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace offline_pages {
+
+// Base class for testing prefetch requests with simulated responses.
+class PrefetchRequestTestBase : public testing::Test {
+ public:
+  PrefetchRequestTestBase();
+  ~PrefetchRequestTestBase() override;
+
+  void RespondWithNetError(int net_error);
+  void RespondWithHttpError(int http_error);
+  void RespondWithData(const std::string& data);
+
+  net::URLRequestContextGetter* request_context() const {
+    return request_context_.get();
+  }
+
+ private:
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle task_runner_handle_;
+  net::TestURLFetcherFactory url_fetcher_factory_;
+  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_types.cc b/components/offline_pages/core/prefetch/prefetch_types.cc
new file mode 100644
index 0000000..8f06ddd
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_types.cc
@@ -0,0 +1,13 @@
+// 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/offline_pages/core/prefetch/prefetch_types.h"
+
+namespace offline_pages {
+
+RenderPageInfo::RenderPageInfo() {}
+
+RenderPageInfo::RenderPageInfo(const RenderPageInfo& other) = default;
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h
new file mode 100644
index 0000000..98dc912
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -0,0 +1,64 @@
+// 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_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+
+namespace offline_pages {
+
+// Status for sending prefetch request to the server.
+enum class PrefetchRequestStatus {
+  // Request completed successfully.
+  SUCCESS,
+  // Request failed due to to local network problem, unrelated to server load
+  // levels. The caller will simply reschedule the retry in the next available
+  // WiFi window after 15 minutes have passed.
+  SHOULD_RETRY_WITHOUT_BACKOFF,
+  // Request failed probably related to transient server problems. The caller
+  // will reschedule the retry with backoff included.
+  SHOULD_RETRY_WITH_BACKOFF,
+  // Request failed with error indicating that the server no longer knows how
+  // to service a request. The caller will prevent network requests for the
+  // period of 1 day.
+  SHOULD_SUSPEND
+};
+
+// Status indicating the page rendering status in the server.
+enum class RenderStatus {
+  // The page is rendered.
+  RENDERED,
+  // The page is still being processed.
+  PENDING,
+  // The page failed to render.
+  FAILED,
+  // Failed due to bundle size limits.
+  EXCEEDED_LIMIT
+};
+
+// Information about the page rendered in the server.
+struct RenderPageInfo {
+  RenderPageInfo();
+  RenderPageInfo(const RenderPageInfo& other);
+
+  // The URL of the page that was rendered.
+  std::string url;
+  // The final URL after redirects. Empty if the final URL is url.
+  std::string redirect_url;
+  // Status of the render attempt.
+  RenderStatus status = RenderStatus::FAILED;
+  // Resource name for the body which can be read via the ByteStream API.
+  // Set only when |status| is RENDERED.
+  std::string body_name;
+  // Length of the body in bytes. Set only when |status| is RENDERED.
+  int64_t body_length = 0LL;
+  // Time the page was rendered. Set only when |status| is RENDERED.
+  base::Time render_time;
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
diff --git a/components/offline_pages/core/prefetch/prefetch_utils.cc b/components/offline_pages/core/prefetch/prefetch_utils.cc
new file mode 100644
index 0000000..9a25f78
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_utils.cc
@@ -0,0 +1,94 @@
+// 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/offline_pages/core/prefetch/prefetch_utils.h"
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "components/offline_pages/core/prefetch/proto/any.pb.h"
+#include "components/offline_pages/core/prefetch/proto/offline_pages.pb.h"
+
+namespace offline_pages {
+
+const char kPageBundleTypeURL[] =
+    "type.googleapis.com/chrome.offlinepages.v1.PageBundle";
+
+bool ParsePageBundleInAnyData(const proto::Any& any_data,
+                              std::vector<RenderPageInfo>* pages) {
+  if (any_data.type_url() != kPageBundleTypeURL) {
+    DVLOG(1) << "Wrong type url in any data";
+    return false;
+  }
+
+  proto::PageBundle page_bundle;
+  if (!page_bundle.ParseFromString(any_data.value())) {
+    DVLOG(1) << "Failed to parse PageBundle in any data";
+    return false;
+  }
+
+  if (!page_bundle.archives_size()) {
+    DVLOG(1) << "No archive in PageBundle";
+    return false;
+  }
+
+  for (int i = 0; i < page_bundle.archives_size(); ++i) {
+    const proto::Archive& archive = page_bundle.archives(i);
+
+    if (!archive.page_infos_size()) {
+      DVLOG(1) << "No page in archive";
+      return false;
+      ;
+    }
+
+    // Only one page is available in PageInfos.
+    const proto::PageInfo& page_info = archive.page_infos(0);
+
+    if (page_info.url().empty()) {
+      DVLOG(1) << "Empty page url";
+      return false;
+      ;
+    }
+
+    RenderPageInfo page;
+    page.url = page_info.url();
+    page.redirect_url = page_info.redirect_url();
+    if (page_info.has_status()) {
+      switch (page_info.status().code()) {
+        case proto::OK:
+          page.status = RenderStatus::RENDERED;
+          break;
+        case proto::NOT_FOUND:
+          page.status = RenderStatus::PENDING;
+          break;
+        case proto::FAILED_PRECONDITION:
+          page.status = RenderStatus::EXCEEDED_LIMIT;
+          break;
+        case proto::UNKNOWN:
+          page.status = RenderStatus::FAILED;
+          break;
+        default:
+          NOTREACHED();
+          break;
+      }
+    } else {
+      page.status = RenderStatus::RENDERED;
+    }
+
+    if (page.status == RenderStatus::RENDERED) {
+      page.body_name = archive.body_name();
+      page.body_length = archive.body_length();
+      page.render_time =
+          base::Time::FromJavaTime(page_info.render_time().seconds() * 1000 +
+                                   page_info.render_time().nanos() / 1000000);
+    }
+
+    DVLOG(1) << "Got page " << page.url << " " << static_cast<int>(page.status)
+             << " " << page.body_name << " " << page.body_length;
+    pages->push_back(page);
+  }
+
+  return true;
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_utils.h b/components/offline_pages/core/prefetch/prefetch_utils.h
new file mode 100644
index 0000000..caf6d85
--- /dev/null
+++ b/components/offline_pages/core/prefetch/prefetch_utils.h
@@ -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.
+
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_UTILS_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_UTILS_H_
+
+#include <vector>
+#include "components/offline_pages/core/prefetch/prefetch_types.h"
+
+namespace offline_pages {
+
+namespace proto {
+class Any;
+}  // namespace proto
+
+// The fully qualified type name for PageBundle defined in proto.
+extern const char kPageBundleTypeURL[];
+
+// Parse PageBundle data stored as Any proto data. True is returned when the
+// parsing succeeds and the result pages are stored in |pages|.
+bool ParsePageBundleInAnyData(const proto::Any& any_data,
+                              std::vector<RenderPageInfo>* pages);
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_UTILS_H_
diff --git a/components/offline_pages/core/prefetch/proto/any.proto b/components/offline_pages/core/prefetch/proto/any.proto
new file mode 100644
index 0000000..bc71002
--- /dev/null
+++ b/components/offline_pages/core/prefetch/proto/any.proto
@@ -0,0 +1,13 @@
+// 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.
+
+syntax = "proto3";
+option optimize_for = LITE_RUNTIME;
+
+package offline_pages.proto;
+
+message Any {
+  string type_url = 1;
+  bytes value = 2;
+}
diff --git a/components/offline_pages/core/prefetch/proto/offline_pages.proto b/components/offline_pages/core/prefetch/proto/offline_pages.proto
new file mode 100644
index 0000000..bffc766
--- /dev/null
+++ b/components/offline_pages/core/prefetch/proto/offline_pages.proto
@@ -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.
+
+syntax = "proto3";
+option optimize_for = LITE_RUNTIME;
+
+package offline_pages.proto;
+
+import "status.proto";
+import "timestamp.proto";
+
+// Type of transformation applied to a web page.
+enum Transformation {
+  // Transformation not specified.
+  TRANSFORMATION_UNSPECIFIED = 0;
+  // Minimal transformation required to provide an offline-accessible web page.
+  NO_TRANSFORMATION = 1;
+}
+
+// Page package format.
+enum OutputFormat {
+  // Format not specified.
+  FORMAT_UNSPECIFIED = 0;
+  // An MHTML archive containing a single web page.
+  FORMAT_MHTML = 1;
+}
+
+// Response to the GeneratePageBundle request.
+message PageBundle {
+  // The list of archives in the bundle. The distribution of pages into archives
+  // is arbitrary.
+  repeated Archive archives = 1;
+}
+
+// A resource containing one or more serialized offline pages.
+message Archive {
+  // Information about the individual page(s) used to create the Archive.
+  // There will be one PageInfo message for every page in the archive, including
+  // those that encountered an error or were elided due to size considerations.
+  repeated PageInfo page_infos = 1;
+  // Format of the body.
+  OutputFormat output_format = 2;
+  // Resource name for the body which can be read via the ByteStream API.
+  // This resource will remain available for a minimum of 24 hours after the
+  // GeneratePageBundle request.
+  string body_name = 3;
+  // Length of the body in bytes.
+  int64 body_length = 4;
+}
+
+// Information about a single returned offline page.
+message PageInfo {
+  // The URL of the page that was rendered.
+  string url = 1;
+  // The final URL after redirects. Empty if the final URL is url.
+  string redirect_url = 2;
+  // Status of the render attempt. If status.code != OK, fields below this will
+  // be unset. If the operation is still running, status is NotFound to
+  // indicate the page is still being processed.
+  // If the page was not returned due to bundle size limits, status is
+  // FailedPrecondition. If the page failed to render for any other reason,
+  // status is Unknown.
+  Status status = 3;
+  // Transformation that was applied to the page.
+  Transformation transformation = 4;
+  // Time the page was rendered.
+  Timestamp render_time = 5;
+}
+
+// Request to return a list of pages in a format suitable for offline viewing.
+message GeneratePageBundleRequest {
+  // The client's browser's user agent string.
+  string user_agent = 1;
+  // Preferred browser language(s) as defined by
+  // [IETF BCP 47](https://tools.ietf.org/html/bcp47).
+  repeated string browser_languages = 2;
+  // Desired format of the web page archive(s).
+  OutputFormat output_format = 3;
+  // Maximum size of the generated body. If all pages' output would exceed this
+  // size, only the first N pages are returned.
+  int64 max_bundle_size_bytes = 4;
+  // The GCM registration ID that can be used to inform the client
+  // of LRO completion.
+  string gcm_registration_id = 5;
+  // List of individual page requests, in order of priority. At most 100 pages
+  // may be requested at a time.
+  repeated PageParameters pages = 6;
+}
+
+// Request a set of pages to be returned in a format suitable for offline
+// viewing.
+message PageParameters {
+  // URL of the web page to return.
+  string url = 1;
+  // Transformation to apply. Must not be TRANSFORMATION_UNSPECIFIED.
+  Transformation transformation = 2;
+}
diff --git a/components/offline_pages/core/prefetch/proto/operation.proto b/components/offline_pages/core/prefetch/proto/operation.proto
new file mode 100644
index 0000000..77558d9f
--- /dev/null
+++ b/components/offline_pages/core/prefetch/proto/operation.proto
@@ -0,0 +1,42 @@
+// 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.
+
+syntax = "proto3";
+option optimize_for = LITE_RUNTIME;
+
+package offline_pages.proto;
+;
+
+import "any.proto";
+import "status.proto";
+
+// This resource represents a long-running operation that is the result of a
+// network API call.
+message Operation {
+  // The server-assigned name, which is only unique within the same service that
+  // originally returns it.
+  string name = 1;
+
+  // Service-specific metadata associated with the operation.  It typically
+  // contains progress information and common metadata such as create time.
+  // Some services might not provide such metadata.  Any method that returns a
+  // long-running operation should document the metadata type, if any.
+  Any metadata = 2;
+
+  // If the value is 'false', it means the operation is still in progress.
+  // If true, the operation is completed, and either 'error' or 'response' is
+  // available.
+  bool done = 3;
+
+  // The operation result, which can be either an 'error' or a valid 'response'.
+  // If 'done' == 'false', neither 'error' nor 'response' is set.
+  // If 'done' == 'true', exactly one of 'error' or 'response' is set.
+  oneof result {
+    // The error result of the operation in case of failure or cancellation.
+    Status error = 4;
+
+    // The normal response of the operation in case of success.
+    Any response = 5;
+  }
+}
\ No newline at end of file
diff --git a/components/offline_pages/core/prefetch/proto/status.proto b/components/offline_pages/core/prefetch/proto/status.proto
new file mode 100644
index 0000000..f7187993
--- /dev/null
+++ b/components/offline_pages/core/prefetch/proto/status.proto
@@ -0,0 +1,29 @@
+// 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.
+
+syntax = "proto3";
+option optimize_for = LITE_RUNTIME;
+
+package offline_pages.proto;
+
+import "any.proto";
+
+enum Code {
+  OK = 0;
+  UNKNOWN = 2;
+  NOT_FOUND = 5;
+  FAILED_PRECONDITION = 9;
+}
+
+message Status {
+  // The status code.
+  int32 code = 1;
+
+  // A developer-facing error message, which should be in English.
+  string message = 2;
+
+  // A list of messages that carry the error details.  There will be a
+  // common set of message types for APIs to use.
+  repeated Any details = 3;
+}
diff --git a/components/offline_pages/core/prefetch/proto/timestamp.proto b/components/offline_pages/core/prefetch/proto/timestamp.proto
new file mode 100644
index 0000000..c9658e7
--- /dev/null
+++ b/components/offline_pages/core/prefetch/proto/timestamp.proto
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+option optimize_for = LITE_RUNTIME;
+
+package offline_pages.proto;
+
+message Timestamp {
+  // Represents seconds of UTC time since Unix epoch
+  // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+  // 9999-12-31T23:59:59Z inclusive.
+  int64 seconds = 1;
+
+  // Non-negative fractions of a second at nanosecond resolution. Negative
+  // second values with fractions must still have non-negative nanos values
+  // that count forward in time. Must be from 0 to 999,999,999
+  // inclusive.
+  int32 nanos = 2;
+}
diff --git a/components/password_manager/content/browser/credential_manager_impl_unittest.cc b/components/password_manager/content/browser/credential_manager_impl_unittest.cc
index e47c595..3776496 100644
--- a/components/password_manager/content/browser/credential_manager_impl_unittest.cc
+++ b/components/password_manager/content/browser/credential_manager_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/location.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/string16.h"
diff --git a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
index 63ebc533..6ee8afd40 100644
--- a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
+++ b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index 8b54816..c47de36 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -15,6 +15,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/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/components/policy/core/common/cloud/cloud_policy_manager_unittest.cc b/components/policy/core/common/cloud/cloud_policy_manager_unittest.cc
index ad47f9a..dc71014f 100644
--- a/components/policy/core/common/cloud/cloud_policy_manager_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_manager_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
diff --git a/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc b/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
index 423d401..78b3a59 100644
--- a/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
+++ b/components/policy/core/common/cloud/component_cloud_policy_service_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/callback.h"
 #include "base/files/scoped_temp_dir.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/stl_util.h"
diff --git a/components/policy/core/common/cloud/device_management_service_unittest.cc b/components/policy/core/common/cloud/device_management_service_unittest.cc
index 64cf4aa..f31ea084 100644
--- a/components/policy/core/common/cloud/device_management_service_unittest.cc
+++ b/components/policy/core/common/cloud/device_management_service_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
diff --git a/components/policy/core/common/policy_loader_mac_unittest.cc b/components/policy/core/common/policy_loader_mac_unittest.cc
index a9d636f..f247941 100644
--- a/components/policy/core/common/policy_loader_mac_unittest.cc
+++ b/components/policy/core/common/policy_loader_mac_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/mac/scoped_cftyperef.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/strings/sys_string_conversions.h"
 #include "base/values.h"
diff --git a/components/policy/core/common/policy_service_impl_unittest.cc b/components/policy/core/common/policy_service_impl_unittest.cc
index db9e321..d781f990 100644
--- a/components/policy/core/common/policy_service_impl_unittest.cc
+++ b/components/policy/core/common/policy_service_impl_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/callback.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/values.h"
 #include "components/policy/core/common/external_data_fetcher.h"
diff --git a/components/safe_browsing/base_blocking_page.cc b/components/safe_browsing/base_blocking_page.cc
index 3f91702..3b047b9 100644
--- a/components/safe_browsing/base_blocking_page.cc
+++ b/components/safe_browsing/base_blocking_page.cc
@@ -12,13 +12,15 @@
 #include "components/safe_browsing_db/safe_browsing_prefs.h"
 #include "components/security_interstitials/content/security_interstitial_controller_client.h"
 #include "components/security_interstitials/core/metrics_helper.h"
+#include "components/security_interstitials/core/safe_browsing_loud_error_ui.h"
 #include "content/public/browser/interstitial_page.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 
 using content::InterstitialPage;
 using content::WebContents;
-using security_interstitials::SafeBrowsingErrorUI;
+using security_interstitials::BaseSafeBrowsingErrorUI;
+using security_interstitials::SafeBrowsingLoudErrorUI;
 using security_interstitials::SecurityInterstitialControllerClient;
 
 namespace safe_browsing {
@@ -42,7 +44,7 @@
     const GURL& main_frame_url,
     const UnsafeResourceList& unsafe_resources,
     std::unique_ptr<SecurityInterstitialControllerClient> controller_client,
-    const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
+    const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
     : SecurityInterstitialPage(web_contents,
                                unsafe_resources[0].url,
                                std::move(controller_client)),
@@ -53,7 +55,7 @@
               ? -1
               : web_contents->GetController().GetLastCommittedEntryIndex()),
       unsafe_resources_(unsafe_resources),
-      sb_error_ui_(base::MakeUnique<SafeBrowsingErrorUI>(
+      sb_error_ui_(base::MakeUnique<SafeBrowsingLoudErrorUI>(
           unsafe_resources_[0].url,
           main_frame_url_,
           GetInterstitialReason(unsafe_resources_),
@@ -68,10 +70,10 @@
 BaseBlockingPage::~BaseBlockingPage() {}
 
 // static
-const SafeBrowsingErrorUI::SBErrorDisplayOptions
+const security_interstitials::BaseSafeBrowsingErrorUI::SBErrorDisplayOptions
 BaseBlockingPage::CreateDefaultDisplayOptions(
     const UnsafeResourceList& unsafe_resources) {
-  return SafeBrowsingErrorUI::SBErrorDisplayOptions(
+  return BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
       IsMainPageLoadBlocked(unsafe_resources),
       false,  // kSafeBrowsingExtendedReportingOptInAllowed
       false,  // is_off_the_record
@@ -222,14 +224,14 @@
 // static
 std::string BaseBlockingPage::GetMetricPrefix(
     const UnsafeResourceList& unsafe_resources,
-    SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason) {
+    BaseSafeBrowsingErrorUI::SBInterstitialReason interstitial_reason) {
   bool primary_subresource = unsafe_resources[0].is_subresource;
   switch (interstitial_reason) {
-    case SafeBrowsingErrorUI::SB_REASON_MALWARE:
+    case BaseSafeBrowsingErrorUI::SB_REASON_MALWARE:
       return primary_subresource ? "malware_subresource" : "malware";
-    case SafeBrowsingErrorUI::SB_REASON_HARMFUL:
+    case BaseSafeBrowsingErrorUI::SB_REASON_HARMFUL:
       return primary_subresource ? "harmful_subresource" : "harmful";
-    case SafeBrowsingErrorUI::SB_REASON_PHISHING:
+    case BaseSafeBrowsingErrorUI::SB_REASON_PHISHING:
       ThreatPatternType threat_pattern_type =
           unsafe_resources[0].threat_metadata.threat_pattern_type;
       if (threat_pattern_type == ThreatPatternType::PHISHING ||
@@ -271,7 +273,7 @@
 }
 
 // static
-SafeBrowsingErrorUI::SBInterstitialReason
+security_interstitials::BaseSafeBrowsingErrorUI::SBInterstitialReason
 BaseBlockingPage::GetInterstitialReason(
     const UnsafeResourceList& unsafe_resources) {
   bool harmful = false;
@@ -281,7 +283,7 @@
     safe_browsing::SBThreatType threat_type = resource.threat_type;
     if (threat_type == SB_THREAT_TYPE_URL_MALWARE ||
         threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL) {
-      return SafeBrowsingErrorUI::SB_REASON_MALWARE;
+      return BaseSafeBrowsingErrorUI::SB_REASON_MALWARE;
     } else if (threat_type == SB_THREAT_TYPE_URL_UNWANTED) {
       harmful = true;
     } else {
@@ -291,8 +293,8 @@
   }
 
   if (harmful)
-    return SafeBrowsingErrorUI::SB_REASON_HARMFUL;
-  return SafeBrowsingErrorUI::SB_REASON_PHISHING;
+    return BaseSafeBrowsingErrorUI::SB_REASON_HARMFUL;
+  return BaseSafeBrowsingErrorUI::SB_REASON_PHISHING;
 }
 
 BaseUIManager* BaseBlockingPage::ui_manager() const {
@@ -308,7 +310,7 @@
   return unsafe_resources_;
 }
 
-SafeBrowsingErrorUI* BaseBlockingPage::sb_error_ui() const {
+BaseSafeBrowsingErrorUI* BaseBlockingPage::sb_error_ui() const {
   return sb_error_ui_.get();
 }
 
@@ -319,7 +321,7 @@
 // static
 security_interstitials::MetricsHelper::ReportDetails
 BaseBlockingPage::GetReportingInfo(const UnsafeResourceList& unsafe_resources) {
-  SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason =
+  BaseSafeBrowsingErrorUI::SBInterstitialReason interstitial_reason =
       GetInterstitialReason(unsafe_resources);
 
   security_interstitials::MetricsHelper::ReportDetails reporting_info;
diff --git a/components/safe_browsing/base_blocking_page.h b/components/safe_browsing/base_blocking_page.h
index ee73139..66c34e7 100644
--- a/components/safe_browsing/base_blocking_page.h
+++ b/components/safe_browsing/base_blocking_page.h
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "components/safe_browsing/base_ui_manager.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
 #include "components/security_interstitials/core/metrics_helper.h"
-#include "components/security_interstitials/core/safe_browsing_error_ui.h"
 #include "content/public/browser/interstitial_page_delegate.h"
 #include "url/gurl.h"
 
@@ -24,14 +24,15 @@
     : public security_interstitials::SecurityInterstitialPage {
  public:
   typedef security_interstitials::UnsafeResource UnsafeResource;
-  typedef security_interstitials::SafeBrowsingErrorUI SafeBrowsingErrorUI;
+  typedef security_interstitials::BaseSafeBrowsingErrorUI
+      BaseSafeBrowsingErrorUI;
   typedef std::vector<UnsafeResource> UnsafeResourceList;
   typedef std::unordered_map<content::WebContents*, UnsafeResourceList>
       UnsafeResourceMap;
 
   ~BaseBlockingPage() override;
 
-  static const SafeBrowsingErrorUI::SBErrorDisplayOptions
+  static const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions
   CreateDefaultDisplayOptions(const UnsafeResourceList& unsafe_resources);
 
   // Shows a blocking page warning the user about phishing/malware for a
@@ -61,7 +62,7 @@
       std::unique_ptr<
           security_interstitials::SecurityInterstitialControllerClient>
           controller_client,
-      const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options);
 
   // SecurityInterstitialPage methods:
   bool ShouldCreateNewNavigation() const override;
@@ -81,14 +82,14 @@
 
   static std::string GetMetricPrefix(
       const UnsafeResourceList& unsafe_resources,
-      SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason);
+      BaseSafeBrowsingErrorUI::SBInterstitialReason interstitial_reason);
 
   static std::string GetExtraMetricsSuffix(
       const UnsafeResourceList& unsafe_resources);
 
   // Return the most severe interstitial reason from a list of unsafe resources.
   // Severity ranking: malware > UwS (harmful) > phishing.
-  static SafeBrowsingErrorUI::SBInterstitialReason GetInterstitialReason(
+  static BaseSafeBrowsingErrorUI::SBInterstitialReason GetInterstitialReason(
       const UnsafeResourceList& unsafe_resources);
 
   BaseUIManager* ui_manager() const;
@@ -97,7 +98,7 @@
 
   UnsafeResourceList unsafe_resources() const;
 
-  SafeBrowsingErrorUI* sb_error_ui() const;
+  BaseSafeBrowsingErrorUI* sb_error_ui() const;
 
   void set_proceeded(bool proceeded);
 
@@ -131,7 +132,7 @@
   UnsafeResourceList unsafe_resources_;
 
   // For displaying safe browsing interstitial.
-  std::unique_ptr<SafeBrowsingErrorUI> sb_error_ui_;
+  std::unique_ptr<BaseSafeBrowsingErrorUI> sb_error_ui_;
 
   // Indicate whether user has proceeded this blocking page.
   bool proceeded_;
diff --git a/components/safe_browsing_db/v4_local_database_manager_unittest.cc b/components/safe_browsing_db/v4_local_database_manager_unittest.cc
index 595feec8..3d2eac5 100644
--- a/components/safe_browsing_db/v4_local_database_manager_unittest.cc
+++ b/components/safe_browsing_db/v4_local_database_manager_unittest.cc
@@ -6,6 +6,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/search_provider_logos/logo_tracker_unittest.cc b/components/search_provider_logos/logo_tracker_unittest.cc
index 7181eca4..926f485f 100644
--- a/components/search_provider_logos/logo_tracker_unittest.cc
+++ b/components/search_provider_logos/logo_tracker_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/security_interstitials/core/BUILD.gn b/components/security_interstitials/core/BUILD.gn
index 6970a43..f29f158c 100644
--- a/components/security_interstitials/core/BUILD.gn
+++ b/components/security_interstitials/core/BUILD.gn
@@ -6,14 +6,16 @@
   sources = [
     "bad_clock_ui.cc",
     "bad_clock_ui.h",
+    "base_safe_browsing_error_ui.cc",
+    "base_safe_browsing_error_ui.h",
     "common_string_util.cc",
     "common_string_util.h",
     "controller_client.cc",
     "controller_client.h",
     "metrics_helper.cc",
     "metrics_helper.h",
-    "safe_browsing_error_ui.cc",
-    "safe_browsing_error_ui.h",
+    "safe_browsing_loud_error_ui.cc",
+    "safe_browsing_loud_error_ui.h",
     "ssl_error_ui.cc",
     "ssl_error_ui.h",
   ]
diff --git a/components/security_interstitials/core/base_safe_browsing_error_ui.cc b/components/security_interstitials/core/base_safe_browsing_error_ui.cc
new file mode 100644
index 0000000..18be04292
--- /dev/null
+++ b/components/security_interstitials/core/base_safe_browsing_error_ui.cc
@@ -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.
+
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
+
+namespace security_interstitials {
+
+BaseSafeBrowsingErrorUI::BaseSafeBrowsingErrorUI(
+    const GURL& request_url,
+    const GURL& main_frame_url,
+    BaseSafeBrowsingErrorUI::SBInterstitialReason reason,
+    const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
+    const std::string& app_locale,
+    const base::Time& time_triggered,
+    ControllerClient* controller)
+    : request_url_(request_url),
+      main_frame_url_(main_frame_url),
+      interstitial_reason_(reason),
+      display_options_(display_options),
+      app_locale_(app_locale),
+      time_triggered_(time_triggered),
+      controller_(controller) {}
+
+BaseSafeBrowsingErrorUI::~BaseSafeBrowsingErrorUI() {}
+
+}  // security_interstitials
diff --git a/components/security_interstitials/core/safe_browsing_error_ui.h b/components/security_interstitials/core/base_safe_browsing_error_ui.h
similarity index 64%
rename from components/security_interstitials/core/safe_browsing_error_ui.h
rename to components/security_interstitials/core/base_safe_browsing_error_ui.h
index ed1a9058..02d2517 100644
--- a/components/security_interstitials/core/safe_browsing_error_ui.h
+++ b/components/security_interstitials/core/base_safe_browsing_error_ui.h
@@ -1,9 +1,9 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_ERROR_UI_H_
-#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_ERROR_UI_H_
+#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CORE_BASE_SAFE_BROWSING_ERROR_UI_H_
+#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_BASE_SAFE_BROWSING_ERROR_UI_H_
 
 #include "base/macros.h"
 #include "base/time/time.h"
@@ -13,10 +13,11 @@
 
 namespace security_interstitials {
 
+// A base class for quiet vs loud versions of the safe browsing interstitial.
 // This class displays UI for Safe Browsing errors that block page loads. This
 // class is purely about visual display; it does not do any error-handling logic
 // to determine what type of error should be displayed when.
-class SafeBrowsingErrorUI {
+class BaseSafeBrowsingErrorUI {
  public:
   enum SBInterstitialReason {
     SB_REASON_MALWARE,
@@ -64,22 +65,15 @@
     bool is_resource_cancellable;
   };
 
-  SafeBrowsingErrorUI(const GURL& request_url,
-                      const GURL& main_frame_url,
-                      SBInterstitialReason reason,
-                      const SBErrorDisplayOptions& display_options,
-                      const std::string& app_locale,
-                      const base::Time& time_triggered,
-                      ControllerClient* controller);
-  ~SafeBrowsingErrorUI();
-
-  void PopulateStringsForHTML(base::DictionaryValue* load_time_data);
-  void HandleCommand(SecurityInterstitialCommands command);
-
-  // Checks if we should even show the extended reporting option. We don't show
-  // it in incognito mode or if kSafeBrowsingExtendedReportingOptInAllowed
-  // preference is disabled.
-  bool CanShowExtendedReportingOption();
+  BaseSafeBrowsingErrorUI(
+      const GURL& request_url,
+      const GURL& main_frame_url,
+      BaseSafeBrowsingErrorUI::SBInterstitialReason reason,
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
+      const std::string& app_locale,
+      const base::Time& time_triggered,
+      ControllerClient* controller);
+  virtual ~BaseSafeBrowsingErrorUI();
 
   bool is_main_frame_load_blocked() const {
     return display_options_.is_main_frame_load_blocked;
@@ -89,30 +83,51 @@
     return display_options_.is_extended_reporting_opt_in_allowed;
   }
 
-  bool is_off_the_record() const {
-    return display_options_.is_off_the_record;
-  }
+  bool is_off_the_record() const { return display_options_.is_off_the_record; }
 
   bool is_extended_reporting_enabled() const {
     return display_options_.is_extended_reporting_enabled;
   }
 
+  void set_extended_reporting(bool pref) {
+    display_options_.is_extended_reporting_enabled = pref;
+  }
+
+  bool is_scout_reporting_enabled() const {
+    return display_options_.is_scout_reporting_enabled;
+  }
+
   bool is_proceed_anyway_disabled() const {
     return display_options_.is_proceed_anyway_disabled;
   }
 
-  const std::string app_locale() const {
-    return app_locale_;
+  bool is_resource_cancellable() const {
+    return display_options_.is_resource_cancellable;
   }
 
- private:
-  // Fills the passed dictionary with the values to be passed to the template
-  // when creating the HTML.
-  void PopulateExtendedReportingOption(base::DictionaryValue* load_time_data);
-  void PopulateMalwareLoadTimeData(base::DictionaryValue* load_time_data);
-  void PopulateHarmfulLoadTimeData(base::DictionaryValue* load_time_data);
-  void PopulatePhishingLoadTimeData(base::DictionaryValue* load_time_data);
+  // Checks if we should even show the extended reporting option. We don't show
+  // it in incognito mode or if kSafeBrowsingExtendedReportingOptInAllowed
+  // preference is disabled.
+  bool CanShowExtendedReportingOption() {
+    return !is_off_the_record() && is_extended_reporting_opt_in_allowed();
+  }
 
+  SBInterstitialReason interstitial_reason() const {
+    return interstitial_reason_;
+  }
+
+  const std::string app_locale() const { return app_locale_; }
+
+  ControllerClient* controller() { return controller_; };
+
+  GURL request_url() const { return request_url_; }
+  GURL main_frame_url() const { return main_frame_url_; }
+
+  virtual void PopulateStringsForHTML(
+      base::DictionaryValue* load_time_data) = 0;
+  virtual void HandleCommand(SecurityInterstitialCommands command) = 0;
+
+ private:
   const GURL request_url_;
   const GURL main_frame_url_;
   const SBInterstitialReason interstitial_reason_;
@@ -122,9 +137,9 @@
 
   ControllerClient* controller_;
 
-  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingErrorUI);
+  DISALLOW_COPY_AND_ASSIGN(BaseSafeBrowsingErrorUI);
 };
 
 }  // security_interstitials
 
-#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_ERROR_UI_H_
+#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CORE_BASE_SAFE_BROWSING_ERROR_UI_H_
diff --git a/components/security_interstitials/core/safe_browsing_error_ui.cc b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
similarity index 68%
rename from components/security_interstitials/core/safe_browsing_error_ui.cc
rename to components/security_interstitials/core/safe_browsing_loud_error_ui.cc
index 7b2ad57..8c0df9a 100644
--- a/components/security_interstitials/core/safe_browsing_error_ui.cc
+++ b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/security_interstitials/core/safe_browsing_error_ui.h"
+#include "components/security_interstitials/core/safe_browsing_loud_error_ui.h"
 
 #include "base/i18n/time_formatting.h"
 #include "base/metrics/histogram_macros.h"
@@ -19,7 +19,8 @@
 namespace {
 
 // URL for the Help Center article on Safe Browsing warnings.
-const char kLearnMore[] = "https://support.google.com/chrome/answer/99020";
+const char kLearnMore[] =
+    "https://support.google.com/chrome/?p=cpn_safe_browsing";
 
 // For malware interstitial pages, we link the problematic URL to Google's
 // diagnostic page.
@@ -50,7 +51,7 @@
 
 }  // namespace
 
-SafeBrowsingErrorUI::SafeBrowsingErrorUI(
+SafeBrowsingLoudErrorUI::SafeBrowsingLoudErrorUI(
     const GURL& request_url,
     const GURL& main_frame_url,
     SBInterstitialReason reason,
@@ -58,26 +59,26 @@
     const std::string& app_locale,
     const base::Time& time_triggered,
     ControllerClient* controller)
-    : request_url_(request_url),
-      main_frame_url_(main_frame_url),
-      interstitial_reason_(reason),
-      display_options_(display_options),
-      app_locale_(app_locale),
-      time_triggered_(time_triggered),
-      controller_(controller) {
-  controller_->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW);
-  controller_->metrics_helper()->RecordUserInteraction(
+    : BaseSafeBrowsingErrorUI(request_url,
+                              main_frame_url,
+                              reason,
+                              display_options,
+                              app_locale,
+                              time_triggered,
+                              controller) {
+  controller->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW);
+  controller->metrics_helper()->RecordUserInteraction(
       MetricsHelper::TOTAL_VISITS);
-  if (display_options_.is_proceed_anyway_disabled)
-    controller_->metrics_helper()->RecordUserDecision(
+  if (is_proceed_anyway_disabled())
+    controller->metrics_helper()->RecordUserDecision(
         security_interstitials::MetricsHelper::PROCEEDING_DISABLED);
 }
 
-SafeBrowsingErrorUI::~SafeBrowsingErrorUI() {
-  controller_->metrics_helper()->RecordShutdownMetrics();
+SafeBrowsingLoudErrorUI::~SafeBrowsingLoudErrorUI() {
+  controller()->metrics_helper()->RecordShutdownMetrics();
 }
 
-void SafeBrowsingErrorUI::PopulateStringsForHTML(
+void SafeBrowsingLoudErrorUI::PopulateStringsForHTML(
     base::DictionaryValue* load_time_data) {
   DCHECK(load_time_data);
 
@@ -93,18 +94,17 @@
   load_time_data->SetString(
       "primaryButtonText",
       l10n_util::GetStringUTF16(IDS_SAFEBROWSING_OVERRIDABLE_SAFETY_BUTTON));
-  load_time_data->SetBoolean("overridable",
-                             !display_options_.is_proceed_anyway_disabled);
-  load_time_data->SetBoolean("hide_primary_button", !controller_->CanGoBack());
+  load_time_data->SetBoolean("overridable", !is_proceed_anyway_disabled());
+  load_time_data->SetBoolean("hide_primary_button", !controller()->CanGoBack());
 
-  switch (interstitial_reason_) {
-    case SB_REASON_MALWARE:
+  switch (interstitial_reason()) {
+    case BaseSafeBrowsingErrorUI::SB_REASON_MALWARE:
       PopulateMalwareLoadTimeData(load_time_data);
       break;
-    case SB_REASON_HARMFUL:
+    case BaseSafeBrowsingErrorUI::SB_REASON_HARMFUL:
       PopulateHarmfulLoadTimeData(load_time_data);
       break;
-    case SB_REASON_PHISHING:
+    case BaseSafeBrowsingErrorUI::SB_REASON_PHISHING:
       PopulatePhishingLoadTimeData(load_time_data);
       break;
   }
@@ -112,14 +112,15 @@
   PopulateExtendedReportingOption(load_time_data);
 }
 
-void SafeBrowsingErrorUI::HandleCommand(SecurityInterstitialCommands command) {
+void SafeBrowsingLoudErrorUI::HandleCommand(
+    SecurityInterstitialCommands command) {
   switch (command) {
     case CMD_PROCEED: {
       // User pressed on the button to proceed.
-      if (!display_options_.is_proceed_anyway_disabled) {
-        controller_->metrics_helper()->RecordUserDecision(
+      if (!is_proceed_anyway_disabled()) {
+        controller()->metrics_helper()->RecordUserDecision(
             MetricsHelper::PROCEED);
-        controller_->Proceed();
+        controller()->Proceed();
         break;
       }
     }
@@ -128,83 +129,81 @@
       // User pressed on the button to return to safety.
       // Don't record the user action here because there are other ways of
       // triggering DontProceed, like clicking the back button.
-      if (display_options_.is_resource_cancellable) {
+      if (is_resource_cancellable()) {
         // If the load is blocked, we want to close the interstitial and discard
         // the pending entry.
-        controller_->GoBack();
+        controller()->GoBack();
       } else {
         // Otherwise the offending entry has committed, and we need to go back
         // or to a safe page.  We will close the interstitial when that page
         // commits.
-        controller_->GoBackAfterNavigationCommitted();
+        controller()->GoBackAfterNavigationCommitted();
       }
       break;
     }
     case CMD_DO_REPORT: {
       // User enabled SB Extended Reporting via the checkbox.
-      display_options_.is_extended_reporting_enabled = true;
-      controller_->SetReportingPreference(true);
-      RecordExtendedReportingPrefChanged(
-          true, display_options_.is_scout_reporting_enabled);
+      set_extended_reporting(true);
+      controller()->SetReportingPreference(true);
+      RecordExtendedReportingPrefChanged(true, is_scout_reporting_enabled());
       break;
     }
     case CMD_DONT_REPORT: {
       // User disabled SB Extended Reporting via the checkbox.
-      display_options_.is_extended_reporting_enabled = false;
-      controller_->SetReportingPreference(false);
-      RecordExtendedReportingPrefChanged(
-          false, display_options_.is_scout_reporting_enabled);
+      set_extended_reporting(false);
+      controller()->SetReportingPreference(false);
+      RecordExtendedReportingPrefChanged(false, is_scout_reporting_enabled());
       break;
     }
     case CMD_SHOW_MORE_SECTION: {
-      controller_->metrics_helper()->RecordUserInteraction(
+      controller()->metrics_helper()->RecordUserInteraction(
           security_interstitials::MetricsHelper::SHOW_ADVANCED);
       break;
     }
     case CMD_OPEN_HELP_CENTER: {
       // User pressed "Learn more".
-      controller_->metrics_helper()->RecordUserInteraction(
+      controller()->metrics_helper()->RecordUserInteraction(
           security_interstitials::MetricsHelper::SHOW_LEARN_MORE);
       GURL learn_more_url(kLearnMore);
       learn_more_url =
-          google_util::AppendGoogleLocaleParam(learn_more_url, app_locale_);
-      controller_->OpenUrlInCurrentTab(learn_more_url);
+          google_util::AppendGoogleLocaleParam(learn_more_url, app_locale());
+      controller()->OpenUrlInCurrentTab(learn_more_url);
       break;
     }
     case CMD_RELOAD: {
-      controller_->metrics_helper()->RecordUserInteraction(
+      controller()->metrics_helper()->RecordUserInteraction(
           security_interstitials::MetricsHelper::RELOAD);
-      controller_->Reload();
+      controller()->Reload();
       break;
     }
     case CMD_OPEN_REPORTING_PRIVACY: {
       // User pressed on the SB Extended Reporting "privacy policy" link.
-      controller_->OpenExtendedReportingPrivacyPolicy();
+      controller()->OpenExtendedReportingPrivacyPolicy();
       break;
     }
     case CMD_OPEN_WHITEPAPER: {
-      controller_->OpenExtendedReportingWhitepaper();
+      controller()->OpenExtendedReportingWhitepaper();
       break;
     }
     case CMD_OPEN_DIAGNOSTIC: {
-      controller_->metrics_helper()->RecordUserInteraction(
+      controller()->metrics_helper()->RecordUserInteraction(
           security_interstitials::MetricsHelper::SHOW_DIAGNOSTIC);
       std::string diagnostic = base::StringPrintf(
           kSbDiagnosticUrl,
-          net::EscapeQueryParamValue(request_url_.spec(), true).c_str());
+          net::EscapeQueryParamValue(request_url().spec(), true).c_str());
       GURL diagnostic_url(diagnostic);
       diagnostic_url =
-          google_util::AppendGoogleLocaleParam(diagnostic_url, app_locale_);
-      controller_->OpenUrlInCurrentTab(diagnostic_url);
+          google_util::AppendGoogleLocaleParam(diagnostic_url, app_locale());
+      controller()->OpenUrlInCurrentTab(diagnostic_url);
       break;
     }
     case CMD_REPORT_PHISHING_ERROR: {
-      controller_->metrics_helper()->RecordUserInteraction(
+      controller()->metrics_helper()->RecordUserInteraction(
           security_interstitials::MetricsHelper::REPORT_PHISHING_ERROR);
       GURL phishing_error_url(kReportPhishingErrorUrl);
-      phishing_error_url =
-          google_util::AppendGoogleLocaleParam(phishing_error_url, app_locale_);
-      controller_->OpenUrlInCurrentTab(phishing_error_url);
+      phishing_error_url = google_util::AppendGoogleLocaleParam(
+          phishing_error_url, app_locale());
+      controller()->OpenUrlInCurrentTab(phishing_error_url);
       break;
     }
     case CMD_OPEN_DATE_SETTINGS:
@@ -216,11 +215,7 @@
   }
 }
 
-bool SafeBrowsingErrorUI::CanShowExtendedReportingOption() {
-  return !is_off_the_record() && is_extended_reporting_opt_in_allowed();
-}
-
-void SafeBrowsingErrorUI::PopulateMalwareLoadTimeData(
+void SafeBrowsingLoudErrorUI::PopulateMalwareLoadTimeData(
     base::DictionaryValue* load_time_data) {
   load_time_data->SetBoolean("phishing", false);
   load_time_data->SetString("heading",
@@ -229,23 +224,23 @@
       "primaryParagraph",
       l10n_util::GetStringFUTF16(
           IDS_MALWARE_V3_PRIMARY_PARAGRAPH,
-          common_string_util::GetFormattedHostName(request_url_)));
+          common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "explanationParagraph",
-      display_options_.is_main_frame_load_blocked
+      is_main_frame_load_blocked()
           ? l10n_util::GetStringFUTF16(
                 IDS_MALWARE_V3_EXPLANATION_PARAGRAPH,
-                common_string_util::GetFormattedHostName(request_url_))
+                common_string_util::GetFormattedHostName(request_url()))
           : l10n_util::GetStringFUTF16(
                 IDS_MALWARE_V3_EXPLANATION_PARAGRAPH_SUBRESOURCE,
-                base::UTF8ToUTF16(main_frame_url_.host()),
-                common_string_util::GetFormattedHostName(request_url_)));
+                base::UTF8ToUTF16(main_frame_url().host()),
+                common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "finalParagraph",
       l10n_util::GetStringUTF16(IDS_MALWARE_V3_PROCEED_PARAGRAPH));
 }
 
-void SafeBrowsingErrorUI::PopulateHarmfulLoadTimeData(
+void SafeBrowsingLoudErrorUI::PopulateHarmfulLoadTimeData(
     base::DictionaryValue* load_time_data) {
   load_time_data->SetBoolean("phishing", false);
   load_time_data->SetString("heading",
@@ -254,18 +249,18 @@
       "primaryParagraph",
       l10n_util::GetStringFUTF16(
           IDS_HARMFUL_V3_PRIMARY_PARAGRAPH,
-          common_string_util::GetFormattedHostName(request_url_)));
+          common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "explanationParagraph",
       l10n_util::GetStringFUTF16(
           IDS_HARMFUL_V3_EXPLANATION_PARAGRAPH,
-          common_string_util::GetFormattedHostName(request_url_)));
+          common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "finalParagraph",
       l10n_util::GetStringUTF16(IDS_HARMFUL_V3_PROCEED_PARAGRAPH));
 }
 
-void SafeBrowsingErrorUI::PopulatePhishingLoadTimeData(
+void SafeBrowsingLoudErrorUI::PopulatePhishingLoadTimeData(
     base::DictionaryValue* load_time_data) {
   load_time_data->SetBoolean("phishing", true);
   load_time_data->SetString("heading",
@@ -274,18 +269,18 @@
       "primaryParagraph",
       l10n_util::GetStringFUTF16(
           IDS_PHISHING_V4_PRIMARY_PARAGRAPH,
-          common_string_util::GetFormattedHostName(request_url_)));
+          common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "explanationParagraph",
       l10n_util::GetStringFUTF16(
           IDS_PHISHING_V4_EXPLANATION_PARAGRAPH,
-          common_string_util::GetFormattedHostName(request_url_)));
+          common_string_util::GetFormattedHostName(request_url())));
   load_time_data->SetString(
       "finalParagraph",
       l10n_util::GetStringUTF16(IDS_PHISHING_V4_PROCEED_AND_REPORT_PARAGRAPH));
 }
 
-void SafeBrowsingErrorUI::PopulateExtendedReportingOption(
+void SafeBrowsingLoudErrorUI::PopulateExtendedReportingOption(
     base::DictionaryValue* load_time_data) {
   bool can_show_extended_reporting_option = CanShowExtendedReportingOption();
   load_time_data->SetBoolean(security_interstitials::kDisplayCheckBox,
@@ -299,12 +294,12 @@
       l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
   load_time_data->SetString(security_interstitials::kOptInLink,
                             l10n_util::GetStringFUTF16(
-                                display_options_.is_scout_reporting_enabled
+                                is_scout_reporting_enabled()
                                     ? IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE
                                     : IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
                                 base::UTF8ToUTF16(privacy_link)));
   load_time_data->SetBoolean(security_interstitials::kBoxChecked,
-                             display_options_.is_extended_reporting_enabled);
+                             is_extended_reporting_enabled());
 }
 
 }  // security_interstitials
diff --git a/components/security_interstitials/core/safe_browsing_loud_error_ui.h b/components/security_interstitials/core/safe_browsing_loud_error_ui.h
new file mode 100644
index 0000000..c90391a
--- /dev/null
+++ b/components/security_interstitials/core/safe_browsing_loud_error_ui.h
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_LOUD_ERROR_UI_H_
+#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_LOUD_ERROR_UI_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
+#include "components/security_interstitials/core/controller_client.h"
+#include "url/gurl.h"
+
+namespace security_interstitials {
+
+// Loud version of the safe browsing interstitial. This is the full screen
+// version of the interstitial used on Desktop, Android and iOS. It is
+// selectively used in parts of WebView.
+// This class displays UI for Safe Browsing errors that block page loads. This
+// class is purely about visual display; it does not do any error-handling logic
+// to determine what type of error should be displayed when.
+class SafeBrowsingLoudErrorUI
+    : public security_interstitials::BaseSafeBrowsingErrorUI {
+ public:
+  SafeBrowsingLoudErrorUI(
+      const GURL& request_url,
+      const GURL& main_frame_url,
+      BaseSafeBrowsingErrorUI::SBInterstitialReason reason,
+      const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
+      const std::string& app_locale,
+      const base::Time& time_triggered,
+      ControllerClient* controller);
+
+  ~SafeBrowsingLoudErrorUI() override;
+
+  // Implement BaseSafeBrowsingErrorUI.
+  void PopulateStringsForHTML(base::DictionaryValue* load_time_data) override;
+  void HandleCommand(SecurityInterstitialCommands command) override;
+
+ private:
+  // Fills the passed dictionary with the values to be passed to the template
+  // when creating the HTML.
+  void PopulateExtendedReportingOption(base::DictionaryValue* load_time_data);
+  void PopulateMalwareLoadTimeData(base::DictionaryValue* load_time_data);
+  void PopulateHarmfulLoadTimeData(base::DictionaryValue* load_time_data);
+  void PopulatePhishingLoadTimeData(base::DictionaryValue* load_time_data);
+
+  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingLoudErrorUI);
+};
+
+}  // security_interstitials
+
+#endif  // COMPONENTS_SECURITY_INTERSTITIALS_CORE_SAFE_BROWSING_LOUD_ERROR_UI_H_
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
index d70d591..a4043b3 100644
--- a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
@@ -5,6 +5,7 @@
 #include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/components/storage_monitor/media_storage_util_unittest.cc b/components/storage_monitor/media_storage_util_unittest.cc
index 5b895a870..b478bf7 100644
--- a/components/storage_monitor/media_storage_util_unittest.cc
+++ b/components/storage_monitor/media_storage_util_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index 5ffb3f8..e644d276 100644
--- a/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
diff --git a/components/storage_monitor/storage_monitor_linux_unittest.cc b/components/storage_monitor/storage_monitor_linux_unittest.cc
index 769d46e..7c3b223c 100644
--- a/components/storage_monitor/storage_monitor_linux_unittest.cc
+++ b/components/storage_monitor/storage_monitor_linux_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
index 7fcb8fa..9b06df8 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
index bf02f83..7e6a426 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
index 5e123381..3d621de 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index 8e0954e..7aa45beb5 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind.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/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/components/sync/driver/shared_change_processor_unittest.cc b/components/sync/driver/shared_change_processor_unittest.cc
index b6494049..d13805f 100644
--- a/components/sync/driver/shared_change_processor_unittest.cc
+++ b/components/sync/driver/shared_change_processor_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "components/sync/base/model_type.h"
diff --git a/components/sync/engine/attachments/attachment_store_test_template.h b/components/sync/engine/attachments/attachment_store_test_template.h
index b3d6422d..b047934c 100644
--- a/components/sync/engine/attachments/attachment_store_test_template.h
+++ b/components/sync/engine/attachments/attachment_store_test_template.h
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/sync/engine/attachments/attachment_util.h"
diff --git a/components/sync/engine/attachments/fake_attachment_uploader_unittest.cc b/components/sync/engine/attachments/fake_attachment_uploader_unittest.cc
index 5f3f3f7..ab27843 100644
--- a/components/sync/engine/attachments/fake_attachment_uploader_unittest.cc
+++ b/components/sync/engine/attachments/fake_attachment_uploader_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/sync/model/attachments/attachment.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/sync/engine/net/http_bridge_unittest.cc b/components/sync/engine/net/http_bridge_unittest.cc
index 6c55cef..57a33b5 100644
--- a/components/sync/engine/net/http_bridge_unittest.cc
+++ b/components/sync/engine/net/http_bridge_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/bit_cast.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/sync/engine/sync_backend_registrar_unittest.cc b/components/sync/engine/sync_backend_registrar_unittest.cc
index 5c42d6e..40c841e 100644
--- a/components/sync/engine/sync_backend_registrar_unittest.cc
+++ b/components/sync/engine/sync_backend_registrar_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/location.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/threading/thread.h"
diff --git a/components/sync/engine/ui_model_worker_unittest.cc b/components/sync/engine/ui_model_worker_unittest.cc
index ab27452..3a9915d9 100644
--- a/components/sync/engine/ui_model_worker_unittest.cc
+++ b/components/sync/engine/ui_model_worker_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index a62d45c..fa5e417 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/location.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/test/test_timeouts.h"
diff --git a/components/sync/model/attachments/attachment_service_proxy_unittest.cc b/components/sync/model/attachments/attachment_service_proxy_unittest.cc
index ae6d5ec..52faba4 100644
--- a/components/sync/model/attachments/attachment_service_proxy_unittest.cc
+++ b/components/sync/model/attachments/attachment_service_proxy_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
diff --git a/components/sync/model_impl/accumulating_metadata_change_list_unittest.cc b/components/sync/model_impl/accumulating_metadata_change_list_unittest.cc
index d65c321..f98755c 100644
--- a/components/sync/model_impl/accumulating_metadata_change_list_unittest.cc
+++ b/components/sync/model_impl/accumulating_metadata_change_list_unittest.cc
@@ -7,6 +7,7 @@
 #include <set>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/sync/model/mock_model_type_store.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/sync/model_impl/passthrough_metadata_change_list_unittest.cc b/components/sync/model_impl/passthrough_metadata_change_list_unittest.cc
index 50340e7..4805a09a 100644
--- a/components/sync/model_impl/passthrough_metadata_change_list_unittest.cc
+++ b/components/sync/model_impl/passthrough_metadata_change_list_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/sync/model/mock_model_type_store.h"
 #include "components/sync/protocol/entity_metadata.pb.h"
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 31b343b39..4f9da73 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -472,6 +472,15 @@
   VISIT(is_bookmarked);
 }
 
+VISIT_PROTO_FIELDS(const sync_pb::FieldTrialEvent::FieldTrial& proto) {
+  VISIT(name_id);
+  VISIT(group_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::FieldTrialEvent& proto) {
+  VISIT_REP(field_trials);
+}
+
 VISIT_PROTO_FIELDS(const sync_pb::GcmChannelFlags& proto) {
   VISIT(enabled);
 }
@@ -851,6 +860,7 @@
   VISIT(event_time_usec);
   VISIT(navigation_id);
   VISIT(session_id);
+  VISIT(field_trial_event);
 }
 
 VISIT_PROTO_FIELDS(const sync_pb::WalletMaskedCreditCard& proto) {
diff --git a/components/sync/protocol/user_event_specifics.proto b/components/sync/protocol/user_event_specifics.proto
index 8d3efd1..fa74e611 100644
--- a/components/sync/protocol/user_event_specifics.proto
+++ b/components/sync/protocol/user_event_specifics.proto
@@ -13,6 +13,14 @@
 
 package sync_pb;
 
+message FieldTrialEvent {
+  message FieldTrial {
+    optional fixed32 name_id = 1;
+    optional fixed32 group_id = 2;
+  }
+  repeated FieldTrial field_trials = 1;
+}
+
 message UserEventSpecifics {
   // Time of event, as measured on the client (unix epoch).
   optional int64 event_time_usec = 1;
@@ -24,5 +32,5 @@
   // other events belonged to.
   optional fixed64 session_id = 3;
 
-  // TODO(skym): Wrap actual event payloads in a oneof.
+  oneof event { FieldTrialEvent field_trial_event = 4; }
 }
diff --git a/components/sync/user_events/user_event_service.cc b/components/sync/user_events/user_event_service.cc
index 328808b6..7a7e0b8c 100644
--- a/components/sync/user_events/user_event_service.cc
+++ b/components/sync/user_events/user_event_service.cc
@@ -13,20 +13,19 @@
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/model/model_type_sync_bridge.h"
-#include "components/sync/protocol/sync.pb.h"
 #include "components/sync/user_events/user_event_sync_bridge.h"
 
 using sync_pb::UserEventSpecifics;
 
 namespace syncer {
 
-namespace {}  // namespace
-
 UserEventService::UserEventService(SyncService* sync_service,
                                    std::unique_ptr<UserEventSyncBridge> bridge)
     : sync_service_(sync_service),
       bridge_(std::move(bridge)),
-      session_id_(base::RandUint64()) {}
+      session_id_(base::RandUint64()) {
+  // TODO(skym): Subscribe to events about field trial membership changing.
+}
 
 UserEventService::~UserEventService() {}
 
@@ -58,4 +57,9 @@
          sync_service_->GetPreferredDataTypes().Has(HISTORY_DELETE_DIRECTIVES);
 }
 
+void RegisterDependentFieldTrial(const std::string& trial_name,
+                                 UserEventSpecifics::EventCase event_case) {
+  // TODO(skym): Implementation.
+}
+
 }  // namespace syncer
diff --git a/components/sync/user_events/user_event_service.h b/components/sync/user_events/user_event_service.h
index f460d6c3..09e2b60 100644
--- a/components/sync/user_events/user_event_service.h
+++ b/components/sync/user_events/user_event_service.h
@@ -6,14 +6,12 @@
 #define COMPONENTS_SYNC_USER_EVENTS_USER_EVENT_SERVICE_H_
 
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
-
-namespace sync_pb {
-class UserEventSpecifics;
-}  // namespace sync_pb
+#include "components/sync/protocol/user_event_specifics.pb.h"
 
 namespace syncer {
 
@@ -37,6 +35,12 @@
   void RecordUserEvent(std::unique_ptr<sync_pb::UserEventSpecifics> specifics);
   void RecordUserEvent(const sync_pb::UserEventSpecifics& specifics);
 
+  // Register that knowledge about a given field trial is important when
+  // interpreting specified user event type, and should be recorded if assigned.
+  void RegisterDependentFieldTrial(
+      const std::string& trial_name,
+      sync_pb::UserEventSpecifics::EventCase event_case);
+
   base::WeakPtr<ModelTypeSyncBridge> GetSyncBridge();
 
  private:
diff --git a/components/tracing/test/trace_event_perftest.cc b/components/tracing/test/trace_event_perftest.cc
index 721c3aa..6dfedab 100644
--- a/components/tracing/test/trace_event_perftest.cc
+++ b/components/tracing/test/trace_event_perftest.cc
@@ -5,6 +5,7 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pending_task.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
diff --git a/components/ui_devtools/devtools_server.cc b/components/ui_devtools/devtools_server.cc
index 5ed5794..32e0e33 100644
--- a/components/ui_devtools/devtools_server.cc
+++ b/components/ui_devtools/devtools_server.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/format_macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/update_client/crx_downloader_unittest.cc b/components/update_client/crx_downloader_unittest.cc
index ca9d4c7..aba14b11 100644
--- a/components/update_client/crx_downloader_unittest.cc
+++ b/components/update_client/crx_downloader_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc
index 2c85259..5c526bbb 100644
--- a/components/update_client/ping_manager_unittest.cc
+++ b/components/update_client/ping_manager_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/version.h"
diff --git a/components/update_client/request_sender_unittest.cc b/components/update_client/request_sender_unittest.cc
index 793e53c0..4255d23 100644
--- a/components/update_client/request_sender_unittest.cc
+++ b/components/update_client/request_sender_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc
index 6546206..81106a0b 100644
--- a/components/update_client/update_checker_unittest.cc
+++ b/components/update_client/update_checker_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_scheduler.h"
diff --git a/components/url_formatter/elide_url_unittest.cc b/components/url_formatter/elide_url_unittest.cc
index f8f52f96..4ded2f99 100644
--- a/components/url_formatter/elide_url_unittest.cc
+++ b/components/url_formatter/elide_url_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
diff --git a/components/web_resource/resource_request_allowed_notifier_unittest.cc b/components/web_resource/resource_request_allowed_notifier_unittest.cc
index 78ceb33..014a0ec 100644
--- a/components/web_resource/resource_request_allowed_notifier_unittest.cc
+++ b/components/web_resource/resource_request_allowed_notifier_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/web_resource/eula_accepted_notifier.h"
diff --git a/components/webauth/BUILD.gn b/components/webauth/BUILD.gn
new file mode 100644
index 0000000..80da9afb
--- /dev/null
+++ b/components/webauth/BUILD.gn
@@ -0,0 +1,15 @@
+# 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("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("authenticator") {
+  sources = [
+    "authenticator.mojom",
+  ]
+
+  public_deps = [
+    "//mojo/common:common_custom_types",
+  ]
+}
diff --git a/components/webauth/OWNERS b/components/webauth/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/components/webauth/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/webauth/authenticator.mojom b/components/webauth/authenticator.mojom
new file mode 100644
index 0000000..1bf69a9
--- /dev/null
+++ b/components/webauth/authenticator.mojom
@@ -0,0 +1,89 @@
+// 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.
+
+[JavaPackage="org.chromium.webauth.mojom"]
+module webauth.mojom;
+
+// This file describes the communication between the WebAuthentication renderer
+// implementation and browser-side implementations to create scoped credentials
+// and use already-created credentials to get assertions.
+// See https://w3c.github.io/webauthn/.
+
+// The public key and attestation that is returned by an authenticator's 
+// call to makeCredential.
+struct ScopedCredentialInfo {
+  // A blob of data containing the JSON serialization of client data passed
+  // to the authenticator.
+  array<uint8> client_data;
+  // A blob of data returned from the authenticator.
+  array<uint8> attestation;
+};
+
+// Information about the relying party and the user account held by that 
+// relying party. This information is used by the authenticator to create 
+// or retrieve an appropriate scoped credential for this account.
+// These fields take arbitrary input.
+
+struct RelyingPartyAccount {
+  // Friendly name of the Relying Party, e.g. "Acme Corporation"
+  string relying_party_display_name;
+  // Friendly name associated with the user account, e.g. "John P. Smith"
+  string display_name;
+  // Identifier for the account, corresponding to no more than one credential 
+  // per authenticator and Relying Party.
+  string id;
+  // Detailed name for the account, e.g. john.p.smith@example.com
+  string name;
+  // User image, if any.
+  // Todo make this url.mojom.Url in a followup CL
+  string image_url;
+};
+
+// Parameters that are used to generate an appropriate scoped credential.
+struct ScopedCredentialParameters {
+  ScopedCredentialType type;
+  // TODO(kpaulhamus): add AlgorithmIdentifier algorithm;
+};
+
+// Optional parameters that are used during makeCredential. 
+struct ScopedCredentialOptions {
+  //TODO(kpaulhamus): Make this mojo.common.mojom.TimeDelta in followup CL
+  int32 timeout_seconds;
+  string relying_party_id;
+  array<ScopedCredentialDescriptor> exclude_list;
+  // TODO(kpaulhamus): add Extensions
+};
+
+enum ScopedCredentialType {
+  SCOPEDCRED,
+};
+
+// Describes the credentials that the relying party already knows about for
+// the given account. If any of these are known to the authenticator, 
+// it should not create a new credential.
+struct ScopedCredentialDescriptor {
+  ScopedCredentialType type;
+  // Blob representing a credential key handle. Up to 255 bytes for 
+  // U2F authenticators.
+  array<uint8> id;
+  array<Transport> transports;
+};
+
+enum Transport {
+  USB,
+  NFC,
+  BLE,
+};
+
+// Interface to direct authenticators to create or use a scoped credential.
+interface Authenticator {
+  // Gets the credential info for a new credential created by an authenticator
+  // for the given relying party and account. 
+  // |attestation_challenge| is a blob passed from the relying party server.
+  MakeCredential(RelyingPartyAccount account_information,
+                 array<ScopedCredentialParameters> crypto_parameters,
+                 array<uint8> attestation_challenge,
+                 ScopedCredentialOptions? options)
+      => (array<ScopedCredentialInfo> scoped_credentials);
+};
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index c108d08..fc63bcd 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -84,7 +84,6 @@
     "//device/power_save_blocker",
     "//device/screen_orientation/public/interfaces",
     "//device/vr",
-    "//device/vr:mojo_bindings",
     "//device/vr/features",
     "//device/wake_lock/public/interfaces",
     "//google_apis",
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index d39e6a3..81b453ae 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -597,9 +597,12 @@
   const bool can_edit_richly =
       !!(params.edit_flags & blink::WebContextMenuData::kCanEditRichly);
 
-  Java_ContentViewCore_showPastePopup(env, obj, params.selection_start.x(),
-                                      params.selection_start.y(),
-                                      can_select_all, can_edit_richly);
+  int handle_height = GetRenderWidgetHostViewAndroid()->GetTouchHandleHeight();
+  Java_ContentViewCore_showPastePopup(
+      env, obj, params.selection_rect.x(), params.selection_rect.y(),
+      params.selection_rect.right(),
+      params.selection_rect.bottom() + handle_height, can_select_all,
+      can_edit_richly);
   return true;
 }
 
diff --git a/content/browser/android/selection_popup_controller.cc b/content/browser/android/selection_popup_controller.cc
index 70c142c..5f56370c 100644
--- a/content/browser/android/selection_popup_controller.cc
+++ b/content/browser/android/selection_popup_controller.cc
@@ -51,7 +51,6 @@
 
 void SelectionPopupController::OnSelectionEvent(
     ui::SelectionEventType event,
-    const gfx::PointF& selection_anchor,
     const gfx::RectF& selection_rect) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_obj_.get(env);
@@ -59,9 +58,8 @@
     return;
 
   Java_SelectionPopupController_onSelectionEvent(
-      env, obj, event, selection_anchor.x(), selection_anchor.y(),
-      selection_rect.x(), selection_rect.y(), selection_rect.right(),
-      selection_rect.bottom());
+      env, obj, event, selection_rect.x(), selection_rect.y(),
+      selection_rect.right(), selection_rect.bottom());
 }
 
 void SelectionPopupController::OnSelectionChanged(const std::string& text) {
diff --git a/content/browser/android/selection_popup_controller.h b/content/browser/android/selection_popup_controller.h
index 46f59808..b5d1b3e 100644
--- a/content/browser/android/selection_popup_controller.h
+++ b/content/browser/android/selection_popup_controller.h
@@ -29,7 +29,6 @@
 
   // Called from native -> java
   void OnSelectionEvent(ui::SelectionEventType event,
-                        const gfx::PointF& selection_anchor,
                         const gfx::RectF& selection_rect);
   void OnSelectionChanged(const std::string& text);
 
diff --git a/content/browser/appcache/appcache_disk_cache_unittest.cc b/content/browser/appcache/appcache_disk_cache_unittest.cc
index ff923d1..5241805 100644
--- a/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "content/browser/appcache/appcache_disk_cache.h"
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_disk_cache.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/appcache/appcache_request_handler_unittest.cc b/content/browser/appcache/appcache_request_handler_unittest.cc
index 3ae29404..3f506e9 100644
--- a/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/content/browser/appcache/appcache_response_unittest.cc b/content/browser/appcache/appcache_response_unittest.cc
index 8e633c1f..3fd5f1c 100644
--- a/content/browser/appcache/appcache_response_unittest.cc
+++ b/content/browser/appcache/appcache_response_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/compiler_specific.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pickle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc
index d1ed641..695d2d2 100644
--- a/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc
index 1ba9bbb..bf3752e 100644
--- a/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/content/browser/appcache/appcache_update_job_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/content/browser/appcache/appcache_url_request_job_unittest.cc b/content/browser/appcache/appcache_url_request_job_unittest.cc
index eb2ea07..9b9a6af 100644
--- a/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pickle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 3d5834cc..b6c50bd 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -189,6 +189,7 @@
   BFSI_INVALID_REQUESTS = 165,
   BFSI_INVALID_TITLE = 166,
   RWH_INVALID_FRAME_TOKEN = 167,
+  RWH_BAD_FRAME_SINK_REQUEST = 168,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 2425b673..ee67b18 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -20,6 +20,7 @@
 #include "base/memory/memory_coordinator_proxy.h"
 #include "base/memory/memory_pressure_monitor.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index 2499e1b..d770c3d 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -10,6 +10,7 @@
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/profiler/scoped_profile.h"
diff --git a/content/browser/byte_stream_unittest.cc b/content/browser/byte_stream_unittest.cc
index ab91257..f233a41 100644
--- a/content/browser/byte_stream_unittest.cc
+++ b/content/browser/byte_stream_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "net/base/io_buffer.h"
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 47b95f6..1017d56 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -19,6 +19,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "cc/base/histograms.h"
+#include "cc/base/switches.h"
 #include "cc/output/texture_mailbox_deleter.h"
 #include "cc/output/vulkan_in_process_context_provider.h"
 #include "cc/raster/single_thread_task_graph_runner.h"
@@ -57,7 +58,9 @@
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_constants.h"
 #include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/compositor_util.h"
 #include "ui/compositor/layer.h"
+#include "ui/display/display_switches.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/switches.h"
@@ -197,6 +200,8 @@
 
 GpuProcessTransportFactory::GpuProcessTransportFactory()
     : frame_sink_id_allocator_(kDefaultClientId),
+      renderer_settings_(
+          ui::CreateRendererSettings(&gpu::GetImageTextureTarget)),
       task_graph_runner_(new cc::SingleThreadTaskGraphRunner),
       callback_factory_(this) {
   cc::SetClientNameForMetrics("Browser");
@@ -601,7 +606,7 @@
   // The Display owns and uses the |display_output_surface| created above.
   data->display = base::MakeUnique<cc::Display>(
       display_compositor::HostSharedBitmapManager::current(),
-      GetGpuMemoryBufferManager(), compositor->GetRendererSettings(),
+      GetGpuMemoryBufferManager(), renderer_settings_,
       compositor->frame_sink_id(), begin_frame_source,
       std::move(display_output_surface), std::move(scheduler),
       base::MakeUnique<cc::TextureMailboxDeleter>(
@@ -695,12 +700,6 @@
   return 60.0;
 }
 
-uint32_t GpuProcessTransportFactory::GetImageTextureTarget(
-    gfx::BufferFormat format,
-    gfx::BufferUsage usage) {
-  return gpu::GetImageTextureTarget(format, usage);
-}
-
 gpu::GpuMemoryBufferManager*
 GpuProcessTransportFactory::GetGpuMemoryBufferManager() {
   return gpu_channel_factory_->GetGpuMemoryBufferManager();
@@ -803,6 +802,11 @@
     data->display->SetOutputIsSecure(secure);
 }
 
+const cc::RendererSettings& GpuProcessTransportFactory::GetRendererSettings()
+    const {
+  return renderer_settings_;
+}
+
 void GpuProcessTransportFactory::AddObserver(
     ui::ContextFactoryObserver* observer) {
   observer_list_.AddObserver(observer);
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index e54e923f..3474d77 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "build/build_config.h"
+#include "cc/output/renderer_settings.h"
 #include "cc/surfaces/frame_sink_id_allocator.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
@@ -48,11 +49,10 @@
   void CreateCompositorFrameSink(
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
-  uint32_t GetImageTextureTarget(gfx::BufferFormat format,
-                                 gfx::BufferUsage usage) override;
   double GetRefreshRate() const override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
+  const cc::RendererSettings& GetRendererSettings() const override;
   void AddObserver(ui::ContextFactoryObserver* observer) override;
   void RemoveObserver(ui::ContextFactoryObserver* observer) override;
 
@@ -121,6 +121,7 @@
       PerCompositorDataMap;
   PerCompositorDataMap per_compositor_data_;
 
+  const cc::RendererSettings renderer_settings_;
   scoped_refptr<ui::ContextProviderCommandBuffer> shared_main_thread_contexts_;
   std::unique_ptr<display_compositor::GLHelper> gl_helper_;
   base::ObserverList<ui::ContextFactoryObserver> observer_list_;
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc
index bb39a61..868c2ff 100644
--- a/content/browser/compositor/reflector_impl_unittest.cc
+++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/callback.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 "build/build_config.h"
diff --git a/content/browser/device_sensors/device_sensor_browsertest.cc b/content/browser/device_sensors/device_sensor_browsertest.cc
index 3edb868a..ef16d38 100644
--- a/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc
index 81eda4c..2ff78d2 100644
--- a/content/browser/devtools/devtools_http_handler.cc
+++ b/content/browser/devtools/devtools_http_handler.cc
@@ -15,6 +15,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc
index b264c07d..9d63fa7 100644
--- a/content/browser/devtools/devtools_manager_unittest.cc
+++ b/content/browser/devtools/devtools_manager_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/guid.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index fcf8b12..67af007f 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/content/browser/devtools/site_per_process_devtools_browsertest.cc b/content/browser/devtools/site_per_process_devtools_browsertest.cc
index 62817ef0..2bac5725 100644
--- a/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/browser/frame_host/frame_tree.h"
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 14298ac9..20dfc1c9 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -18,6 +18,7 @@
 #include "base/format_macros.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
diff --git a/content/browser/download/drag_download_file_browsertest.cc b/content/browser/download/drag_download_file_browsertest.cc
index 5e65fe1..6753598 100644
--- a/content/browser/download/drag_download_file_browsertest.cc
+++ b/content/browser/download/drag_download_file_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "content/browser/download/download_file_factory.h"
 #include "content/browser/download/download_file_impl.h"
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc
index fab177f..370e426 100644
--- a/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -107,4 +107,8 @@
 }
 #endif
 
+bool RenderFrameHostDelegate::IsBeingDestroyed() const {
+  return false;
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 92f6c2b..081986b 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -301,6 +301,10 @@
   GetJavaRenderFrameHostDelegate();
 #endif
 
+  // Whether the delegate is being destroyed, in which case the RenderFrameHost
+  // should not be asked to create a RenderFrame.
+  virtual bool IsBeingDestroyed() const;
+
  protected:
   virtual ~RenderFrameHostDelegate() {}
 };
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 2f7909aa9..9092831 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1067,6 +1067,12 @@
 }
 
 void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
+  // We should not create new RenderFrames while our delegate is being destroyed
+  // (e.g., via a WebContentsObserver during WebContents shutdown).  This seems
+  // to have caused crashes in https://crbug.com/717650.
+  if (created && delegate_)
+    CHECK(!delegate_->IsBeingDestroyed());
+
   bool was_created = render_frame_created_;
   render_frame_created_ = created;
 
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 03fd18bd..6d8896a 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -19,6 +19,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sha1.h"
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc
index 1f7d428..5ea32da 100644
--- a/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -134,7 +134,8 @@
         BrowserThread::IO, FROM_HERE,
         base::Bind(
             &PrepareNavigationOnIOThread, base::Passed(std::move(new_request)),
-            resource_context, resource_type, appcache_handle->core(),
+            resource_context, resource_type,
+            appcache_handle ? appcache_handle->core() : nullptr,
             base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest,
                        weak_factory_.GetWeakPtr())));
     return;
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 2bc2208..ec9bfc8 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pickle.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc
index f46634e..26058d7 100644
--- a/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index 655418b..f4236b5a 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/lock.h"
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
index b520705..502b06e 100644
--- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/debug/debugger.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/test_timeouts.h"
 #include "base/time/time.h"
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 6719ef1e..e376268 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/location.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/utf_string_conversions.h"
diff --git a/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc b/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc
index d3f0199a..a1c67cb 100644
--- a/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc
+++ b/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/memory/shared_memory.h"
 #include "base/memory/shared_memory_handle.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/sync_socket.h"
 #include "cc/base/math_util.h"
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 82b8ee9..c50f9d34 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -10,6 +10,7 @@
 #include <deque>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/sys_byteorder.h"
 #include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b6f34a5..be7acbc 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -31,6 +31,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/shared_memory.h"
 #include "base/memory/shared_memory_handle.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/metrics/persistent_memory_allocator.h"
@@ -1924,7 +1925,6 @@
     switches::kSitePerProcess,
     switches::kStatsCollectionController,
     switches::kTestType,
-    switches::kTopDocumentIsolation,
     switches::kTouchEventFeatureDetection,
     switches::kTouchTextSelectionStrategy,
     switches::kTraceConfigFile,
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index a79dc45..dbc1a4d 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -19,6 +19,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 2b146c05..0e3f32db 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 9dbbf15b..57c17da 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -973,6 +973,13 @@
          touch_selection_controller_->WillHandleTouchEvent(event);
 }
 
+int RenderWidgetHostViewAndroid::GetTouchHandleHeight() {
+  if (!touch_selection_controller_)
+    return 0;
+  return static_cast<int>(
+      touch_selection_controller_->GetStartHandleRect().height());
+}
+
 void RenderWidgetHostViewAndroid::ResetGestureDetection() {
   const ui::MotionEvent* current_down_event =
       gesture_provider_.GetCurrentDownEvent();
@@ -1148,6 +1155,14 @@
 
 void RenderWidgetHostViewAndroid::DidCreateNewRendererCompositorFrameSink(
     cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) {
+  if (!delegated_frame_host_) {
+    DCHECK(!using_browser_compositor_);
+    // We don't expect RendererCompositorFrameSink on Android WebView.
+    // (crbug.com/721102)
+    bad_message::ReceivedBadMessage(host_->GetProcess(),
+                                    bad_message::RWH_BAD_FRAME_SINK_REQUEST);
+    return;
+  }
   delegated_frame_host_->CompositorFrameSinkChanged();
   renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
   // Accumulated resources belong to the old RendererCompositorFrameSink and
@@ -1158,8 +1173,12 @@
 void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
     const cc::LocalSurfaceId& local_surface_id,
     cc::CompositorFrame frame) {
+  if (!delegated_frame_host_) {
+    DCHECK(!using_browser_compositor_);
+    return;
+  }
+
   last_scroll_offset_ = frame.metadata.root_scroll_offset;
-  DCHECK(delegated_frame_host_);
   DCHECK(!frame.render_pass_list.empty());
 
   cc::RenderPass* root_pass = frame.render_pass_list.back().get();
@@ -1309,8 +1328,7 @@
     ResetGestureDetection();
   }
   selection_popup_controller_->OnSelectionEvent(
-      event, touch_selection_controller_->GetStartPosition(),
-      GetSelectionRect(*touch_selection_controller_));
+      event, GetSelectionRect(*touch_selection_controller_));
 }
 
 std::unique_ptr<ui::TouchHandleDrawable>
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index aa85ccba..e56a9aa 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -254,6 +254,7 @@
 
   bool OnTouchEvent(const ui::MotionEvent& event);
   bool OnTouchHandleEvent(const ui::MotionEvent& event);
+  int GetTouchHandleHeight();
   void ResetGestureDetection();
   void SetDoubleTapSupportEnabled(bool enabled);
   void SetMultiTouchZoomSupportEnabled(bool enabled);
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 5145ff9..ca7aea28 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/content/browser/shareable_file_reference_unittest.cc b/content/browser/shareable_file_reference_unittest.cc
index 237d0d41..2d6fbd6 100644
--- a/content/browser/shareable_file_reference_unittest.cc
+++ b/content/browser/shareable_file_reference_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc
index f0d52a58..6c8455ed5 100644
--- a/content/browser/site_instance_impl_unittest.cc
+++ b/content/browser/site_instance_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/browsing_instance.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -25,6 +26,7 @@
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/url_utils.h"
@@ -796,8 +798,8 @@
   if (AreAllSitesIsolatedForTesting())
     return;  // --top-document-isolation is not possible.
 
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kTopDocumentIsolation);
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kTopDocumentIsolation);
 
   std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
   scoped_refptr<SiteInstanceImpl> main_instance =
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 7eebfa3c..0d39621 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -252,14 +252,14 @@
   return device_scale_factor;
 }
 
-// This method returns the scale factor on Android and 1.0 on other
-// platforms in order to adjust coordinates appropriately.
-double GetAdjustmentScaleFactorForAndroid(Shell* shell) {
-#if defined(OS_ANDROID)
-  return GetFrameDeviceScaleFactor(shell->web_contents());
-#else
-  return 1.0;
-#endif
+// This helper accounts for Android devices which use page scale factor
+// different from 1.0. Coordinate targeting needs to be adjusted before
+// hit testing.
+double GetPageScaleFactor(Shell* shell) {
+  return RenderWidgetHostImpl::From(
+             shell->web_contents()->GetRenderViewHost()->GetWidget())
+      ->last_frame_metadata()
+      .page_scale_factor;
 }
 
 // Helper function that performs a surface hittest.
@@ -299,7 +299,7 @@
 
   WaitForChildFrameSurfaceReady(child_node->current_frame_host());
 
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell);
+  float scale_factor = GetPageScaleFactor(shell);
 
   // Get the view bounds of the child iframe, which should account for the
   // relative offset of its direct parent within the root frame, for use in
@@ -312,28 +312,20 @@
                                    blink::WebInputEvent::kTimeStampForTesting);
   child_event.button = blink::WebPointerProperties::Button::kLeft;
   child_event.SetPositionInWidget(
-      gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x()) /
-                       scale_factor) +
-          3,
-      gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y()) /
-                       scale_factor) +
-          3);
+      gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x() + 5) *
+                       scale_factor),
+      gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y() + 5) *
+                       scale_factor));
   child_event.click_count = 1;
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
   router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
 
   EXPECT_TRUE(child_frame_monitor.EventWasReceived());
-  // The expected result coordinates are (3, 3), but can get slightly
-  // different results due to rounding error with some device scale factors.
-  EXPECT_TRUE(child_frame_monitor.event().PositionInWidget().x <= 5 &&
-              child_frame_monitor.event().PositionInWidget().x >= 1)
-      << " actual event.positionInWidget().x: "
-      << child_frame_monitor.event().PositionInWidget().x;
-  EXPECT_TRUE(child_frame_monitor.event().PositionInWidget().y <= 5 &&
-              child_frame_monitor.event().PositionInWidget().y >= 1)
-      << " actual event.positionInWidget().y: "
-      << child_frame_monitor.event().PositionInWidget().y;
+  // The expected result coordinates are (5, 5), but can get slightly
+  // different results due to rounding error with some page scale factors.
+  EXPECT_NEAR(5, child_frame_monitor.event().PositionInWidget().x, 2);
+  EXPECT_NEAR(5, child_frame_monitor.event().PositionInWidget().y, 2);
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
 
   child_frame_monitor.ResetEventReceived();
@@ -344,15 +336,15 @@
                                   blink::WebInputEvent::kNoModifiers,
                                   blink::WebInputEvent::kTimeStampForTesting);
   main_event.button = blink::WebPointerProperties::Button::kLeft;
-  main_event.SetPositionInWidget(1, 1);
+  main_event.SetPositionInWidget(2, 2);
   main_event.click_count = 1;
   // Ladies and gentlemen, THIS is the main_event!
   router->RouteMouseEvent(root_view, &main_event, ui::LatencyInfo());
 
   EXPECT_FALSE(child_frame_monitor.EventWasReceived());
   EXPECT_TRUE(main_frame_monitor.EventWasReceived());
-  EXPECT_EQ(1, main_frame_monitor.event().PositionInWidget().x);
-  EXPECT_EQ(1, main_frame_monitor.event().PositionInWidget().y);
+  EXPECT_NEAR(2, main_frame_monitor.event().PositionInWidget().x, 2);
+  EXPECT_NEAR(2, main_frame_monitor.event().PositionInWidget().y, 2);
 }
 
 class RedirectNotificationObserver : public NotificationObserver {
@@ -1031,15 +1023,7 @@
 // Test that the view bounds for an out-of-process iframe are set and updated
 // correctly, including accounting for local frame offsets in the parent and
 // scroll positions.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_ViewBoundsInNestedFrameTest DISABLED_ViewBoundsInNestedFrameTest
-#else
-#define MAYBE_ViewBoundsInNestedFrameTest ViewBoundsInNestedFrameTest
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_ViewBoundsInNestedFrameTest) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ViewBoundsInNestedFrameTest) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a)"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1074,26 +1058,11 @@
 
   WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
 
-#if defined(OS_ANDROID)
-  // Android browser tests have some differences that affect the results. One
-  // is viewport dimensions, the other is that it handles scale factor
-  // differently.
-  int expected_x = 487;
-#else
-  int expected_x = 397;
-#endif
-  int expected_y = 112;
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell());
+  float scale_factor = GetPageScaleFactor(shell());
 
-  // Verify the view bounds of the nested iframe, which should account for the
+  // Get the view bounds of the nested iframe, which should account for the
   // relative offset of its direct parent within the root frame.
   gfx::Rect bounds = rwhv_nested->GetViewBounds();
-  int diff_x = bounds.x() - rwhv_root->GetViewBounds().x() - expected_x;
-  int diff_y = bounds.y() - rwhv_root->GetViewBounds().y() - expected_y;
-  // diff_x and diff_y should usually be zero, but can get slightly different
-  // results due to rounding error with some device scale factors.
-  EXPECT_TRUE(diff_x <= 2 && diff_x >= -2) << " actual diff_x: " << diff_x;
-  EXPECT_TRUE(diff_y <= 2 && diff_y >= -2) << " actual diff_y: " << diff_y;
 
   scoped_refptr<FrameRectChangedMessageFilter> filter =
       new FrameRectChangedMessageFilter();
@@ -1106,9 +1075,9 @@
       blink::WebInputEvent::kTimeStampForTesting);
 
   scroll_event.SetPositionInWidget(
-      gfx::ToFlooredInt((bounds.x() - rwhv_root->GetViewBounds().x() - 5) /
+      gfx::ToFlooredInt((bounds.x() - rwhv_root->GetViewBounds().x() - 5) *
                         scale_factor),
-      gfx::ToFlooredInt((bounds.y() - rwhv_root->GetViewBounds().y() - 5) /
+      gfx::ToFlooredInt((bounds.y() - rwhv_root->GetViewBounds().y() - 5) *
                         scale_factor));
   scroll_event.delta_x = 0.0f;
   scroll_event.delta_y = -30.0f;
@@ -1194,13 +1163,7 @@
 
 // Test that scrolling a nested out-of-process iframe bubbles unused scroll
 // delta to a parent frame.
-#if defined(OS_ANDROID)
-#define MAYBE_ScrollBubblingFromOOPIFTest DISABLED_ScrollBubblingFromOOPIFTest
-#else
-#define MAYBE_ScrollBubblingFromOOPIFTest ScrollBubblingFromOOPIFTest
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_ScrollBubblingFromOOPIFTest) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScrollBubblingFromOOPIFTest) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1431,11 +1394,9 @@
 
 // Test that mouse events are being routed to the correct RenderWidgetHostView
 // based on coordinates.
-#if defined(THREAD_SANITIZER) || defined(OS_ANDROID)
+#if defined(THREAD_SANITIZER)
 // The test times out often on TSAN bot.
 // https://crbug.com/591170.
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
 #define MAYBE_SurfaceHitTestTest DISABLED_SurfaceHitTestTest
 #else
 #define MAYBE_SurfaceHitTestTest SurfaceHitTestTest
@@ -1460,15 +1421,7 @@
 
 // Test that mouse events are being routed to the correct RenderWidgetHostView
 // when there are nested out-of-process iframes.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_NestedSurfaceHitTestTest DISABLED_NestedSurfaceHitTestTest
-#else
-#define MAYBE_NestedSurfaceHitTestTest NestedSurfaceHitTestTest
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_NestedSurfaceHitTestTest) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NestedSurfaceHitTestTest) {
   GURL main_url(embedded_test_server()->GetURL(
       "/frame_tree/page_with_positioned_nested_frames.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1512,7 +1465,7 @@
 
   WaitForChildFrameSurfaceReady(nested_iframe_node->current_frame_host());
 
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell());
+  float scale_factor = GetPageScaleFactor(shell());
 
   // Get the view bounds of the nested iframe, which should account for the
   // relative offset of its direct parent within the root frame, for use in
@@ -1525,43 +1478,25 @@
                                     blink::WebInputEvent::kTimeStampForTesting);
   nested_event.button = blink::WebPointerProperties::Button::kLeft;
   nested_event.SetPositionInWidget(
-      gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x()) /
-                       scale_factor) +
-          5,
-      gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y()) /
-                       scale_factor) +
-          5);
+      gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x() + 10) *
+                       scale_factor),
+      gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y() + 10) *
+                       scale_factor));
   nested_event.click_count = 1;
   nested_frame_monitor.ResetEventReceived();
   main_frame_monitor.ResetEventReceived();
   router->RouteMouseEvent(root_view, &nested_event, ui::LatencyInfo());
 
   EXPECT_TRUE(nested_frame_monitor.EventWasReceived());
-  // The expected result coordinates are (5, 5), but can get slightly
-  // different results due to rounding error with some device scale factors.
-  EXPECT_TRUE(nested_frame_monitor.event().PositionInWidget().x <= 6 &&
-              nested_frame_monitor.event().PositionInWidget().x >= 4)
-      << " actual event.positionInWidget().x: "
-      << nested_frame_monitor.event().PositionInWidget().x;
-  EXPECT_TRUE(nested_frame_monitor.event().PositionInWidget().y <= 6 &&
-              nested_frame_monitor.event().PositionInWidget().y >= 4)
-      << " actual event.positionInWidget().y: "
-      << nested_frame_monitor.event().PositionInWidget().y;
+  EXPECT_NEAR(10, nested_frame_monitor.event().PositionInWidget().x, 2);
+  EXPECT_NEAR(10, nested_frame_monitor.event().PositionInWidget().y, 2);
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
 }
 
 // This test tests that browser process hittesting ignores frames with
 // pointer-events: none.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_SurfaceHitTestPointerEventsNone \
-  DISABLED_SurfaceHitTestPointerEventsNone
-#else
-#define MAYBE_SurfaceHitTestPointerEventsNone SurfaceHitTestPointerEventsNone
-#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_SurfaceHitTestPointerEventsNone) {
+                       SurfaceHitTestPointerEventsNone) {
   GURL main_url(embedded_test_server()->GetURL(
       "/frame_tree/page_with_positioned_frame_pointer-events_none.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1602,24 +1537,15 @@
   router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
 
   EXPECT_TRUE(main_frame_monitor.EventWasReceived());
-  EXPECT_EQ(75, main_frame_monitor.event().PositionInWidget().x);
-  EXPECT_EQ(75, main_frame_monitor.event().PositionInWidget().y);
+  EXPECT_NEAR(75, main_frame_monitor.event().PositionInWidget().x, 2);
+  EXPECT_NEAR(75, main_frame_monitor.event().PositionInWidget().y, 2);
   EXPECT_FALSE(child_frame_monitor.EventWasReceived());
 }
 
 // This test verifies that MouseEnter and MouseLeave events fire correctly
 // when the mouse cursor moves between processes.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_CrossProcessMouseEnterAndLeaveTest \
-  DISABLED_CrossProcessMouseEnterAndLeaveTest
-#else
-#define MAYBE_CrossProcessMouseEnterAndLeaveTest \
-  CrossProcessMouseEnterAndLeaveTest
-#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_CrossProcessMouseEnterAndLeaveTest) {
+                       CrossProcessMouseEnterAndLeaveTest) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b,c(d))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1669,7 +1595,7 @@
   RenderWidgetHostMouseEventMonitor d_frame_monitor(
       d_node->current_frame_host()->GetRenderWidgetHost());
 
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell());
+  float scale_factor = GetPageScaleFactor(shell());
 
   // Get the view bounds of the child iframe, which should account for the
   // relative offset of its direct parent within the root frame, for use in
@@ -1680,11 +1606,11 @@
 
   gfx::Point point_in_a_frame(2, 2);
   gfx::Point point_in_b_frame(
-      gfx::ToCeiledInt((b_bounds.x() - a_bounds.x()) / scale_factor) + 25,
-      gfx::ToCeiledInt((b_bounds.y() - a_bounds.y()) / scale_factor) + 25);
+      gfx::ToCeiledInt((b_bounds.x() - a_bounds.x() + 25) * scale_factor),
+      gfx::ToCeiledInt((b_bounds.y() - a_bounds.y() + 25) * scale_factor));
   gfx::Point point_in_d_frame(
-      gfx::ToCeiledInt((d_bounds.x() - a_bounds.x()) / scale_factor) + 25,
-      gfx::ToCeiledInt((d_bounds.y() - a_bounds.y()) / scale_factor) + 25);
+      gfx::ToCeiledInt((d_bounds.x() - a_bounds.x() + 25) * scale_factor),
+      gfx::ToCeiledInt((d_bounds.y() - a_bounds.y() + 25) * scale_factor));
 
   blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseMove,
                                    blink::WebInputEvent::kNoModifiers,
@@ -1735,15 +1661,7 @@
 // Verify that mouse capture works on a RenderWidgetHostView level, so that
 // dragging scroll bars and selecting text continues even when the mouse
 // cursor crosses over cross-process frame boundaries.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_CrossProcessMouseCapture DISABLED_CrossProcessMouseCapture
-#else
-#define MAYBE_CrossProcessMouseCapture CrossProcessMouseCapture
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       MAYBE_CrossProcessMouseCapture) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossProcessMouseCapture) {
   GURL main_url(embedded_test_server()->GetURL(
       "/frame_tree/page_with_positioned_frame.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1774,20 +1692,16 @@
 
   WaitForChildFrameSurfaceReady(child_node->current_frame_host());
 
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell());
+  float scale_factor = GetPageScaleFactor(shell());
 
   // Get the view bounds of the child iframe, which should account for the
   // relative offset of its direct parent within the root frame, for use in
   // targeting the input event.
   gfx::Rect bounds = rwhv_child->GetViewBounds();
-  int child_frame_target_x =
-      gfx::ToCeiledInt((bounds.x() - root_view->GetViewBounds().x()) /
-                       scale_factor) +
-      5;
-  int child_frame_target_y =
-      gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y()) /
-                       scale_factor) +
-      5;
+  int child_frame_target_x = gfx::ToCeiledInt(
+      (bounds.x() - root_view->GetViewBounds().x() + 5) * scale_factor);
+  int child_frame_target_y = gfx::ToCeiledInt(
+      (bounds.y() - root_view->GetViewBounds().y() + 5) * scale_factor);
 
   // Target MouseDown to child frame.
   blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown,
@@ -1815,7 +1729,7 @@
   router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
-  mouse_event.SetPositionInWidget(1, 2);
+  mouse_event.SetPositionInWidget(1, 5);
   router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
 
   EXPECT_FALSE(main_frame_monitor.EventWasReceived());
@@ -1835,12 +1749,12 @@
   // Subsequent MouseMove events targeted to the main frame should be routed
   // to that frame.
   mouse_event.SetType(blink::WebInputEvent::kMouseMove);
-  mouse_event.SetPositionInWidget(1, 3);
+  mouse_event.SetPositionInWidget(1, 10);
   // Sending the MouseMove twice for the same reason as above.
   router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
-  mouse_event.SetPositionInWidget(1, 4);
+  mouse_event.SetPositionInWidget(1, 15);
   router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
 
   EXPECT_TRUE(main_frame_monitor.EventWasReceived());
@@ -1848,7 +1762,7 @@
 
   // Target MouseDown to the main frame to cause it to capture input.
   mouse_event.SetType(blink::WebInputEvent::kMouseDown);
-  mouse_event.SetPositionInWidget(1, 1);
+  mouse_event.SetPositionInWidget(1, 20);
   main_frame_monitor.ResetEventReceived();
   child_frame_monitor.ResetEventReceived();
   router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo());
@@ -6356,14 +6270,14 @@
       static_cast<WebContentsImpl*>(shell->web_contents())
           ->GetInputEventRouter();
 
-  float scale_factor = GetAdjustmentScaleFactorForAndroid(shell);
+  float scale_factor = GetPageScaleFactor(shell);
 
   gfx::Rect root_bounds = root_view->GetViewBounds();
   gfx::Rect bounds = rwhv_child->GetViewBounds();
 
   gfx::Point point(
-      gfx::ToCeiledInt((bounds.x() - root_bounds.x()) / scale_factor) + 10,
-      gfx::ToCeiledInt((bounds.y() - root_bounds.y()) / scale_factor) + 10);
+      gfx::ToCeiledInt((bounds.x() - root_bounds.x() + 5) * scale_factor),
+      gfx::ToCeiledInt((bounds.y() - root_bounds.y() + 5) * scale_factor));
 
   // Target right-click event to child frame.
   blink::WebMouseEvent click_event(blink::WebInputEvent::kMouseDown,
@@ -6383,20 +6297,13 @@
 
   ContextMenuParams params = context_menu_delegate.getParams();
 
-  EXPECT_EQ(point.x(), params.x);
-  EXPECT_EQ(point.y(), params.y);
+  EXPECT_NEAR(point.x(), params.x, 2);
+  EXPECT_NEAR(point.y(), params.y, 2);
 }
 
 // Test that a mouse right-click to an out-of-process iframe causes a context
 // menu to be generated with the correct screen position.
-#if defined(OS_ANDROID)
-// Test failing on some Android builders, due to inaccurate coordinates on
-// some devices. See: https://crbug.com/700007.
-#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
-#else
-#define MAYBE_CreateContextMenuTest CreateContextMenuTest
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CreateContextMenuTest) {
   CreateContextMenuTestHelper(shell(), embedded_test_server());
 }
 
diff --git a/content/browser/storage_partition_impl_map_unittest.cc b/content/browser/storage_partition_impl_map_unittest.cc
index 8ec82e4..2b8cc09f 100644
--- a/content/browser/storage_partition_impl_map_unittest.cc
+++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_context.h"
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 4142782..1aeac50 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/content/browser/top_document_isolation_browsertest.cc b/content/browser/top_document_isolation_browsertest.cc
index 6cd1f03..17caf7a 100644
--- a/content/browser/top_document_isolation_browsertest.cc
+++ b/content/browser/top_document_isolation_browsertest.cc
@@ -5,9 +5,10 @@
 #include <string>
 
 #include "base/command_line.h"
+#include "base/test/scoped_feature_list.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -30,11 +31,8 @@
     return visualizer_.DepictFrameTree(node);
   }
 
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kTopDocumentIsolation);
-  }
-
   void SetUpOnMainThread() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kTopDocumentIsolation);
     host_resolver()->AddRule("*", "127.0.0.1");
     SetupCrossSiteRedirector(embedded_test_server());
     ASSERT_TRUE(embedded_test_server()->Start());
@@ -67,6 +65,9 @@
 
  private:
   FrameTreeVisualizer visualizer_;
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(TopDocumentIsolationTest);
 };
 
 IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, SameSiteDeeplyNested) {
diff --git a/content/browser/wake_lock/wake_lock_browsertest.cc b/content/browser/wake_lock/wake_lock_browsertest.cc
index cae2296..57f3814 100644
--- a/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/test_timeouts.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index ebbb7ef5..78c9738 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -530,10 +530,16 @@
 }
 
 WebContentsImpl::~WebContentsImpl() {
+  // Imperfect sanity check against double free, given some crashes unexpectedly
+  // observed in the wild.
+  CHECK(!is_being_destroyed_);
+
+  // We generally keep track of is_being_destroyed_ to let other features know
+  // to avoid certain actions during destruction.
   is_being_destroyed_ = true;
 
   // A WebContents should never be deleted while it is notifying observers,
-  // since this will lead to a use-after-free as it continues to notfiy later
+  // since this will lead to a use-after-free as it continues to notify later
   // observers.
   CHECK(!is_notifying_observers_);
 
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index ba5ced33..a12d017 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index 7bb4984..bff7772 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -18,6 +18,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/message_loop/timer_slack.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
@@ -68,6 +69,7 @@
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
 #include "services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h"
+#include "services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "services/service_manager/runner/common/client_util.h"
@@ -498,8 +500,21 @@
     channel_->AddFilter(new ChildMemoryMessageFilter());
 
     if (service_manager_connection_) {
+      std::string process_type_str =
+          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+              switches::kProcessType);
+      auto process_type = memory_instrumentation::mojom::ProcessType::OTHER;
+      if (process_type_str == switches::kRendererProcess)
+        process_type = memory_instrumentation::mojom::ProcessType::RENDERER;
+      else if (process_type_str == switches::kGpuProcess)
+        process_type = memory_instrumentation::mojom::ProcessType::GPU;
+      else if (process_type_str == switches::kUtilityProcess)
+        process_type = memory_instrumentation::mojom::ProcessType::UTILITY;
+      else if (process_type_str == switches::kPpapiPluginProcess)
+        process_type = memory_instrumentation::mojom::ProcessType::PLUGIN;
+
       memory_instrumentation::ProcessLocalDumpManagerImpl::Config config(
-          GetConnector(), mojom::kBrowserServiceName);
+          GetConnector(), mojom::kBrowserServiceName, process_type);
       memory_instrumentation::ProcessLocalDumpManagerImpl::CreateInstance(
           config);
     }
diff --git a/content/child/url_response_body_consumer_unittest.cc b/content/child/url_response_body_consumer_unittest.cc
index 9648c3ae..09018ac3 100644
--- a/content/child/url_response_body_consumer_unittest.cc
+++ b/content/child/url_response_body_consumer_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/child/request_extra_data.h"
 #include "content/child/resource_dispatcher.h"
diff --git a/content/child/web_data_consumer_handle_impl_unittest.cc b/content/child/web_data_consumer_handle_impl_unittest.cc
index 17f9361..17eae33 100644
--- a/content/child/web_data_consumer_handle_impl_unittest.cc
+++ b/content/child/web_data_consumer_handle_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/location.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/synchronization/waitable_event.h"
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 963405f..af19509 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -644,7 +644,9 @@
     "//url/mojo:url_mojom_origin",
   ]
 
-  component_output_prefix = "content_common_mojo_bindings"
+  overridden_deps = [ "//ipc:mojom" ]
+  component_deps = [ "//ipc" ]
+
   export_class_attribute = "CONTENT_EXPORT"
   export_define = "CONTENT_IMPLEMENTATION=1"
   export_header = "content/common/content_export.h"
diff --git a/content/common/feature_policy/feature_policy.cc b/content/common/feature_policy/feature_policy.cc
index bfc79cf..76ad7698 100644
--- a/content/common/feature_policy/feature_policy.cc
+++ b/content/common/feature_policy/feature_policy.cc
@@ -235,7 +235,9 @@
                            {blink::WebFeaturePolicyFeature::kSyncXHR,
                             FeaturePolicy::FeatureDefault::EnableForAll},
                            {blink::WebFeaturePolicyFeature::kWebRTC,
-                            FeaturePolicy::FeatureDefault::EnableForAll}}));
+                            FeaturePolicy::FeatureDefault::EnableForAll},
+                           {blink::WebFeaturePolicyFeature::kUsb,
+                            FeaturePolicy::FeatureDefault::EnableForSelf}}));
   return default_feature_list;
 }
 
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 5e159ff..ca1ed2d0 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -160,11 +160,8 @@
   IPC_STRUCT_TRAITS_MEMBER(custom_context)
   IPC_STRUCT_TRAITS_MEMBER(custom_items)
   IPC_STRUCT_TRAITS_MEMBER(source_type)
-#if defined(OS_ANDROID)
-  IPC_STRUCT_TRAITS_MEMBER(selection_start)
-  IPC_STRUCT_TRAITS_MEMBER(selection_end)
-#endif
   IPC_STRUCT_TRAITS_MEMBER(input_field_type)
+  IPC_STRUCT_TRAITS_MEMBER(selection_rect)
 IPC_STRUCT_TRAITS_END()
 
 IPC_STRUCT_TRAITS_BEGIN(content::CustomContextMenuContext)
diff --git a/content/common/site_isolation_policy.cc b/content/common/site_isolation_policy.cc
index b3db97e..41c3653 100644
--- a/content/common/site_isolation_policy.cc
+++ b/content/common/site_isolation_policy.cc
@@ -39,8 +39,7 @@
   if (UseDedicatedProcessesForAllSites())
     return false;
 
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kTopDocumentIsolation);
+  return base::FeatureList::IsEnabled(::features::kTopDocumentIsolation);
 }
 
 }  // namespace content
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 91f1fcb..2258ec9 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
 #include "content/child/child_process.h"
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 7e307d91..91aaf8f3 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -203,9 +203,6 @@
     "java/src/org/chromium/content/browser/input/ThreadedInputConnection.java",
     "java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java",
     "java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java",
-    "java/src/org/chromium/content/browser/installedapp/InstalledAppProviderFactory.java",
-    "java/src/org/chromium/content/browser/installedapp/InstalledAppProviderImpl.java",
-    "java/src/org/chromium/content/browser/installedapp/PackageHash.java",
     "java/src/org/chromium/content/browser/picker/DateDialogNormalizer.java",
     "java/src/org/chromium/content/browser/picker/DatePickerDialogCompat.java",
     "java/src/org/chromium/content/browser/picker/DateTimePickerDialog.java",
@@ -480,8 +477,6 @@
     "junit/src/org/chromium/content/browser/input/ThreadedInputConnectionFactoryTest.java",
     "junit/src/org/chromium/content/browser/input/ThreadedInputConnectionTest.java",
     "junit/src/org/chromium/content/browser/picker/DateDialogNormalizerTest.java",
-    "junit/src/org/chromium/content/browser/installedapp/InstalledAppProviderTest.java",
-    "junit/src/org/chromium/content/browser/installedapp/PackageHashTest.java",
   ]
   deps = [
     ":content_java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index e3656b1..0bf514a4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -1696,8 +1696,10 @@
     }
 
     @CalledByNative
-    private void showPastePopup(int x, int y, boolean canSelectAll, boolean canEditRichly) {
-        mSelectionPopupController.createAndShowPastePopup(x, y, canSelectAll, canEditRichly);
+    private void showPastePopup(
+            int left, int top, int right, int bottom, boolean canSelectAll, boolean canEditRichly) {
+        mSelectionPopupController.createAndShowPastePopup(
+                left, top, right, bottom, canSelectAll, canEditRichly);
     }
 
     private void destroyPastePopup() {
diff --git a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
index 10bb5e4..81357340 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
@@ -9,12 +9,10 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.androidoverlay.AndroidOverlayProviderImpl;
-import org.chromium.content.browser.installedapp.InstalledAppProviderFactory;
 import org.chromium.content_public.browser.InterfaceRegistrar;
 import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.device.nfc.mojom.Nfc;
-import org.chromium.installedapp.mojom.InstalledAppProvider;
 import org.chromium.media.mojom.AndroidOverlayProvider;
 import org.chromium.mojo.system.impl.CoreImpl;
 import org.chromium.services.service_manager.InterfaceRegistry;
@@ -58,8 +56,6 @@
         InterfaceRegistrar.Registry.addContextRegistrar(new ContentContextInterfaceRegistrar());
         InterfaceRegistrar.Registry.addWebContentsRegistrar(
                 new ContentWebContentsInterfaceRegistrar());
-        InterfaceRegistrar.Registry.addRenderFrameHostRegistrar(
-                new ContentRenderFrameHostInterfaceRegistrar());
     }
 
     private static class ContentContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
@@ -81,14 +77,4 @@
             }
         }
     }
-
-    private static class ContentRenderFrameHostInterfaceRegistrar
-            implements InterfaceRegistrar<RenderFrameHost> {
-        @Override
-        public void registerInterfaces(
-                InterfaceRegistry registry, final RenderFrameHost renderFrameHost) {
-            registry.addInterface(
-                    InstalledAppProvider.MANAGER, new InstalledAppProviderFactory(renderFrameHost));
-        }
-    }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
index e23122b..cb1e9845c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java
@@ -268,13 +268,15 @@
         return actionMode;
     }
 
-    void createAndShowPastePopup(int x, int y, boolean canSelectAll, boolean canEditRichly) {
+    void createAndShowPastePopup(
+            int left, int top, int right, int bottom, boolean canSelectAll, boolean canEditRichly) {
         if (mView.getParent() == null || mView.getVisibility() != View.VISIBLE) {
             return;
         }
 
         if (!supportsFloatingActionMode() && !canPaste()) return;
         destroyPastePopup();
+        mSelectionRect.set(left, top, right, bottom);
         mCanSelectAllForPastePopup = canSelectAll;
         mCanEditRichlyForPastePopup = canEditRichly;
         PastePopupMenuDelegate delegate = new PastePopupMenuDelegate() {
@@ -317,17 +319,12 @@
         } else {
             mPastePopupMenu = new LegacyPastePopupMenu(windowContext, mView, delegate);
         }
-        showPastePopup(x, y);
+        showPastePopup();
     }
 
-    private void showPastePopup(int x, int y) {
-        // Coordinates are in DIP.
-        final float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
-        final int xPix = (int) (x * deviceScale);
-        final int yPix = (int) (y * deviceScale);
-        final float browserControlsShownPix = mRenderCoordinates.getContentOffsetYPix();
+    private void showPastePopup() {
         try {
-            mPastePopupMenu.show(xPix, (int) (yPix + browserControlsShownPix));
+            mPastePopupMenu.show(getSelectionRectRelativeToContainingView());
         } catch (WindowManager.BadTokenException e) {
         }
     }
@@ -686,15 +683,20 @@
      */
     @Override
     public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+        outRect.set(getSelectionRectRelativeToContainingView());
+    }
+
+    private Rect getSelectionRectRelativeToContainingView() {
         float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
-        outRect.set((int) (mSelectionRect.left * deviceScale),
+        Rect viewSelectionRect = new Rect((int) (mSelectionRect.left * deviceScale),
                 (int) (mSelectionRect.top * deviceScale),
                 (int) (mSelectionRect.right * deviceScale),
                 (int) (mSelectionRect.bottom * deviceScale));
 
         // The selection coordinates are relative to the content viewport, but we need
         // coordinates relative to the containing View.
-        outRect.offset(0, (int) mRenderCoordinates.getContentOffsetYPix());
+        viewSelectionRect.offset(0, (int) mRenderCoordinates.getContentOffsetYPix());
+        return viewSelectionRect;
     }
 
     /**
@@ -924,8 +926,7 @@
 
     // All coordinates are in DIP.
     @CalledByNative
-    private void onSelectionEvent(
-            int eventType, int xAnchor, int yAnchor, int left, int top, int right, int bottom) {
+    private void onSelectionEvent(int eventType, int left, int top, int right, int bottom) {
         // Ensure the provided selection coordinates form a non-empty rect, as required by
         // the selection action mode.
         if (left == right) ++right;
@@ -984,7 +985,7 @@
             case SelectionEventType.INSERTION_HANDLE_MOVED:
                 mSelectionRect.set(left, top, right, bottom);
                 if (!mScrollInProgress && isPastePopupShowing()) {
-                    showPastePopup(xAnchor, yAnchor);
+                    showPastePopup();
                 } else {
                     destroyPastePopup();
                 }
@@ -994,7 +995,7 @@
                 if (mWasPastePopupShowingOnInsertionDragStart) {
                     destroyPastePopup();
                 } else {
-                    mWebContents.showContextMenuAtPoint(xAnchor, yAnchor);
+                    mWebContents.showContextMenuAtPoint(mSelectionRect.left, mSelectionRect.bottom);
                 }
                 mWasPastePopupShowingOnInsertionDragStart = false;
                 break;
@@ -1012,7 +1013,7 @@
 
             case SelectionEventType.INSERTION_HANDLE_DRAG_STOPPED:
                 if (mWasPastePopupShowingOnInsertionDragStart) {
-                    mWebContents.showContextMenuAtPoint(xAnchor, yAnchor);
+                    mWebContents.showContextMenuAtPoint(mSelectionRect.left, mSelectionRect.bottom);
                 }
                 mWasPastePopupShowingOnInsertionDragStart = false;
                 break;
@@ -1023,8 +1024,8 @@
 
         if (mSelectionClient != null) {
             final float deviceScale = mRenderCoordinates.getDeviceScaleFactor();
-            int xAnchorPix = (int) (xAnchor * deviceScale);
-            int yAnchorPix = (int) (yAnchor * deviceScale);
+            int xAnchorPix = (int) (mSelectionRect.left * deviceScale);
+            int yAnchorPix = (int) (mSelectionRect.bottom * deviceScale);
             mSelectionClient.onSelectionEvent(eventType, xAnchorPix, yAnchorPix);
         }
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java b/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java
index 8d7e89b9..e4b66718 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java
@@ -8,7 +8,6 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
-import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -23,25 +22,12 @@
  */
 @TargetApi(Build.VERSION_CODES.M)
 public class FloatingPastePopupMenu implements PastePopupMenu {
-    private static final int CONTENT_RECT_OFFSET_DIP = 15;
-    private static final int SLOP_LENGTH_DIP = 10;
-
     private final View mParent;
     private final PastePopupMenuDelegate mDelegate;
     private final Context mContext;
 
-    // Offset from the paste coordinates to provide the floating ActionMode.
-    private final int mContentRectOffset;
-
-    // Slack for ignoring small deltas in the paste popup position. The initial
-    // position can change by a few pixels due to differences in how context
-    // menu and selection coordinates are computed. Suppressing this small delta
-    // avoids the floating ActionMode flicker when the popup is repositioned.
-    private final int mSlopLengthSquared;
-
     private ActionMode mActionMode;
-    private int mRawPositionX;
-    private int mRawPositionY;
+    private Rect mSelectionRect;
 
     public FloatingPastePopupMenu(Context context, View parent, PastePopupMenuDelegate delegate) {
         assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
@@ -49,22 +35,11 @@
         mParent = parent;
         mDelegate = delegate;
         mContext = context;
-
-        mContentRectOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                CONTENT_RECT_OFFSET_DIP, mContext.getResources().getDisplayMetrics());
-        int slopLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                SLOP_LENGTH_DIP, mContext.getResources().getDisplayMetrics());
-        mSlopLengthSquared = slopLength * slopLength;
     }
 
     @Override
-    public void show(int x, int y) {
-        int dx = mRawPositionX - x;
-        int dy = mRawPositionY - y;
-        if (dx * dx + dy * dy < mSlopLengthSquared) return;
-
-        mRawPositionX = x;
-        mRawPositionY = y;
+    public void show(Rect selectionRect) {
+        mSelectionRect = selectionRect;
         if (mActionMode != null) {
             mActionMode.invalidateContentRect();
             return;
@@ -154,10 +129,7 @@
 
         @Override
         public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
-            // Use a rect that spans above and below the insertion point.
-            // This avoids paste popup overlap with selection handles.
-            outRect.set(mRawPositionX - mContentRectOffset, mRawPositionY - mContentRectOffset,
-                    mRawPositionX + mContentRectOffset, mRawPositionY + mContentRectOffset);
+            outRect.set(mSelectionRect);
         }
     };
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/LegacyPastePopupMenu.java b/content/public/android/java/src/org/chromium/content/browser/input/LegacyPastePopupMenu.java
index fc8ba7fd..f3493c5 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/LegacyPastePopupMenu.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/LegacyPastePopupMenu.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -68,10 +69,10 @@
     }
 
     @Override
-    public void show(int x, int y) {
+    public void show(Rect selectionRect) {
         hide();
         updateContent();
-        positionAt(x, y);
+        positionAt(selectionRect.left, selectionRect.bottom);
     }
 
     @Override
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java b/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java
index 8b91ca3..15d64eb 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.java
@@ -4,6 +4,8 @@
 
 package org.chromium.content.browser.input;
 
+import android.graphics.Rect;
+
 /**
  * Paste popup implementation based on TextView.PastePopupMenu.
  */
@@ -44,9 +46,9 @@
     }
 
     /**
-     * Shows the paste popup at an appropriate location relative to the specified position.
+     * Shows the paste popup at an appropriate location relative to the specified selection.
      */
-    public void show(int x, int y);
+    public void show(Rect selectionRect);
 
     /**
      * Hides the paste popup.
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 4e85584..a89ba20 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -6,7 +6,9 @@
       "provides": {
         "gpu": [
           "content::mojom::FieldTrialRecorder",
-          "media::mojom::AndroidOverlayProvider",
+          "media::mojom::AndroidOverlayProvider"
+        ],
+        "memory_instrumentation": [
           "memory_instrumentation::mojom::Coordinator"
         ],
         "plugin": [
@@ -37,7 +39,6 @@
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
           "media::mojom::ImageCapture",
           "memory_coordinator::mojom::MemoryCoordinatorHandle",
-          "memory_instrumentation::mojom::Coordinator",
           "metrics::mojom::SingleSampleMetricsProvider",
           "payments::mojom::PaymentManager",
           "shape_detection::mojom::BarcodeDetection",
@@ -47,15 +48,12 @@
         ],
         "service_manager:service_factory": [
           "service_manager::mojom::ServiceFactory"
-        ],
-        "utility": [
-          "memory_instrumentation::mojom::Coordinator"
         ]
       },
       "requires": {
         "*": [ "app" ],
         // In classic ash, the browser supplies ash interfaces to itself.
-        "content_browser": [ "ash" ],
+        "content_browser": [ "ash", "memory_instrumentation" ],
         "content_gpu": [ "browser" ],
         "content_plugin": [ "browser" ],
         "content_renderer": [ "browser" ],
diff --git a/content/public/app/mojo/content_gpu_manifest.json b/content/public/app/mojo/content_gpu_manifest.json
index 238972c..a7d05d7 100644
--- a/content/public/app/mojo/content_gpu_manifest.json
+++ b/content/public/app/mojo/content_gpu_manifest.json
@@ -15,7 +15,7 @@
         ]
       },
       "requires": {
-        "content_browser": [ "gpu" ],
+        "content_browser": [ "gpu", "memory_instrumentation" ],
         "device": [ "device:power_monitor" ]
       }
     }
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json
index 1f85972..43c2a71 100644
--- a/content/public/app/mojo/content_renderer_manifest.json
+++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -19,7 +19,7 @@
         ]
       },
       "requires": {
-        "content_browser": [ "renderer" ],
+        "content_browser": [ "memory_instrumentation", "renderer" ],
         "device": [
           "device:battery_monitor",
           "device:generic_sensor",
@@ -47,7 +47,7 @@
         ]
       },
       "requires": {
-        "content_browser": [ "renderer" ]
+        "content_browser": [ "memory_instrumentation", "renderer" ]
       }
     }
   },
diff --git a/content/public/app/mojo/content_utility_manifest.json b/content/public/app/mojo/content_utility_manifest.json
index 0a058d7..3ea2993 100644
--- a/content/public/app/mojo/content_utility_manifest.json
+++ b/content/public/app/mojo/content_utility_manifest.json
@@ -14,7 +14,7 @@
         ]
       },
       "requires": {
-        "content_browser": [ "utility" ],
+        "content_browser": [ "memory_instrumentation" ],
         "device": [
           "device:power_monitor",
           "device:time_zone_monitor"
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index d122d0e44..fbadbdd 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -229,6 +229,12 @@
 const base::Feature kTokenBinding{"token-binding",
                                   base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Groups all out-of-process iframes to a different process from the process of
+// the top document. This is a performance isolation mode.  Launch bug:
+// https://crbug.com/595987.
+const base::Feature kTopDocumentIsolation{"top-document-isolation",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables touchpad and wheel scroll latching.
 const base::Feature kTouchpadAndWheelScrollLatching{
     "TouchpadAndWheelScrollLatching", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 697c35e4..a48969a9a 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -61,6 +61,7 @@
 CONTENT_EXPORT extern const base::Feature kSlimmingPaintInvalidation;
 CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
 CONTENT_EXPORT extern const base::Feature kTokenBinding;
+CONTENT_EXPORT extern const base::Feature kTopDocumentIsolation;
 CONTENT_EXPORT extern const base::Feature kTouchpadAndWheelScrollLatching;
 CONTENT_EXPORT extern const base::Feature kVibrateRequiresUserGesture;
 CONTENT_EXPORT extern const base::Feature kVrShell;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index c37a3cd..224c032 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -853,10 +853,6 @@
 // Type of the current test harness ("browser" or "ui").
 const char kTestType[]                      = "test-type";
 
-// Groups all out-of-process iframes to a different process from the process
-// of the top document. This is a performance isolation mode.
-const char kTopDocumentIsolation[] = "top-document-isolation";
-
 // Enable support for touch event feature detection.
 const char kTouchEventFeatureDetection[] = "touch-events";
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 7a4b891..b07cc564 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -240,7 +240,6 @@
 CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
 CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
 CONTENT_EXPORT extern const char kTestType[];
-CONTENT_EXPORT extern const char kTopDocumentIsolation[];
 CONTENT_EXPORT extern const char kTouchEventFeatureDetection[];
 CONTENT_EXPORT extern const char kTouchEventFeatureDetectionAuto[];
 CONTENT_EXPORT extern const char kTouchEventFeatureDetectionEnabled[];
diff --git a/content/public/common/context_menu_params.h b/content/public/common/context_menu_params.h
index f052d3ff..7c104b8e 100644
--- a/content/public/common/context_menu_params.h
+++ b/content/public/common/context_menu_params.h
@@ -20,12 +20,9 @@
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
 #include "third_party/WebKit/public/web/WebContextMenuData.h"
 #include "ui/base/ui_base_types.h"
+#include "ui/gfx/geometry/rect.h"
 #include "url/gurl.h"
 
-#if defined(OS_ANDROID)
-#include "ui/gfx/geometry/point.h"
-#endif
-
 namespace content {
 
 struct CONTENT_EXPORT CustomContextMenuContext {
@@ -156,15 +153,11 @@
   // Extra properties for the context menu.
   std::map<std::string, std::string> properties;
 
-#if defined(OS_ANDROID)
-  // Points representing the coordinates in the document space of the start and
-  // end of the selection, if there is one.
-  gfx::Point selection_start;
-  gfx::Point selection_end;
-#endif
-
   // If this node is an input field, the type of that field.
   blink::WebContextMenuData::InputFieldType input_field_type;
+
+  // Rect representing the coordinates in the document space of the selection.
+  gfx::Rect selection_rect;
 };
 
 }  // namespace content
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index d9e976e1..9526a39 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -13,6 +13,7 @@
 #include "base/i18n/icu_util.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info.h"
diff --git a/content/public/test/javascript_test_observer.cc b/content/public/test/javascript_test_observer.cc
index becdd834..50aaf04 100644
--- a/content/public/test/javascript_test_observer.cc
+++ b/content/public/test/javascript_test_observer.cc
@@ -4,6 +4,7 @@
 
 #include "content/public/test/javascript_test_observer.h"
 
+#include "base/message_loop/message_loop.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index 4fb9c66..a50cc6c 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/content/renderer/device_sensors/device_motion_event_pump_unittest.cc b/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
index d655ee49..a87462441 100644
--- a/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
+++ b/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc b/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
index 8a61ba3a..a2139512 100644
--- a/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
+++ b/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 936cb828..7730f139 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -1124,6 +1124,11 @@
 
   bool fallback = num_failed_recreate_attempts_ >=
                   COMPOSITOR_FRAME_SINK_RETRIES_BEFORE_FALLBACK;
+
+#ifdef OS_ANDROID
+  LOG_IF(FATAL, fallback) << "Android does not support fallback frame sinks.";
+#endif
+
   delegate_->RequestNewCompositorFrameSink(
       fallback, base::Bind(&RenderWidgetCompositor::SetCompositorFrameSink,
                            weak_factory_.GetWeakPtr()));
diff --git a/content/renderer/gpu/render_widget_compositor_unittest.cc b/content/renderer/gpu/render_widget_compositor_unittest.cc
index 82f8f1c..eeb3e29 100644
--- a/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/location.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/threading/thread_task_runner_handle.h"
@@ -292,6 +293,8 @@
   RunTest(false, 1, 1, 0);
 }
 
+// Android doesn't support fallback frame sinks. (crbug.com/721102)
+#ifndef OS_ANDROID
 TEST_F(RenderWidgetCompositorFrameSinkTest, FallbackSuccessNull) {
   RunTest(true,
           RenderWidgetCompositor::COMPOSITOR_FRAME_SINK_RETRIES_BEFORE_FALLBACK,
@@ -310,6 +313,7 @@
           RenderWidgetCompositor::COMPOSITOR_FRAME_SINK_RETRIES_BEFORE_FALLBACK,
           1, 1);
 }
+#endif
 
 }  // namespace
 }  // namespace content
diff --git a/content/renderer/media/audio_message_filter_unittest.cc b/content/renderer/media/audio_message_filter_unittest.cc
index 1619706..a4223f4 100644
--- a/content/renderer/media/audio_message_filter_unittest.cc
+++ b/content/renderer/media/audio_message_filter_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/common/media/audio_messages.h"
 #include "content/renderer/media/audio_message_filter.h"
diff --git a/content/renderer/media/audio_renderer_sink_cache_unittest.cc b/content/renderer/media/audio_renderer_sink_cache_unittest.cc
index f9348e4c..afbaf16 100644
--- a/content/renderer/media/audio_renderer_sink_cache_unittest.cc
+++ b/content/renderer/media/audio_renderer_sink_cache_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread.h"
diff --git a/content/renderer/media/media_stream_video_renderer_sink_unittest.cc b/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
index 511c1041..6ced490 100644
--- a/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
+++ b/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/child/child_process.h"
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 964b2d3..1b83f15 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/content/renderer/media/webmediaplayer_ms_unittest.cc b/content/renderer/media/webmediaplayer_ms_unittest.cc
index 127a782..96d56a5 100644
--- a/content/renderer/media/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "content/public/renderer/media_stream_renderer_factory.h"
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
index dca3365..e88da286e 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
@@ -5,6 +5,7 @@
 #include <algorithm>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "content/child/child_process.h"
diff --git a/content/renderer/media/webrtc_audio_renderer_unittest.cc b/content/renderer/media/webrtc_audio_renderer_unittest.cc
index 4c6bd1e3..89785b3e 100644
--- a/content/renderer/media/webrtc_audio_renderer_unittest.cc
+++ b/content/renderer/media/webrtc_audio_renderer_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/public/renderer/media_stream_audio_renderer.h"
diff --git a/content/renderer/media_recorder/video_track_recorder_unittest.cc b/content/renderer/media_recorder/video_track_recorder_unittest.cc
index 05cd924..ee70c84 100644
--- a/content/renderer/media_recorder/video_track_recorder_unittest.cc
+++ b/content/renderer/media_recorder/video_track_recorder_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/child/child_process.h"
diff --git a/content/renderer/pepper/pepper_broker_unittest.cc b/content/renderer/pepper/pepper_broker_unittest.cc
index 62c2574a..4012be98 100644
--- a/content/renderer/pepper/pepper_broker_unittest.cc
+++ b/content/renderer/pepper/pepper_broker_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "content/renderer/pepper/pepper_broker.h"
+#include "base/message_loop/message_loop.h"
 
 #if defined(OS_POSIX)
 #include <fcntl.h>
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2e952fd..4445469b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1932,7 +1932,8 @@
   // the document, a positive amount moves the selection towards the end of
   // the document.
   frame_->SelectRange(WebRange(range.StartOffset() + start_adjust,
-                               range.length() + end_adjust - start_adjust));
+                               range.length() + end_adjust - start_adjust),
+                      WebLocalFrame::kPreserveHandleVisibility);
 }
 
 void RenderFrameImpl::OnCollapseSelection() {
@@ -4316,14 +4317,9 @@
   if (params.src_url.spec().size() > url::kMaxURLChars)
     params.src_url = GURL();
 
-#if defined(OS_ANDROID)
-  gfx::Rect start_rect;
-  gfx::Rect end_rect;
-  GetRenderWidget()->GetSelectionBounds(&start_rect, &end_rect);
-  params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
-  params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
-#endif
-
+  blink::WebRect selection_in_window(data.selection_rect);
+  GetRenderWidget()->ConvertViewportToWindow(&selection_in_window);
+  params.selection_rect = selection_in_window;
   Send(new FrameHostMsg_ContextMenu(routing_id_, params));
 }
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index a56d9d8..58feb85 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -21,6 +21,7 @@
 #include "base/memory/memory_coordinator_client_registry.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index a5bde06d..42d9a76 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/debug/leak_annotations.h"
 #include "base/location.h"
 #include "base/memory/discardable_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/content/renderer/visual_state_browsertest.cc b/content/renderer/visual_state_browsertest.cc
index 178d538d..2b819e5 100644
--- a/content/renderer/visual_state_browsertest.cc
+++ b/content/renderer/visual_state_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index 8924eba1..a786fe4e 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -16,6 +16,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/content/shell/browser/layout_test/layout_test_browser_main.cc b/content/shell/browser/layout_test/layout_test_browser_main.cc
index 4a498ed..28a0ac7f 100644
--- a/content/shell/browser/layout_test/layout_test_browser_main.cc
+++ b/content/shell/browser/layout_test/layout_test_browser_main.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 74de055a..9d561d70a 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.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"
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc
index 081d63af..3f20c73 100644
--- a/content/shell/test_runner/event_sender.cc
+++ b/content/shell/test_runner/event_sender.cc
@@ -616,7 +616,7 @@
   void GestureTwoFingerTap(gin::Arguments* args);
   void ContinuousMouseScrollBy(gin::Arguments* args);
   void MouseMoveTo(gin::Arguments* args);
-  void MouseLeave();
+  void MouseLeave(gin::Arguments* args);
   void MouseScrollBy(gin::Arguments* args);
   void ScheduleAsynchronousClick(gin::Arguments* args);
   void ScheduleAsynchronousKeyDown(gin::Arguments* args);
@@ -1015,9 +1015,24 @@
     sender_->MouseMoveTo(args);
 }
 
-void EventSenderBindings::MouseLeave() {
-  if (sender_)
-    sender_->MouseLeave();
+void EventSenderBindings::MouseLeave(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  WebPointerProperties::PointerType pointerType =
+      WebPointerProperties::PointerType::kMouse;
+  int pointerId = kRawMousePointerId;
+
+  // Only allow pen or mouse through this API.
+  if (!getPointerType(args, false, pointerType))
+    return;
+  if (!args->PeekNext().IsEmpty()) {
+    if (!args->GetNext(&pointerId)) {
+      args->ThrowError();
+      return;
+    }
+  }
+  sender_->MouseLeave(pointerType, pointerId);
 }
 
 void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
@@ -2211,16 +2226,18 @@
   }
 }
 
-void EventSender::MouseLeave() {
+void EventSender::MouseLeave(
+    blink::WebPointerProperties::PointerType pointerType,
+    int pointerId) {
   if (force_layout_on_events_)
     widget()->UpdateAllLifecyclePhases();
 
   WebMouseEvent event(WebInputEvent::kMouseLeave,
-                      ModifiersForPointer(kRawMousePointerId),
-                      GetCurrentEventTimeSec());
-  InitMouseEvent(WebMouseEvent::Button::kNoButton, 0,
-                 current_pointer_state_[kRawMousePointerId].last_pos_,
-                 click_count_, &event);
+                      ModifiersForPointer(pointerId), GetCurrentEventTimeSec());
+  InitMouseEventGeneric(WebMouseEvent::Button::kNoButton, 0,
+                        current_pointer_state_[kRawMousePointerId].last_pos_,
+                        click_count_, pointerType, pointerId, 0.0, 0, 0,
+                        &event);
   HandleInputEventOnViewOrPopup(event);
 }
 
diff --git a/content/shell/test_runner/event_sender.h b/content/shell/test_runner/event_sender.h
index f8b4cd3..9871739 100644
--- a/content/shell/test_runner/event_sender.h
+++ b/content/shell/test_runner/event_sender.h
@@ -167,7 +167,7 @@
 
   void MouseScrollBy(gin::Arguments* args, MouseScrollType scroll_type);
   void MouseMoveTo(gin::Arguments* args);
-  void MouseLeave();
+  void MouseLeave(blink::WebPointerProperties::PointerType, int pointerId);
   void ScheduleAsynchronousClick(int button_number, int modifiers);
   void ScheduleAsynchronousKeyDown(const std::string& code_str,
                                    int modifiers,
diff --git a/dbus/object_proxy_unittest.cc b/dbus/object_proxy_unittest.cc
index 5e3d3e2e..1f5746f 100644
--- a/dbus/object_proxy_unittest.cc
+++ b/dbus/object_proxy_unittest.cc
@@ -6,6 +6,7 @@
 #include "base/bind.h"
 #include "base/files/file_descriptor_watcher_posix.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "dbus/bus.h"
 #include "dbus/test_service.h"
diff --git a/dbus/test_server.cc b/dbus/test_server.cc
index 54bb0c00..d8cb0d5 100644
--- a/dbus/test_server.cc
+++ b/dbus/test_server.cc
@@ -4,6 +4,7 @@
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/test_timeouts.h"
 #include "dbus/bus.h"
 #include "dbus/test_service.h"
diff --git a/dbus/test_service.cc b/dbus/test_service.cc
index 209b41d..8d428a3 100644
--- a/dbus/test_service.cc
+++ b/dbus/test_service.cc
@@ -11,6 +11,7 @@
 
 #include "base/bind.h"
 #include "base/guid.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/test_timeouts.h"
diff --git a/device/bluetooth/bluetooth_socket_thread.cc b/device/bluetooth/bluetooth_socket_thread.cc
index 3788916c..c9fbb8a 100644
--- a/device/bluetooth/bluetooth_socket_thread.cc
+++ b/device/bluetooth/bluetooth_socket_thread.cc
@@ -5,6 +5,7 @@
 #include "device/bluetooth/bluetooth_socket_thread.h"
 
 #include "base/lazy_instance.h"
+#include "base/message_loop/message_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread.h"
 
diff --git a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
index 2d41757..a969fb0 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/bluetooth/bluetooth_adapter.h"
diff --git a/device/bluetooth/dbus/dbus_thread_manager_linux.cc b/device/bluetooth/dbus/dbus_thread_manager_linux.cc
index adffe9b..ecaed41b 100644
--- a/device/bluetooth/dbus/dbus_thread_manager_linux.cc
+++ b/device/bluetooth/dbus/dbus_thread_manager_linux.cc
@@ -4,6 +4,7 @@
 
 #include "device/bluetooth/dbus/dbus_thread_manager_linux.h"
 
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "dbus/bus.h"
 
diff --git a/device/gamepad/gamepad_provider.cc b/device/gamepad/gamepad_provider.cc
index ab48041..d56910bd 100644
--- a/device/gamepad/gamepad_provider.cc
+++ b/device/gamepad/gamepad_provider.cc
@@ -13,6 +13,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread.h"
diff --git a/device/generic_sensor/platform_sensor_provider_linux.cc b/device/generic_sensor/platform_sensor_provider_linux.cc
index 7049b61..8193a34 100644
--- a/device/generic_sensor/platform_sensor_provider_linux.cc
+++ b/device/generic_sensor/platform_sensor_provider_linux.cc
@@ -5,6 +5,7 @@
 #include "device/generic_sensor/platform_sensor_provider_linux.h"
 
 #include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread.h"
 #include "device/generic_sensor/linux/sensor_data_linux.h"
diff --git a/device/generic_sensor/public/interfaces/BUILD.gn b/device/generic_sensor/public/interfaces/BUILD.gn
index 24aabe84..4d9f3e03 100644
--- a/device/generic_sensor/public/interfaces/BUILD.gn
+++ b/device/generic_sensor/public/interfaces/BUILD.gn
@@ -7,7 +7,6 @@
 mojom("interfaces") {
   visibility = [ "//device/generic_sensor/public/cpp" ]
   visibility_blink = [ "//third_party/WebKit/Source/*" ]
-  component_output_prefix = "generic_sensor_public_interfaces"
   export_class_attribute = "DEVICE_GENERIC_SENSOR_PUBLIC_EXPORT"
   export_define = "DEVICE_GENERIC_SENSOR_PUBLIC_IMPLEMENTATION=1"
   export_header =
diff --git a/device/geolocation/geolocation_provider_impl_unittest.cc b/device/geolocation/geolocation_provider_impl_unittest.cc
index 81ba5fe..190c348 100644
--- a/device/geolocation/geolocation_provider_impl_unittest.cc
+++ b/device/geolocation/geolocation_provider_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
diff --git a/device/geolocation/location_arbitrator_unittest.cc b/device/geolocation/location_arbitrator_unittest.cc
index 8bb36397..f19b0c26 100644
--- a/device/geolocation/location_arbitrator_unittest.cc
+++ b/device/geolocation/location_arbitrator_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "device/geolocation/fake_access_token_store.h"
 #include "device/geolocation/fake_location_provider.h"
 #include "device/geolocation/geolocation_delegate.h"
diff --git a/device/geolocation/network_location_provider_unittest.cc b/device/geolocation/network_location_provider_unittest.cc
index 2d0d754..0129625 100644
--- a/device/geolocation/network_location_provider_unittest.cc
+++ b/device/geolocation/network_location_provider_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
diff --git a/device/hid/hid_connection_linux.cc b/device/hid/hid_connection_linux.cc
index 62d06c3..fd5fc01 100644
--- a/device/hid/hid_connection_linux.cc
+++ b/device/hid/hid_connection_linux.cc
@@ -32,37 +32,37 @@
 
 namespace device {
 
-class HidConnectionLinux::FileThreadHelper {
+class HidConnectionLinux::BlockingTaskHelper {
  public:
-  FileThreadHelper(base::ScopedFD fd,
-                   scoped_refptr<HidDeviceInfo> device_info,
-                   base::WeakPtr<HidConnectionLinux> connection)
+  BlockingTaskHelper(base::ScopedFD fd,
+                     scoped_refptr<HidDeviceInfo> device_info,
+                     base::WeakPtr<HidConnectionLinux> connection)
       : fd_(std::move(fd)),
         connection_(connection),
         origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-    sequence_checker_.DetachFromSequence();
+    DETACH_FROM_SEQUENCE(sequence_checker_);
     // Report buffers must always have room for the report ID.
     report_buffer_size_ = device_info->max_input_report_size() + 1;
     has_report_id_ = device_info->has_report_id();
   }
 
-  ~FileThreadHelper() { DCHECK(sequence_checker_.CalledOnValidSequence()); }
+  ~BlockingTaskHelper() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
 
   // Starts the FileDescriptorWatcher that reads input events from the device.
   // Must be called on a thread that has a base::MessageLoopForIO.
   void Start() {
-    DCHECK(sequence_checker_.CalledOnValidSequence());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     base::ThreadRestrictions::AssertIOAllowed();
 
     file_watcher_ = base::FileDescriptorWatcher::WatchReadable(
-        fd_.get(), base::Bind(&FileThreadHelper::OnFileCanReadWithoutBlocking,
+        fd_.get(), base::Bind(&BlockingTaskHelper::OnFileCanReadWithoutBlocking,
                               base::Unretained(this)));
   }
 
   void Write(scoped_refptr<net::IOBuffer> buffer,
              size_t size,
              const WriteCallback& callback) {
-    DCHECK(sequence_checker_.CalledOnValidSequence());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     ssize_t result = HANDLE_EINTR(write(fd_.get(), buffer->data(), size));
     if (result < 0) {
       HID_PLOG(EVENT) << "Write failed";
@@ -77,7 +77,7 @@
   void GetFeatureReport(uint8_t report_id,
                         scoped_refptr<net::IOBufferWithSize> buffer,
                         const ReadCallback& callback) {
-    DCHECK(sequence_checker_.CalledOnValidSequence());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     int result = HANDLE_EINTR(
         ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data()));
     if (result < 0) {
@@ -103,7 +103,7 @@
   void SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
                          size_t size,
                          const WriteCallback& callback) {
-    DCHECK(sequence_checker_.CalledOnValidSequence());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     int result =
         HANDLE_EINTR(ioctl(fd_.get(), HIDIOCSFEATURE(size), buffer->data()));
     if (result < 0) {
@@ -116,7 +116,7 @@
 
  private:
   void OnFileCanReadWithoutBlocking() {
-    DCHECK(sequence_checker_.CalledOnValidSequence());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
     scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_));
     char* data = buffer->data();
@@ -151,7 +151,7 @@
                               connection_, buffer, bytes_read));
   }
 
-  base::SequenceChecker sequence_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
   base::ScopedFD fd_;
   size_t report_buffer_size_;
   bool has_report_id_;
@@ -159,7 +159,7 @@
   const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
   std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_;
 
-  DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
+  DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper);
 };
 
 HidConnectionLinux::HidConnectionLinux(
@@ -169,15 +169,15 @@
     : HidConnection(device_info),
       blocking_task_runner_(std::move(blocking_task_runner)),
       weak_factory_(this) {
-  helper_ = base::MakeUnique<FileThreadHelper>(std::move(fd), device_info,
-                                               weak_factory_.GetWeakPtr());
+  helper_ = base::MakeUnique<BlockingTaskHelper>(std::move(fd), device_info,
+                                                 weak_factory_.GetWeakPtr());
   blocking_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
+      base::Bind(&BlockingTaskHelper::Start, base::Unretained(helper_.get())));
 }
 
 HidConnectionLinux::~HidConnectionLinux() {
-  DCHECK(sequence_checker_.CalledOnValidSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void HidConnectionLinux::PlatformClose() {
@@ -207,7 +207,7 @@
   // buffer can be used directly.
   blocking_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FileThreadHelper::Write, base::Unretained(helper_.get()),
+      base::Bind(&BlockingTaskHelper::Write, base::Unretained(helper_.get()),
                  buffer, size, callback));
 }
 
@@ -223,7 +223,7 @@
 
   blocking_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FileThreadHelper::GetFeatureReport,
+      base::Bind(&BlockingTaskHelper::GetFeatureReport,
                  base::Unretained(helper_.get()), report_id, buffer, callback));
 }
 
@@ -235,7 +235,7 @@
   // buffer can be used directly.
   blocking_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FileThreadHelper::SendFeatureReport,
+      base::Bind(&BlockingTaskHelper::SendFeatureReport,
                  base::Unretained(helper_.get()), buffer, size, callback));
 }
 
diff --git a/device/hid/hid_connection_linux.h b/device/hid/hid_connection_linux.h
index 574c732..1231d58 100644
--- a/device/hid/hid_connection_linux.h
+++ b/device/hid/hid_connection_linux.h
@@ -31,7 +31,7 @@
 
  private:
   friend class base::RefCountedThreadSafe<HidConnectionLinux>;
-  class FileThreadHelper;
+  class BlockingTaskHelper;
 
   ~HidConnectionLinux() override;
 
@@ -50,17 +50,17 @@
   void ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, size_t size);
   void ProcessReadQueue();
 
-  // This object lives on the sequence to which |blocking_task_runner_| posts
+  // |helper_| lives on the sequence to which |blocking_task_runner_| posts
   // tasks so all calls must be posted there including this object's
   // destruction.
-  std::unique_ptr<FileThreadHelper> helper_;
+  std::unique_ptr<BlockingTaskHelper> helper_;
 
   const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
   std::queue<PendingHidReport> pending_reports_;
   std::queue<PendingHidRead> pending_reads_;
 
-  base::SequenceChecker sequence_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<HidConnectionLinux> weak_factory_;
 
diff --git a/device/hid/hid_connection_unittest.cc b/device/hid/hid_connection_unittest.cc
index f05d79d..c9902bb 100644
--- a/device/hid/hid_connection_unittest.cc
+++ b/device/hid/hid_connection_unittest.cc
@@ -12,6 +12,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/device/hid/hid_service.cc b/device/hid/hid_service.cc
index cee3980..d2cad1d 100644
--- a/device/hid/hid_service.cc
+++ b/device/hid/hid_service.cc
@@ -36,10 +36,13 @@
     scoped_refptr<HidDeviceInfo> device_info) {
 }
 
+// static
+constexpr base::TaskTraits HidService::kBlockingTaskTraits;
+
 std::unique_ptr<HidService> HidService::Create(
     scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
 #if defined(OS_LINUX) && defined(USE_UDEV)
-  return base::WrapUnique(new HidServiceLinux(file_task_runner));
+  return base::WrapUnique(new HidServiceLinux());
 #elif defined(OS_MACOSX)
   return base::WrapUnique(new HidServiceMac(file_task_runner));
 #elif defined(OS_WIN)
diff --git a/device/hid/hid_service.h b/device/hid/hid_service.h
index c46ce13..ee70446 100644
--- a/device/hid/hid_service.h
+++ b/device/hid/hid_service.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/threading/thread_checker.h"
 #include "device/hid/hid_device_info.h"
 
@@ -41,10 +42,14 @@
     virtual void OnDeviceRemovedCleanup(scoped_refptr<HidDeviceInfo> info);
   };
 
-  typedef base::Callback<void(const std::vector<scoped_refptr<HidDeviceInfo>>&)>
-      GetDevicesCallback;
-  typedef base::Callback<void(scoped_refptr<HidConnection> connection)>
-      ConnectCallback;
+  using GetDevicesCallback =
+      base::Callback<void(const std::vector<scoped_refptr<HidDeviceInfo>>&)>;
+  using ConnectCallback =
+      base::Callback<void(scoped_refptr<HidConnection> connection)>;
+
+  static constexpr base::TaskTraits kBlockingTaskTraits = {
+      base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
 
   // This function should be called on a thread with a MessageLoopForUI and be
   // passed the task runner for a thread with a MessageLoopForIO.
diff --git a/device/hid/hid_service_linux.cc b/device/hid/hid_service_linux.cc
index 6b52446..75a31561 100644
--- a/device/hid/hid_service_linux.cc
+++ b/device/hid/hid_service_linux.cc
@@ -20,17 +20,18 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/scoped_observer.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/device_event_log/device_event_log.h"
-#include "device/base/device_monitor_linux.h"
 #include "device/hid/hid_connection_linux.h"
 #include "device/hid/hid_device_info_linux.h"
 #include "device/udev_linux/scoped_udev.h"
+#include "device/udev_linux/udev_watcher.h"
 
 #if defined(OS_CHROMEOS)
 #include "base/sys_info.h"
@@ -52,13 +53,12 @@
 
 struct HidServiceLinux::ConnectParams {
   ConnectParams(scoped_refptr<HidDeviceInfoLinux> device_info,
-                const ConnectCallback& callback,
-                scoped_refptr<base::SequencedTaskRunner> task_runner,
-                scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
+                const ConnectCallback& callback)
       : device_info(std::move(device_info)),
         callback(callback),
-        task_runner(std::move(task_runner)),
-        blocking_task_runner(std::move(blocking_task_runner)) {}
+        task_runner(base::ThreadTaskRunnerHandle::Get()),
+        blocking_task_runner(
+            base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)) {}
   ~ConnectParams() {}
 
   scoped_refptr<HidDeviceInfoLinux> device_info;
@@ -68,67 +68,59 @@
   base::ScopedFD fd;
 };
 
-class HidServiceLinux::FileThreadHelper : public DeviceMonitorLinux::Observer {
+class HidServiceLinux::BlockingTaskHelper : public UdevWatcher::Observer {
  public:
-  FileThreadHelper(base::WeakPtr<HidServiceLinux> service,
-                   scoped_refptr<base::SequencedTaskRunner> task_runner)
-      : observer_(this), service_(service), task_runner_(task_runner) {
-    thread_checker_.DetachFromThread();
+  BlockingTaskHelper(base::WeakPtr<HidServiceLinux> service)
+      : service_(std::move(service)),
+        task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+    DETACH_FROM_SEQUENCE(sequence_checker_);
   }
 
-  ~FileThreadHelper() override {
-    DCHECK(thread_checker_.CalledOnValidThread());
+  ~BlockingTaskHelper() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   }
 
   void Start() {
     base::ThreadRestrictions::AssertIOAllowed();
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-    DeviceMonitorLinux* monitor = DeviceMonitorLinux::GetInstance();
-    observer_.Add(monitor);
-    monitor->Enumerate(
-        base::Bind(&FileThreadHelper::OnDeviceAdded, base::Unretained(this)));
+    watcher_ = UdevWatcher::StartWatching(this);
+    watcher_->EnumerateExistingDevices();
     task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&HidServiceLinux::FirstEnumerationComplete, service_));
   }
 
  private:
-  // DeviceMonitorLinux::Observer:
-  void OnDeviceAdded(udev_device* device) override {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    const char* device_path = udev_device_get_syspath(device);
-    if (!device_path) {
+  // UdevWatcher::Observer
+  void OnDeviceAdded(ScopedUdevDevicePtr device) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    const char* device_path = udev_device_get_syspath(device.get());
+    if (!device_path)
       return;
-    }
     HidDeviceId device_id = device_path;
 
-    const char* subsystem = udev_device_get_subsystem(device);
-    if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0) {
+    const char* subsystem = udev_device_get_subsystem(device.get());
+    if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0)
       return;
-    }
 
-    const char* str_property = udev_device_get_devnode(device);
-    if (!str_property) {
+    const char* str_property = udev_device_get_devnode(device.get());
+    if (!str_property)
       return;
-    }
     std::string device_node = str_property;
 
-    udev_device* parent = udev_device_get_parent(device);
-    if (!parent) {
+    udev_device* parent = udev_device_get_parent(device.get());
+    if (!parent)
       return;
-    }
 
     const char* hid_id = udev_device_get_property_value(parent, kHIDID);
-    if (!hid_id) {
+    if (!hid_id)
       return;
-    }
 
     std::vector<std::string> parts = base::SplitString(
         hid_id, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-    if (parts.size() != 3) {
+    if (parts.size() != 3)
       return;
-    }
 
     uint32_t int_property = 0;
     if (!HexStringToUInt(base::StringPiece(parts[1]), &int_property) ||
@@ -145,27 +137,22 @@
 
     std::string serial_number;
     str_property = udev_device_get_property_value(parent, kHIDUnique);
-    if (str_property != NULL) {
+    if (str_property)
       serial_number = str_property;
-    }
 
     std::string product_name;
     str_property = udev_device_get_property_value(parent, kHIDName);
-    if (str_property != NULL) {
+    if (str_property)
       product_name = str_property;
-    }
 
     const char* parent_sysfs_path = udev_device_get_syspath(parent);
-    if (!parent_sysfs_path) {
+    if (!parent_sysfs_path)
       return;
-    }
     base::FilePath report_descriptor_path =
         base::FilePath(parent_sysfs_path).Append(kSysfsReportDescriptorKey);
     std::string report_descriptor_str;
-    if (!base::ReadFileToString(report_descriptor_path,
-                                &report_descriptor_str)) {
+    if (!base::ReadFileToString(report_descriptor_path, &report_descriptor_str))
       return;
-    }
 
     scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfoLinux(
         device_id, device_node, vendor_id, product_id, product_name,
@@ -178,9 +165,9 @@
                                                  service_, device_info));
   }
 
-  void OnDeviceRemoved(udev_device* device) override {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    const char* device_path = udev_device_get_syspath(device);
+  void OnDeviceRemoved(ScopedUdevDevicePtr device) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    const char* device_path = udev_device_get_syspath(device.get());
     if (device_path) {
       task_runner_->PostTask(
           FROM_HERE, base::Bind(&HidServiceLinux::RemoveDevice, service_,
@@ -188,26 +175,24 @@
     }
   }
 
-  base::ThreadChecker thread_checker_;
-  ScopedObserver<DeviceMonitorLinux, DeviceMonitorLinux::Observer> observer_;
+  SEQUENCE_CHECKER(sequence_checker_);
+  std::unique_ptr<UdevWatcher> watcher_;
 
   // This weak pointer is only valid when checked on this task runner.
   base::WeakPtr<HidServiceLinux> service_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
-  DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
+  DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper);
 };
 
-HidServiceLinux::HidServiceLinux(
-    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      blocking_task_runner_(std::move(blocking_task_runner)),
+HidServiceLinux::HidServiceLinux()
+    : blocking_task_runner_(
+          base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)),
       weak_factory_(this) {
-  helper_ = base::MakeUnique<FileThreadHelper>(weak_factory_.GetWeakPtr(),
-                                               task_runner_);
+  helper_ = base::MakeUnique<BlockingTaskHelper>(weak_factory_.GetWeakPtr());
   blocking_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
+      base::Bind(&BlockingTaskHelper::Start, base::Unretained(helper_.get())));
 }
 
 HidServiceLinux::~HidServiceLinux() {
@@ -215,9 +200,7 @@
 }
 
 void HidServiceLinux::Shutdown() {
-  const bool did_post_task =
-      blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release());
-  DCHECK(did_post_task);
+  blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release());
   HidService::Shutdown();
 }
 
@@ -227,14 +210,14 @@
 
   const auto& map_entry = devices().find(device_id);
   if (map_entry == devices().end()) {
-    task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(callback, nullptr));
     return;
   }
   scoped_refptr<HidDeviceInfoLinux> device_info =
       static_cast<HidDeviceInfoLinux*>(map_entry->second.get());
 
-  std::unique_ptr<ConnectParams> params(new ConnectParams(
-      device_info, callback, task_runner_, blocking_task_runner_));
+  auto params = base::MakeUnique<ConnectParams>(device_info, callback);
 
 #if defined(OS_CHROMEOS)
   chromeos::PermissionBrokerClient* client =
@@ -248,7 +231,9 @@
       base::Bind(&HidServiceLinux::OnPathOpenComplete, base::Passed(&params)),
       error_callback);
 #else
-  blocking_task_runner_->PostTask(
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner =
+      params->blocking_task_runner;
+  blocking_task_runner->PostTask(
       FROM_HERE, base::Bind(&HidServiceLinux::OpenOnBlockingThread,
                             base::Passed(&params)));
 #endif  // defined(OS_CHROMEOS)
@@ -332,9 +317,9 @@
 // static
 void HidServiceLinux::CreateConnection(std::unique_ptr<ConnectParams> params) {
   DCHECK(params->fd.is_valid());
-  params->callback.Run(make_scoped_refptr(new HidConnectionLinux(
+  params->callback.Run(base::MakeShared<HidConnectionLinux>(
       std::move(params->device_info), std::move(params->fd),
-      std::move(params->blocking_task_runner))));
+      std::move(params->blocking_task_runner)));
 }
 
 }  // namespace device
diff --git a/device/hid/hid_service_linux.h b/device/hid/hid_service_linux.h
index 17616ba..89aafbda 100644
--- a/device/hid/hid_service_linux.h
+++ b/device/hid/hid_service_linux.h
@@ -19,8 +19,7 @@
 
 class HidServiceLinux : public HidService {
  public:
-  HidServiceLinux(
-      scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
+  HidServiceLinux();
   ~HidServiceLinux() override;
 
   // HidService:
@@ -30,7 +29,7 @@
 
  private:
   struct ConnectParams;
-  class FileThreadHelper;
+  class BlockingTaskHelper;
 
   // These functions implement the process of locating, requesting access to and
   // opening a device. Because this operation crosses multiple threads these
@@ -49,12 +48,11 @@
   static void FinishOpen(std::unique_ptr<ConnectParams> params);
   static void CreateConnection(std::unique_ptr<ConnectParams> params);
 
-  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
-  // The helper lives on the FILE thread and holds a weak reference back to the
-  // service that owns it.
-  std::unique_ptr<FileThreadHelper> helper_;
+  // |helper_| lives on the sequence |blocking_task_runner_| posts to and holds
+  // a weak reference back to the service that owns it.
+  std::unique_ptr<BlockingTaskHelper> helper_;
   base::WeakPtrFactory<HidServiceLinux> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(HidServiceLinux);
diff --git a/device/u2f/u2f_hid_device_unittest.cc b/device/u2f/u2f_hid_device_unittest.cc
index 7bc1e95..9927850 100644
--- a/device/u2f/u2f_hid_device_unittest.cc
+++ b/device/u2f/u2f_hid_device_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_io_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/device/usb/mojo/device_impl.cc b/device/usb/mojo/device_impl.cc
index 2d8f7c4..6bbb81b 100644
--- a/device/usb/mojo/device_impl.cc
+++ b/device/usb/mojo/device_impl.cc
@@ -142,40 +142,30 @@
     UsbControlTransferRecipient recipient,
     uint16_t index) {
   DCHECK(device_handle_);
-  const UsbConfigDescriptor* config = device_->active_configuration();
 
-  if (!permission_provider_)
-    return false;
-
-  if (recipient == UsbControlTransferRecipient::INTERFACE ||
-      recipient == UsbControlTransferRecipient::ENDPOINT) {
-    if (!config)
-      return false;
-
-    const UsbInterfaceDescriptor* interface = nullptr;
-    if (recipient == UsbControlTransferRecipient::ENDPOINT) {
-      interface = device_handle_->FindInterfaceByEndpoint(index & 0xff);
-    } else {
-      auto interface_it =
-          std::find_if(config->interfaces.begin(), config->interfaces.end(),
-                       [index](const UsbInterfaceDescriptor& this_iface) {
-                         return this_iface.interface_number == (index & 0xff);
-                       });
-      if (interface_it != config->interfaces.end())
-        interface = &*interface_it;
-    }
-    if (interface == nullptr)
-      return false;
-
-    return permission_provider_->HasFunctionPermission(
-        interface->first_interface, config->configuration_value, device_);
-  } else if (config) {
-    return permission_provider_->HasConfigurationPermission(
-        config->configuration_value, device_);
-  } else {
-    // Client must already have device permission to have gotten this far.
+  if (recipient != UsbControlTransferRecipient::INTERFACE &&
+      recipient != UsbControlTransferRecipient::ENDPOINT) {
     return true;
   }
+
+  const UsbConfigDescriptor* config = device_->active_configuration();
+  if (!config)
+    return false;
+
+  const UsbInterfaceDescriptor* interface = nullptr;
+  if (recipient == UsbControlTransferRecipient::ENDPOINT) {
+    interface = device_handle_->FindInterfaceByEndpoint(index & 0xff);
+  } else {
+    auto interface_it =
+        std::find_if(config->interfaces.begin(), config->interfaces.end(),
+                     [index](const UsbInterfaceDescriptor& this_iface) {
+                       return this_iface.interface_number == (index & 0xff);
+                     });
+    if (interface_it != config->interfaces.end())
+      interface = &*interface_it;
+  }
+
+  return interface != nullptr;
 }
 
 // static
@@ -196,8 +186,7 @@
 
 void DeviceImpl::OnPermissionGrantedForOpen(const OpenCallback& callback,
                                             bool granted) {
-  if (granted && permission_provider_ &&
-      permission_provider_->HasDevicePermission(device_)) {
+  if (granted) {
     device_->Open(
         base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback));
   } else {
@@ -218,13 +207,8 @@
     return;
   }
 
-  if (permission_provider_ &&
-      permission_provider_->HasDevicePermission(device_)) {
-    device_->Open(
-        base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback));
-  } else {
-    callback.Run(mojom::UsbOpenDeviceError::ACCESS_DENIED);
-  }
+  device_->Open(
+      base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback));
 }
 
 void DeviceImpl::Close(const CloseCallback& callback) {
@@ -239,12 +223,7 @@
     return;
   }
 
-  if (permission_provider_ &&
-      permission_provider_->HasConfigurationPermission(value, device_)) {
-    device_handle_->SetConfiguration(value, callback);
-  } else {
-    callback.Run(false);
-  }
+  device_handle_->SetConfiguration(value, callback);
 }
 
 void DeviceImpl::ClaimInterface(uint8_t interface_number,
@@ -270,14 +249,7 @@
     return;
   }
 
-  if (permission_provider_ &&
-      permission_provider_->HasFunctionPermission(interface_it->first_interface,
-                                                  config->configuration_value,
-                                                  device_)) {
-    device_handle_->ClaimInterface(interface_number, callback);
-  } else {
-    callback.Run(false);
-  }
+  device_handle_->ClaimInterface(interface_number, callback);
 }
 
 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
diff --git a/device/usb/mojo/device_impl_unittest.cc b/device/usb/mojo/device_impl_unittest.cc
index 68362907..3d42e9d 100644
--- a/device/usb/mojo/device_impl_unittest.cc
+++ b/device/usb/mojo/device_impl_unittest.cc
@@ -446,6 +446,7 @@
   EXPECT_FALSE(is_device_open());
 
   EXPECT_CALL(mock_device(), Open(_));
+  EXPECT_CALL(permission_provider(), IncrementConnectionCount());
 
   {
     base::RunLoop loop;
@@ -463,6 +464,7 @@
   }
 
   EXPECT_CALL(mock_handle(), Close());
+  EXPECT_CALL(permission_provider(), DecrementConnectionCount());
 }
 
 TEST_F(USBDeviceImplTest, Close) {
@@ -503,7 +505,6 @@
   }
 
   EXPECT_CALL(mock_handle(), SetConfiguration(42, _));
-  EXPECT_CALL(permission_provider(), HasConfigurationPermission(42, _));
 
   {
     // SetConfiguration should fail because 42 is not a valid mock
@@ -530,7 +531,6 @@
   }
 
   EXPECT_CALL(mock_handle(), SetConfiguration(42, _));
-  EXPECT_CALL(permission_provider(), HasConfigurationPermission(42, _));
 
   AddMockConfig(ConfigBuilder(42));
 
@@ -598,7 +598,6 @@
   AddMockConfig(ConfigBuilder(1).AddInterface(1, 0, 1, 2, 3));
 
   EXPECT_CALL(mock_handle(), SetConfiguration(1, _));
-  EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _));
 
   {
     base::RunLoop loop;
@@ -616,7 +615,6 @@
   }
 
   EXPECT_CALL(mock_handle(), ClaimInterface(1, _));
-  EXPECT_CALL(permission_provider(), HasFunctionPermission(1, 1, _));
 
   {
     base::RunLoop loop;
@@ -701,7 +699,6 @@
   AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3));
 
   EXPECT_CALL(mock_handle(), SetConfiguration(1, _));
-  EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _));
 
   {
     base::RunLoop loop;
@@ -722,7 +719,6 @@
                               UsbControlTransferType::STANDARD,
                               UsbControlTransferRecipient::DEVICE, 5, 6, 7, _,
                               _, 0, _));
-  EXPECT_CALL(permission_provider(), HasConfigurationPermission(1, _));
 
   {
     auto params = mojom::UsbControlTransferParams::New();
@@ -747,7 +743,6 @@
                               UsbControlTransferType::STANDARD,
                               UsbControlTransferRecipient::INTERFACE, 5, 6, 7,
                               _, _, 0, _));
-  EXPECT_CALL(permission_provider(), HasFunctionPermission(7, 1, _));
 
   {
     auto params = mojom::UsbControlTransferParams::New();
diff --git a/device/usb/mojo/mock_permission_provider.cc b/device/usb/mojo/mock_permission_provider.cc
index e45b0f6d..3af59f6 100644
--- a/device/usb/mojo/mock_permission_provider.cc
+++ b/device/usb/mojo/mock_permission_provider.cc
@@ -17,8 +17,6 @@
 
 MockPermissionProvider::MockPermissionProvider() : weak_factory_(this) {
   ON_CALL(*this, HasDevicePermission(_)).WillByDefault(Return(true));
-  ON_CALL(*this, HasConfigurationPermission(_, _)).WillByDefault(Return(true));
-  ON_CALL(*this, HasFunctionPermission(_, _, _)).WillByDefault(Return(true));
 }
 
 MockPermissionProvider::~MockPermissionProvider() {}
diff --git a/device/usb/mojo/mock_permission_provider.h b/device/usb/mojo/mock_permission_provider.h
index 26521e2..c558323 100644
--- a/device/usb/mojo/mock_permission_provider.h
+++ b/device/usb/mojo/mock_permission_provider.h
@@ -23,13 +23,6 @@
   base::WeakPtr<PermissionProvider> GetWeakPtr();
   MOCK_CONST_METHOD1(HasDevicePermission,
                      bool(scoped_refptr<const UsbDevice> device));
-  MOCK_CONST_METHOD2(HasConfigurationPermission,
-                     bool(uint8_t requested_configuration,
-                          scoped_refptr<const UsbDevice> device));
-  MOCK_CONST_METHOD3(HasFunctionPermission,
-                     bool(uint8_t requested_function,
-                          uint8_t configuration_value,
-                          scoped_refptr<const UsbDevice> device));
 
   MOCK_METHOD0(IncrementConnectionCount, void());
   MOCK_METHOD0(DecrementConnectionCount, void());
diff --git a/device/usb/mojo/permission_provider.h b/device/usb/mojo/permission_provider.h
index 008fdc3..5bb6a71 100644
--- a/device/usb/mojo/permission_provider.h
+++ b/device/usb/mojo/permission_provider.h
@@ -5,8 +5,6 @@
 #ifndef DEVICE_USB_MOJO_PERMISSION_PROVIDER_H_
 #define DEVICE_USB_MOJO_PERMISSION_PROVIDER_H_
 
-#include <stdint.h>
-
 #include "base/memory/ref_counted.h"
 
 namespace device {
@@ -24,13 +22,6 @@
 
   virtual bool HasDevicePermission(
       scoped_refptr<const UsbDevice> device) const = 0;
-  virtual bool HasConfigurationPermission(
-      uint8_t requested_configuration,
-      scoped_refptr<const UsbDevice> device) const = 0;
-  virtual bool HasFunctionPermission(
-      uint8_t requested_function,
-      uint8_t configuration_value,
-      scoped_refptr<const UsbDevice> device) const = 0;
   virtual void IncrementConnectionCount() = 0;
   virtual void DecrementConnectionCount() = 0;
 };
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index 62a3d7d..10b1226 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -116,10 +116,7 @@
   }
 }
 
-mojom_component("mojo_bindings") {
-  output_prefix = "device_vr_mojo_bindings"
-  macro_prefix = "DEVICE_VR_MOJO_BINDINGS"
-
+mojom("mojo_bindings") {
   sources = [
     "vr_service.mojom",
   ]
@@ -129,6 +126,10 @@
     "//mojo/common:common_custom_types",
   ]
 
+  export_class_attribute = "DEVICE_VR_EXPORT"
+  export_define = "DEVICE_VR_IMPLEMENTATION=1"
+  export_header = "device/vr/vr_export.h"
+
   # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
   use_once_callback = false
 }
diff --git a/docs/android_accessing_cpp_enums_in_java.md b/docs/android_accessing_cpp_enums_in_java.md
index 4cc5fcf..fb3382e 100644
--- a/docs/android_accessing_cpp_enums_in_java.md
+++ b/docs/android_accessing_cpp_enums_in_java.md
@@ -70,15 +70,14 @@
     import java.lang.annotation.Retention;
     import java.lang.annotation.RetentionPolicy;
 
-    public class FooBar {
-      @IntDef({
-          A, B, C
-      })
-      @Retention(RetentionPolicy.SOURCE)
-      public @interface FooBarEnum {}
-      public static final int A = 0;
-      public static final int B = 1;
-      public static final int C = 1;
+    @IntDef({
+        FooBar.A, FooBar.B, FooBar.C
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FooBar {
+      int A = 0;
+      int B = 1;
+      int C = 1;
     }
     ```
 
@@ -130,14 +129,14 @@
 
     ```java
     ...
-    public class CommentEnum {
+    public @interface CommentEnum {
       ...
       /**
        * This comment will be preserved.
        */
-      public static final int ONE = 0;
-      public static final int TWO = 1;
-      public static final int THREE = 2;
+      int ONE = 0;
+      int TWO = 1;
+      int THREE = 2;
     }
     ```
 
diff --git a/docs/ios/build_instructions.md b/docs/ios/build_instructions.md
index 9aa2539..b841bee 100644
--- a/docs/ios/build_instructions.md
+++ b/docs/ios/build_instructions.md
@@ -260,6 +260,8 @@
 
 ### Improving performance of `git status`
 
+#### Increase the vnode cache size
+
 `git status` is used frequently to determine the status of your checkout.  Due
 to the large number of files in Chromium's checkout, `git status` performance
 can be quite variable.  Increasing the system's vnode cache appears to help.
@@ -286,8 +288,22 @@
 
 Or edit the file directly.
 
-If `git --version` reports 2.6 or higher, the following may also improve
-performance of `git status`:
+#### Configure git to use an untracked cache
+
+If `git --version` reports 2.8 or higher, try running
+
+```shell
+$ git update-index --test-untracked-cache
+```
+
+If the output ends with `OK`, then the following may also improve performance of
+`git status`:
+
+```shell
+$ git config core.untrackedCache true
+```
+
+If `git --version` reports 2.6 or higher, but below 2.8, you can instead run
 
 ```shell
 $ git update-index --untracked-cache
diff --git a/docs/mac_build_instructions.md b/docs/mac_build_instructions.md
index 646b64b..1a9824a6 100644
--- a/docs/mac_build_instructions.md
+++ b/docs/mac_build_instructions.md
@@ -231,6 +231,8 @@
 
 ### Improving performance of `git status`
 
+#### Increase the vnode cache size
+
 `git status` is used frequently to determine the status of your checkout.  Due
 to the large number of files in Chromium's checkout, `git status` performance
 can be quite variable.  Increasing the system's vnode cache appears to help. By
@@ -257,8 +259,22 @@
 
 Or edit the file directly.
 
-If `git --version` reports 2.6 or higher, the following may also improve
-performance of `git status`:
+#### Configure git to use an untracked cache
+
+If `git --version` reports 2.8 or higher, try running
+
+```shell
+$ git update-index --test-untracked-cache
+```
+
+If the output ends with `OK`, then the following may also improve performance of
+`git status`:
+
+```shell
+$ git config core.untrackedCache true
+```
+
+If `git --version` reports 2.6 or higher, but below 2.8, you can instead run
 
 ```shell
 $ git update-index --untracked-cache
diff --git a/extensions/common/one_shot_event_unittest.cc b/extensions/common/one_shot_event_unittest.cc
index 6393f9a..f2096198 100644
--- a/extensions/common/one_shot_event_unittest.cc
+++ b/extensions/common/one_shot_event_unittest.cc
@@ -5,6 +5,7 @@
 #include "extensions/common/one_shot_event.h"
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index a76f6237..2ac6389 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
diff --git a/extensions/test/extension_test_message_listener.cc b/extensions/test/extension_test_message_listener.cc
index 5b084f78..2c08d88 100644
--- a/extensions/test/extension_test_message_listener.cc
+++ b/extensions/test/extension_test_message_listener.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/test/extension_test_message_listener.h"
 
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "content/public/browser/notification_service.h"
diff --git a/google_apis/gaia/oauth2_token_service_request_unittest.cc b/google_apis/gaia/oauth2_token_service_request_unittest.cc
index 8c019b9..2c6f828 100644
--- a/google_apis/gaia/oauth2_token_service_request_unittest.cc
+++ b/google_apis/gaia/oauth2_token_service_request_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/google_apis/gcm/base/socket_stream_unittest.cc b/google_apis/gcm/base/socket_stream_unittest.cc
index d82ebb05..b8f02fe4 100644
--- a/google_apis/gcm/base/socket_stream_unittest.cc
+++ b/google_apis/gcm/base/socket_stream_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
 #include "net/base/ip_address.h"
diff --git a/google_apis/gcm/engine/connection_handler_impl_unittest.cc b/google_apis/gcm/engine/connection_handler_impl_unittest.cc
index 40b6777..447c9be 100644
--- a/google_apis/gcm/engine/connection_handler_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_handler_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/test_timeouts.h"
diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
index 3489ea8..0b240da 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc
@@ -14,6 +14,7 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc
index 6590c17..f202c93 100644
--- a/gpu/command_buffer/client/fenced_allocator_test.cc
+++ b/gpu/command_buffer/client/fenced_allocator_test.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/aligned_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/client/fenced_allocator.h"
diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc
index 26124d39..e5040fab6 100644
--- a/gpu/command_buffer/client/ring_buffer_test.cc
+++ b/gpu/command_buffer/client/ring_buffer_test.cc
@@ -12,6 +12,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
diff --git a/gpu/ipc/service/child_window_win.cc b/gpu/ipc/service/child_window_win.cc
index 6c1dfdc9..82d59d0 100644
--- a/gpu/ipc/service/child_window_win.cc
+++ b/gpu/ipc/service/child_window_win.cc
@@ -8,6 +8,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "base/win/scoped_hdc.h"
 #include "base/win/wrapped_window_proc.h"
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index c21bb2c..21a440a 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -10,6 +10,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/public/app/content_main.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/headless/lib/frame_id_browsertest.cc b/headless/lib/frame_id_browsertest.cc
index e8c7c9b..cfb54de4 100644
--- a/headless/lib/frame_id_browsertest.cc
+++ b/headless/lib/frame_id_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/public/test/browser_test.h"
 #include "headless/lib/browser/headless_browser_context_impl.h"
diff --git a/headless/lib/headless_devtools_client_browsertest.cc b/headless/lib/headless_devtools_client_browsertest.cc
index 21028f2..161d8301 100644
--- a/headless/lib/headless_devtools_client_browsertest.cc
+++ b/headless/lib/headless_devtools_client_browsertest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/json/json_reader.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
diff --git a/headless/public/util/deterministic_dispatcher_test.cc b/headless/public/util/deterministic_dispatcher_test.cc
index 7c2c6049..48b30e29 100644
--- a/headless/public/util/deterministic_dispatcher_test.cc
+++ b/headless/public/util/deterministic_dispatcher_test.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #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 "headless/public/util/navigation_request.h"
diff --git a/headless/public/util/expedited_dispatcher_test.cc b/headless/public/util/expedited_dispatcher_test.cc
index 54f5249..dacc82d 100644
--- a/headless/public/util/expedited_dispatcher_test.cc
+++ b/headless/public/util/expedited_dispatcher_test.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #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 "headless/public/util/navigation_request.h"
diff --git a/headless/public/util/generic_url_request_job_test.cc b/headless/public/util/generic_url_request_job_test.cc
index 3fe0e5569..dc7375f 100644
--- a/headless/public/util/generic_url_request_job_test.cc
+++ b/headless/public/util/generic_url_request_job_test.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.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/stringprintf.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 25d848f..3139afc 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1516,6 +1516,9 @@
       <message name="IDS_IOS_SYSTEM_MAIL_APP" desc="Name of iOS system-provided Mail app. Note that this is not consistently translated for all locales, e.g. it is still 'Mail' (in English) for French locale, but is translated to '邮件' for Chinese locale. [Length: 10em]">
         Mail
       </message>
+      <message name="IDS_IOS_COMPOSE_EMAIL_SETTING" desc="Title for the view and option to select a handler for mailto: URLs. [Length: 20em]">
+        Compose Email
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 042185d1..e250794 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -49,6 +49,8 @@
     "block_popups_collection_view_controller.mm",
     "clear_browsing_data_collection_view_controller.h",
     "clear_browsing_data_collection_view_controller.mm",
+    "compose_email_handler_collection_view_controller.h",
+    "compose_email_handler_collection_view_controller.mm",
     "content_settings_collection_view_controller.h",
     "content_settings_collection_view_controller.mm",
     "contextual_search_collection_view_controller.h",
@@ -142,6 +144,7 @@
     "//ios/chrome/browser/ui/settings/utils",
     "//ios/chrome/browser/ui/sync",
     "//ios/chrome/browser/voice",
+    "//ios/chrome/browser/web",
     "//ios/chrome/common",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/images",
@@ -350,6 +353,7 @@
     "bandwidth_management_collection_view_controller_unittest.mm",
     "block_popups_collection_view_controller_unittest.mm",
     "clear_browsing_data_collection_view_controller_unittest.mm",
+    "compose_email_handler_collection_view_controller_unittest.mm",
     "content_settings_collection_view_controller_unittest.mm",
     "contextual_search_collection_view_controller_unittest.mm",
     "dataplan_usage_collection_view_controller_unittest.mm",
@@ -419,6 +423,7 @@
     "//ios/chrome/browser/ui/settings/cells",
     "//ios/chrome/browser/ui/sync",
     "//ios/chrome/browser/voice",
+    "//ios/chrome/browser/web",
     "//ios/chrome/browser/web:test_support",
     "//ios/chrome/common",
     "//ios/chrome/test:test_support",
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
index b256e0e..4442aacf 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
+++ b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
@@ -10,7 +10,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/signin/signin_manager_factory.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.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"
 #include "ios/chrome/grit/ios_strings.h"
@@ -25,7 +24,14 @@
 #error "This file requires ARC support."
 #endif
 
+using chrome_test_util::AccountConsistencyConfirmationOkButton;
+using chrome_test_util::AccountConsistencySetupSigninButton;
+using chrome_test_util::AccountsSyncButton;
+using chrome_test_util::ButtonWithAccessibilityLabel;
 using chrome_test_util::NavigationBarDoneButton;
+using chrome_test_util::SettingsAccountButton;
+using chrome_test_util::SignOutAccountsButton;
+using chrome_test_util::SignInMenuButton;
 
 namespace {
 
@@ -43,37 +49,6 @@
                                           name:@"Fake Bar"];
 }
 
-// Taps the view with acessibility identifier |accessibility_id|.
-void TapViewWithAccessibilityId(NSString* accessiblity_id) {
-  // 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);
-  [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
-}
-
-// Taps the button with accessibility label |label|.
-void TapButtonWithAccessibilityLabel(NSString* label) {
-  id<GREYMatcher> matcher =
-      chrome_test_util::ButtonWithAccessibilityLabel(label);
-  [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
-}
-
-// Taps the button with accessibility labelId |message_id|.
-void TapButtonWithLabelId(int message_id) {
-  id<GREYMatcher> matcher =
-      chrome_test_util::ButtonWithAccessibilityLabelId(message_id);
-  [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
-}
-
-// Opens the signin screen from the settings page. Assumes the tools menu is
-// accessible. User must not be signed in.
-void OpenSignInFromSettings() {
-  [ChromeEarlGreyUI openSettingsMenu];
-  TapViewWithAccessibilityId(kSettingsSignInCellId);
-}
-
 // Asserts that |identity| is actually signed in to the active profile.
 void AssertAuthenticatedIdentityInActiveProfile(ChromeIdentity* identity) {
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
@@ -89,6 +64,33 @@
                   @"\"%@\", actual = \"%s\"]",
                   identity.gaiaID, info.gaia.c_str());
 }
+
+// Accepts account consistency popup prompts after signing in an account via the
+// UI. Should be called right after signing in an account.
+void AcceptAccountConsistencyPopup() {
+  [[EarlGrey selectElementWithMatcher:AccountConsistencySetupSigninButton()]
+      performAction:grey_tap()];
+
+  // The "MORE" button shows up on screens where all content can't be shown, and
+  // must be tapped to bring up the confirmation button.
+  NSError* error = nil;
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"MORE")]
+      assertWithMatcher:grey_notNil()
+                  error:&error];
+  if (error == nil) {
+    [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"MORE")]
+        performAction:grey_tap()];
+  }
+
+  [[EarlGrey selectElementWithMatcher:AccountConsistencyConfirmationOkButton()]
+      performAction:grey_tap()];
+}
+
+// Returns a matcher for a button that matches the userEmail in the given
+// |identity|.
+id<GREYMatcher> ButtonWithIdentity(ChromeIdentity* identity) {
+  return ButtonWithAccessibilityLabel(identity.userEmail);
+}
 }
 
 // Integration tests using the Account Settings screen.
@@ -105,21 +107,21 @@
       identity);
 
   // Sign In |identity|, then open the Sync Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity)]
+      performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
   AssertAuthenticatedIdentityInActiveProfile(identity);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
-  TapViewWithAccessibilityId(kSettingsAccountsSyncCellId);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
+  [ChromeEarlGreyUI tapAccountsMenuButton:AccountsSyncButton()];
 
   // Forget |identity|, screens should be popped back to the Main Settings.
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()
       ->ForgetIdentity(identity, nil);
 
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(kSettingsSignInCellId)]
+  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
@@ -135,29 +137,21 @@
       identity);
 
   // Sign In |identity|, then open the Account Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
-  AssertAuthenticatedIdentityInActiveProfile(identity);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
-
-  // Open the "Disconnect Account" dialog.
-  const CGFloat scroll_displacement = 100.0;
-  [[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                           kSettingsAccountsSignoutCellId)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown,
-                                                  scroll_displacement)
-      onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)]
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity)]
       performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
+  AssertAuthenticatedIdentityInActiveProfile(identity);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
+  [ChromeEarlGreyUI tapAccountsMenuButton:SignOutAccountsButton()];
 
   // Forget |identity|, screens should be popped back to the Main Settings.
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()
       ->ForgetIdentity(identity, nil);
 
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(kSettingsSignInCellId)]
+  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
@@ -176,16 +170,20 @@
   identity_service->AddIdentity(identity2);
 
   // Sign In |identity|, then open the Account Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity1.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity1)]
+      performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
   AssertAuthenticatedIdentityInActiveProfile(identity1);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
 
   // Remove |identity2| from the device.
-  TapButtonWithAccessibilityLabel(identity2.userEmail);
-  TapButtonWithAccessibilityLabel(@"Remove account");
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity2)]
+      performAction:grey_tap()];
+  [[EarlGrey
+      selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Remove account")]
+      performAction:grey_tap()];
 
   // Check that |identity2| isn't available anymore on the Account Settings.
   [[EarlGrey
@@ -210,17 +208,20 @@
   identity_service->AddIdentity(identity2);
 
   // Sign In |identity|, then open the Sync Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity1.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity1)]
+      performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
   AssertAuthenticatedIdentityInActiveProfile(identity1);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
-  TapViewWithAccessibilityId(kSettingsAccountsSyncCellId);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
+  [ChromeEarlGreyUI tapAccountsMenuButton:AccountsSyncButton()];
 
-  // Forget |identity2|.
+  // Forget |identity2|, allowing the UI to synchronize before and after
+  // forgetting the identity.
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
   identity_service->ForgetIdentity(identity2, nil);
+  [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
 
   // Check that both |identity1| and |identity2| aren't shown in the Sync
   // Settings.
@@ -248,20 +249,23 @@
       identity);
 
   // Sign In |identity|, then open the Account Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity)]
+      performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
   AssertAuthenticatedIdentityInActiveProfile(identity);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
 
   // Remove |identity| from the device.
-  TapButtonWithAccessibilityLabel(identity.userEmail);
-  TapButtonWithAccessibilityLabel(@"Remove account");
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity)]
+      performAction:grey_tap()];
+  [[EarlGrey
+      selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Remove account")]
+      performAction:grey_tap()];
 
   // Check that the user is signed out and the Main Settings screen is shown.
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(kSettingsSignInCellId)]
+  [[EarlGrey selectElementWithMatcher:SignInMenuButton()]
       assertWithMatcher:grey_sufficientlyVisible()];
   AssertAuthenticatedIdentityInActiveProfile(nil);
 
@@ -281,22 +285,18 @@
       identity);
 
   // Sign In |identity|, then open the Account Settings.
-  OpenSignInFromSettings();
-  TapButtonWithAccessibilityLabel(identity.userEmail);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
-  TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+  [ChromeEarlGreyUI openSettingsMenu];
+  [ChromeEarlGreyUI tapSettingsMenuButton:SignInMenuButton()];
+  [[EarlGrey selectElementWithMatcher:ButtonWithIdentity(identity)]
+      performAction:grey_tap()];
+  AcceptAccountConsistencyPopup();
   AssertAuthenticatedIdentityInActiveProfile(identity);
-  TapViewWithAccessibilityId(kSettingsAccountCellId);
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
 
   // Open the "Disconnect Account" dialog, then tap "Cancel".
-  const CGFloat scroll_displacement = 100.0;
-  [[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                           kSettingsAccountsSignoutCellId)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown,
-                                                  scroll_displacement)
-      onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)]
+  [ChromeEarlGreyUI tapAccountsMenuButton:SignOutAccountsButton()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::CancelButton()]
       performAction:grey_tap()];
-  TapButtonWithLabelId(IDS_CANCEL);
 
   // Check that Account Settings screen is open and |identity| is signed in.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)]
diff --git a/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller_unittest.mm
index 94586be8..5e923d2 100644
--- a/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/bandwidth_management_collection_view_controller_unittest.mm
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "components/pref_registry/pref_registry_syncable.h"
diff --git a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.h b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.h
new file mode 100644
index 0000000..2be2972
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.h
@@ -0,0 +1,26 @@
+// 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 _IOS_CHROME_BROWSER_UI_SETTINGS_COMPOSE_EMAIL_HANDLER_COLLECTION_VIEW_CONTROLLER_H_
+#define _IOS_CHROME_BROWSER_UI_SETTINGS_COMPOSE_EMAIL_HANDLER_COLLECTION_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h"
+
+@class MailtoURLRewriter;
+
+// UI for Compose Email settings to specify which installed Mail client app to
+// use for handling mailto: URLs. There must be at least 2 Mail client apps
+// installed before this UI should be shown because there is no need to make
+// a choice when there is only 1 Mail client app.
+@interface ComposeEmailHandlerCollectionViewController
+    : SettingsRootCollectionViewController
+
+- (instancetype)initWithRewriter:(MailtoURLRewriter*)rewriter;
+
+- (instancetype)initWithStyle:(CollectionViewControllerStyle)style
+    NS_UNAVAILABLE;
+
+@end
+
+#endif  // _IOS_CHROME_BROWSER_UI_SETTINGS_COMPOSE_EMAIL_HANDLER_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm
new file mode 100644
index 0000000..71010f3
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.mm
@@ -0,0 +1,117 @@
+// 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/settings/compose_email_handler_collection_view_controller.h"
+
+#include "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
+#import "ios/chrome/browser/web/mailto_handler.h"
+#import "ios/chrome/browser/web/mailto_url_rewriter.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierMailtoHandlers = kSectionIdentifierEnumZero,
+};
+
+typedef NS_ENUM(NSInteger, ItemType) {
+  ItemTypeMailtoHandlers = kItemTypeEnumZero,
+};
+
+}  // namespace
+
+@interface ComposeEmailHandlerCollectionViewController () {
+  MailtoURLRewriter* _rewriter;
+}
+@end
+
+@implementation ComposeEmailHandlerCollectionViewController
+
+- (instancetype)initWithRewriter:(MailtoURLRewriter*)rewriter {
+  self = [super initWithStyle:CollectionViewControllerStyleAppBar];
+  if (self) {
+    self.title = l10n_util::GetNSString(IDS_IOS_COMPOSE_EMAIL_SETTING);
+    self.collectionViewAccessibilityIdentifier =
+        @"compose_email_handler_view_controller";
+    _rewriter = rewriter;
+    [self loadModel];
+  }
+  return self;
+}
+
+- (void)loadModel {
+  [super loadModel];
+  CollectionViewModel* model = self.collectionViewModel;
+  [model addSectionWithIdentifier:SectionIdentifierMailtoHandlers];
+
+  // Since this is a one-of-several selection UI, there must be more than one
+  // choice available to the user. If this UI is being presented when there is
+  // only one choice, it is considered a software error.
+  NSArray<MailtoHandler*>* handlers = [_rewriter defaultHandlers];
+  DCHECK([handlers count] > 1);
+  NSString* currentHandlerID = [_rewriter defaultHandlerID];
+  for (MailtoHandler* handler in handlers) {
+    CollectionViewTextItem* item =
+        [[CollectionViewTextItem alloc] initWithType:ItemTypeMailtoHandlers];
+    [item setText:[handler appName]];
+    [item setAccessibilityTraits:UIAccessibilityTraitButton];
+    if ([currentHandlerID isEqualToString:[handler appStoreID]])
+      [item setAccessoryType:MDCCollectionViewCellAccessoryCheckmark];
+    [model addItem:item
+        toSectionWithIdentifier:SectionIdentifierMailtoHandlers];
+  }
+}
+
+#pragma mark UICollectionViewDelegate
+
+- (void)collectionView:(UICollectionView*)collectionView
+    didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  CollectionViewModel* model = self.collectionViewModel;
+
+  // The items created in -loadModel are all MailtoHandlers type.
+  CollectionViewTextItem* selectedItem =
+      base::mac::ObjCCastStrict<CollectionViewTextItem>(
+          [model itemAtIndexPath:indexPath]);
+  DCHECK_EQ(ItemTypeMailtoHandlers, selectedItem.type);
+
+  // Do nothing if the tapped row is already chosen as the default.
+  if (selectedItem.accessoryType == MDCCollectionViewCellAccessoryCheckmark)
+    return;
+
+  // Iterate through the rows and remove the checkmark from any that has it.
+  NSMutableArray* modifiedItems = [NSMutableArray array];
+  for (id item in
+       [model itemsInSectionWithIdentifier:SectionIdentifierMailtoHandlers]) {
+    CollectionViewTextItem* textItem =
+        base::mac::ObjCCastStrict<CollectionViewTextItem>(item);
+    DCHECK_EQ(ItemTypeMailtoHandlers, textItem.type);
+    if (textItem == selectedItem) {
+      // Shows the checkmark on the new default mailto: URL handler.
+      textItem.accessoryType = MDCCollectionViewCellAccessoryCheckmark;
+      [modifiedItems addObject:textItem];
+    } else if (textItem.accessoryType ==
+               MDCCollectionViewCellAccessoryCheckmark) {
+      // Unchecks any currently checked selection.
+      textItem.accessoryType = MDCCollectionViewCellAccessoryNone;
+      [modifiedItems addObject:textItem];
+    }
+  }
+
+  NSUInteger handlerIndex = [model indexInItemTypeForIndexPath:indexPath];
+  MailtoHandler* handler =
+      [[_rewriter defaultHandlers] objectAtIndex:handlerIndex];
+  [_rewriter setDefaultHandlerID:[handler appStoreID]];
+
+  [self reconfigureCellsForItems:modifiedItems];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm
new file mode 100644
index 0000000..0775db6
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller_unittest.mm
@@ -0,0 +1,111 @@
+// 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/settings/compose_email_handler_collection_view_controller.h"
+
+#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h"
+#import "ios/chrome/browser/web/fake_mailto_handler_helpers.h"
+#import "ios/chrome/browser/web/mailto_handler_system_mail.h"
+#import "ios/chrome/browser/web/mailto_url_rewriter.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "testing/gtest_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#pragma mark - MailtoURLRewriter private interface for testing.
+
+@interface MailtoURLRewriter ()
+- (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps;
+@end
+
+#pragma mark - ComposeEmailHandlerCollectionViewControllerTest
+
+class ComposeEmailHandlerCollectionViewControllerTest
+    : public CollectionViewControllerTest {
+ protected:
+  // Before CreateController() is called, set |handers_| and optionally
+  // |defaultHandlerID_| ivars. They will be used to seed the construction of
+  // the MailtoURLRewriter which in turn used for the construction of the
+  // CollectionViewController.
+  CollectionViewController* InstantiateController() override {
+    rewriter_ = [[MailtoURLRewriter alloc] init];
+    [rewriter_ addMailtoApps:handlers_];
+    if (defaultHandlerID_)
+      [rewriter_ setDefaultHandlerID:defaultHandlerID_];
+    return [[ComposeEmailHandlerCollectionViewController alloc]
+        initWithRewriter:rewriter_];
+  }
+
+  // |handlers_| and |defaultHandlerID_| must be set before first call to
+  // CreateController().
+  NSArray<MailtoHandler*>* handlers_;
+  NSString* defaultHandlerID_;
+  MailtoURLRewriter* rewriter_;
+};
+
+TEST_F(ComposeEmailHandlerCollectionViewControllerTest, TestConstructor) {
+  handlers_ = @[
+    [[MailtoHandlerSystemMail alloc] init],
+    [[FakeMailtoHandlerGmailInstalled alloc] init]
+  ];
+  CreateController();
+  CheckController();
+  CheckTitleWithId(IDS_IOS_COMPOSE_EMAIL_SETTING);
+
+  // Checks that there is one section with all the available MailtoHandler
+  // objects listed.
+  ASSERT_EQ(1, NumberOfSections());
+  // Array returned by -defaultHandlers is sorted by the name of the Mail app
+  // and may not be in the same order as |handlers_|.
+  NSArray<MailtoHandler*>* handlers = [rewriter_ defaultHandlers];
+  int number_of_handlers = [handlers count];
+  EXPECT_EQ(number_of_handlers, NumberOfItemsInSection(0));
+  for (int index = 0; index < number_of_handlers; ++index) {
+    MailtoHandler* handler = handlers[index];
+    CheckTextCellTitle([handler appName], 0, index);
+  }
+}
+
+TEST_F(ComposeEmailHandlerCollectionViewControllerTest, TestSelection) {
+  handlers_ = @[
+    [[MailtoHandlerSystemMail alloc] init],
+    [[FakeMailtoHandlerGmailInstalled alloc] init]
+  ];
+  // The UI will come up with the first handler listed in |handlers_|
+  // in the selected state.
+  defaultHandlerID_ = [handlers_[0] appStoreID];
+  CreateController();
+  CheckController();
+
+  // Have an observer to make sure that selecting in the UI causes the
+  // observer to be called.
+  CountingMailtoURLRewriterObserver* observer =
+      [[CountingMailtoURLRewriterObserver alloc] init];
+  [rewriter_ setObserver:observer];
+
+  // The array of |handlers| here is sorted for display and may not be in the
+  // same order as |handlers_|. Finds another entry in the |handlers| that is
+  // not currently selected and use that as the new selection. This test
+  // must set up at least two handlers in |handlers_| which guarantees that
+  // a new |selection| must be found, thus the DCHECK_GE.
+  NSArray<MailtoHandler*>* handlers = [rewriter_ defaultHandlers];
+  int selection = -1;
+  int number_of_handlers = [handlers count];
+  for (int index = 0; index < number_of_handlers; ++index) {
+    if (![defaultHandlerID_ isEqualToString:[handlers[index] appStoreID]]) {
+      selection = index;
+      break;
+    }
+  }
+  DCHECK_GE(selection, 0);
+  // Trigger a selection in the Collection View Controller.
+  [controller() collectionView:[controller() collectionView]
+      didSelectItemAtIndexPath:[NSIndexPath indexPathForRow:selection
+                                                  inSection:0]];
+  // Verify that the observer has been called and new selection has been set.
+  EXPECT_EQ(1, [observer changeCount]);
+  EXPECT_NSEQ([handlers[selection] appStoreID], [rewriter_ defaultHandlerID]);
+}
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h
index a0c6b07f..7523cf17 100644
--- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h
+++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_COLLECTION_VIEW_CONTROLLER_H_
 
 #import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h"
+#import "ios/chrome/browser/web/mailto_url_rewriter.h"
 
 namespace ios {
 class ChromeBrowserState;
@@ -14,7 +15,7 @@
 // Controller for the UI that allows the user to change content settings like
 // blocking popups.
 @interface ContentSettingsCollectionViewController
-    : SettingsRootCollectionViewController
+    : SettingsRootCollectionViewController<MailtoURLRewriterObserver>
 
 // The designated initializer. |browserState| must not be nil.
 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
index 9f6ece6..f363ad4 100644
--- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller.mm
@@ -14,10 +14,12 @@
 #include "components/translate/core/browser/translate_pref_names.h"
 #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/experimental_flags.h"
 #import "ios/chrome/browser/prefs/pref_observer_bridge.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/settings/block_popups_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/compose_email_handler_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/browser/ui/settings/translate_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h"
@@ -40,6 +42,7 @@
 typedef NS_ENUM(NSInteger, ItemType) {
   ItemTypeSettingsBlockPopups = kItemTypeEnumZero,
   ItemTypeSettingsTranslate,
+  ItemTypeSettingsComposeEmail,
 };
 
 }  // namespace
@@ -54,9 +57,15 @@
   // The observable boolean that binds to the "Disable Popups" setting state.
   ContentSettingBackedBoolean* _disablePopupsSetting;
 
+  // This object contains the list of available Mail client apps that can
+  // handle mailto: URLs. The value can be nil if mailto: URL rewriting is
+  // not available because of experimental settings.
+  MailtoURLRewriter* _mailtoURLRewriter;
+
   // Updatable Items
   CollectionViewDetailItem* _blockPopupsDetailItem;
   CollectionViewDetailItem* _translateDetailItem;
+  CollectionViewDetailItem* _composeEmailDetailItem;
 }
 
 // Returns the value for the default setting with ID |settingID|.
@@ -65,6 +74,7 @@
 // Helpers to create collection view items.
 - (id)blockPopupsItem;
 - (id)translateItem;
+- (id)composeEmailItem;
 
 @end
 
@@ -94,6 +104,11 @@
                               inverted:YES];
     [_disablePopupsSetting setObserver:self];
 
+    if (!experimental_flags::IsNativeAppLauncherEnabled()) {
+      _mailtoURLRewriter = [[MailtoURLRewriter alloc] initWithStandardHandlers];
+      [_mailtoURLRewriter setObserver:self];
+    }
+
     [self loadModel];
   }
   return self;
@@ -117,6 +132,11 @@
       toSectionWithIdentifier:SectionIdentifierSettings];
   [model addItem:[self translateItem]
       toSectionWithIdentifier:SectionIdentifierSettings];
+  if (!experimental_flags::IsNativeAppLauncherEnabled() &&
+      [[_mailtoURLRewriter defaultHandlers] count] > 1) {
+    [model addItem:[self composeEmailItem]
+        toSectionWithIdentifier:SectionIdentifierSettings];
+  }
 }
 
 - (CollectionViewItem*)blockPopupsItem {
@@ -147,6 +167,18 @@
   return _translateDetailItem;
 }
 
+- (CollectionViewItem*)composeEmailItem {
+  _composeEmailDetailItem = [[CollectionViewDetailItem alloc]
+      initWithType:ItemTypeSettingsComposeEmail];
+  _composeEmailDetailItem.text =
+      l10n_util::GetNSString(IDS_IOS_COMPOSE_EMAIL_SETTING);
+  _composeEmailDetailItem.detailText = [_mailtoURLRewriter defaultHandlerName];
+  _composeEmailDetailItem.accessoryType =
+      MDCCollectionViewCellAccessoryDisclosureIndicator;
+  _composeEmailDetailItem.accessibilityTraits |= UIAccessibilityTraitButton;
+  return _composeEmailDetailItem;
+}
+
 - (ContentSetting)getContentSetting:(ContentSettingsType)settingID {
   return ios::HostContentSettingsMapFactory::GetForBrowserState(browserState_)
       ->GetDefaultContentSetting(settingID, NULL);
@@ -174,6 +206,13 @@
       [self.navigationController pushViewController:controller animated:YES];
       break;
     }
+    case ItemTypeSettingsComposeEmail: {
+      UIViewController* controller =
+          [[ComposeEmailHandlerCollectionViewController alloc]
+              initWithRewriter:_mailtoURLRewriter];
+      [self.navigationController pushViewController:controller animated:YES];
+      break;
+    }
   }
 }
 
@@ -204,4 +243,13 @@
   [self reconfigureCellsForItems:@[ _blockPopupsDetailItem ]];
 }
 
+#pragma mark - MailtoURLRewriterObserver
+
+- (void)rewriterDidChange:(MailtoURLRewriter*)rewriter {
+  if (rewriter != _mailtoURLRewriter)
+    return;
+  _composeEmailDetailItem.detailText = [rewriter defaultHandlerName];
+  [self reconfigureCellsForItems:@[ _composeEmailDetailItem ]];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
index 1d07ba69..b665cb2 100644
--- a/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/content_settings_collection_view_controller_unittest.mm
@@ -5,9 +5,13 @@
 #import "ios/chrome/browser/ui/settings/content_settings_collection_view_controller.h"
 
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/experimental_flags.h"
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
+#include "testing/gtest_mac.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -39,12 +43,25 @@
   CheckController();
   CheckTitleWithId(IDS_IOS_CONTENT_SETTINGS_TITLE);
 
-  int expectedNumberOfItems = 2;
   ASSERT_EQ(1, NumberOfSections());
+  // Compose Email section is shown only if experiment is turned on and
+  // there are enough number of available mailto: URL handlers.
+  int number_of_handlers =
+      [[[[MailtoURLRewriter alloc] initWithStandardHandlers] defaultHandlers]
+          count];
+  bool show_compose_email_section =
+      experimental_flags::IsNativeAppLauncherEnabled() &&
+      number_of_handlers > 1;
+  int expectedNumberOfItems = show_compose_email_section ? 3 : 2;
   EXPECT_EQ(expectedNumberOfItems, NumberOfItemsInSection(0));
   CheckDetailItemTextWithIds(IDS_IOS_BLOCK_POPUPS, IDS_IOS_SETTING_ON, 0, 0);
   CheckDetailItemTextWithIds(IDS_IOS_TRANSLATE_SETTING, IDS_IOS_SETTING_ON, 0,
                              1);
+  if (show_compose_email_section) {
+    CollectionViewDetailItem* item = GetCollectionViewItem(0, 2);
+    EXPECT_NSEQ(l10n_util::GetNSString(IDS_IOS_COMPOSE_EMAIL_SETTING),
+                item.text);
+  }
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 40a1fa71..c045b75 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -65,6 +65,7 @@
   ]
   deps = [
     ":sad_tab_tab_helper_delegate",
+    ":test_support",
     ":web",
     "//base:base",
     "//base/test:test_support",
@@ -246,12 +247,15 @@
   sources = [
     "chrome_web_test.h",
     "chrome_web_test.mm",
+    "fake_mailto_handler_helpers.h",
+    "fake_mailto_handler_helpers.mm",
   ]
   deps = [
     "//components/password_manager/core/browser:test_support",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/passwords",
     "//ios/chrome/browser/ui:ui_internal",
+    "//ios/chrome/browser/web",
     "//ios/web",
     "//ios/web:test_support",
   ]
diff --git a/ios/chrome/browser/web/fake_mailto_handler_helpers.h b/ios/chrome/browser/web/fake_mailto_handler_helpers.h
new file mode 100644
index 0000000..c48d7ca
--- /dev/null
+++ b/ios/chrome/browser/web/fake_mailto_handler_helpers.h
@@ -0,0 +1,31 @@
+// 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 IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
+#define IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
+
+#import "ios/chrome/browser/web/mailto_handler.h"
+#import "ios/chrome/browser/web/mailto_handler_gmail.h"
+#import "ios/chrome/browser/web/mailto_url_rewriter.h"
+
+// Test fixtures for faking MailtoHandlerGmail objects that reports whether
+// Gmail app as installed or not.
+
+// Fakes Gmail handler where Gmail app is not installed.
+@interface FakeMailtoHandlerGmailNotInstalled : MailtoHandlerGmail
+@end
+
+// Fakes Gmail handler where Gmail app is installed.
+@interface FakeMailtoHandlerGmailInstalled : MailtoHandlerGmail
+@end
+
+// An observer object that counts and reports the number of times it has been
+// called by the MailtoURLRewriter object.
+@interface CountingMailtoURLRewriterObserver
+    : NSObject<MailtoURLRewriterObserver>
+// Returns the number of times that observer has been called.
+@property(nonatomic, readonly) int changeCount;
+@end
+
+#endif  // IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
diff --git a/ios/chrome/browser/web/fake_mailto_handler_helpers.mm b/ios/chrome/browser/web/fake_mailto_handler_helpers.mm
new file mode 100644
index 0000000..c370dfe
--- /dev/null
+++ b/ios/chrome/browser/web/fake_mailto_handler_helpers.mm
@@ -0,0 +1,24 @@
+// 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/web/fake_mailto_handler_helpers.h"
+
+@implementation FakeMailtoHandlerGmailNotInstalled
+- (BOOL)isAvailable {
+  return NO;
+}
+@end
+
+@implementation FakeMailtoHandlerGmailInstalled
+- (BOOL)isAvailable {
+  return YES;
+}
+@end
+
+@implementation CountingMailtoURLRewriterObserver
+@synthesize changeCount = _changeCount;
+- (void)rewriterDidChange:(MailtoURLRewriter*)rewriter {
+  ++_changeCount;
+}
+@end
diff --git a/ios/chrome/browser/web/mailto_url_rewriter.h b/ios/chrome/browser/web/mailto_url_rewriter.h
index 6eb0d86..1c168a09 100644
--- a/ios/chrome/browser/web/mailto_url_rewriter.h
+++ b/ios/chrome/browser/web/mailto_url_rewriter.h
@@ -37,8 +37,9 @@
 // different handlers.
 - (instancetype)initWithStandardHandlers;
 
-// Returns an array of all the currently supported Mail client apps that claims
-// to handle mailto: URL scheme through their own custom defined URL schemes.
+// Returns a sorted array of all the currently supported Mail client apps that
+// claim to handle mailto: URL scheme through their own custom defined URL
+// schemes.
 - (NSArray<MailtoHandler*>*)defaultHandlers;
 
 // Returns the name of the application that handles mailto: URLs.
diff --git a/ios/chrome/browser/web/mailto_url_rewriter.mm b/ios/chrome/browser/web/mailto_url_rewriter.mm
index 8f15372ba..5bb6b26f 100644
--- a/ios/chrome/browser/web/mailto_url_rewriter.mm
+++ b/ios/chrome/browser/web/mailto_url_rewriter.mm
@@ -80,7 +80,11 @@
 }
 
 - (NSArray<MailtoHandler*>*)defaultHandlers {
-  return [_handlers allValues];
+  return [[_handlers allValues]
+      sortedArrayUsingComparator:^NSComparisonResult(
+          MailtoHandler* _Nonnull obj1, MailtoHandler* _Nonnull obj2) {
+        return [[obj1 appName] compare:[obj2 appName]];
+      }];
 }
 
 - (NSString*)defaultHandlerID {
diff --git a/ios/chrome/browser/web/mailto_url_rewriter_unittest.mm b/ios/chrome/browser/web/mailto_url_rewriter_unittest.mm
index 796f53c4..7df96bb 100644
--- a/ios/chrome/browser/web/mailto_url_rewriter_unittest.mm
+++ b/ios/chrome/browser/web/mailto_url_rewriter_unittest.mm
@@ -4,8 +4,7 @@
 
 #import "ios/chrome/browser/web/mailto_url_rewriter.h"
 
-#import "ios/chrome/browser/web/mailto_handler.h"
-#import "ios/chrome/browser/web/mailto_handler_gmail.h"
+#import "ios/chrome/browser/web/fake_mailto_handler_helpers.h"
 #import "ios/chrome/browser/web/mailto_handler_system_mail.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
@@ -28,41 +27,6 @@
 
 }  // namespace
 
-#pragma mark - Gmail not installed
-
-@interface FakeMailtoHandlerGmailNotInstalled : MailtoHandlerGmail
-@end
-
-@implementation FakeMailtoHandlerGmailNotInstalled
-- (BOOL)isAvailable {
-  return NO;
-}
-@end
-
-#pragma mark - Gmail is installed
-
-@interface FakeMailtoHandlerGmailInstalled : MailtoHandlerGmail
-@end
-
-@implementation FakeMailtoHandlerGmailInstalled
-- (BOOL)isAvailable {
-  return YES;
-}
-@end
-
-#pragma mark - Test Observer object
-
-@interface RewriterObserver : NSObject<MailtoURLRewriterObserver>
-@property(nonatomic, readonly) int changeCount;
-@end
-
-@implementation RewriterObserver
-@synthesize changeCount = _changeCount;
-- (void)rewriterDidChange:(MailtoURLRewriter*)rewriter {
-  ++_changeCount;
-}
-@end
-
 #pragma mark - MailtoURLRewriter private interfaces for testing.
 
 @interface MailtoURLRewriter ()
@@ -130,7 +94,8 @@
 }
 
 TEST_F(MailtoURLRewriterTest, TestChangeObserver) {
-  RewriterObserver* observer = [[RewriterObserver alloc] init];
+  CountingMailtoURLRewriterObserver* observer =
+      [[CountingMailtoURLRewriterObserver alloc] init];
   ASSERT_EQ(0, [observer changeCount]);
 
   // Sets up a MailtoURLRewriter object. The default handler is Gmail app
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
index 09dabe5..3377f13 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
@@ -38,6 +38,11 @@
 // there will be a GREYAssert.
 + (void)tapClearBrowsingDataMenuButton:(id<GREYMatcher>)buttonMatcher;
 
+// Scrolls to find the button in the accounts menu with the corresponding
+// |buttonMatcher|, and then taps it. If |buttonMatcher| is not found, or the
+// accounts menu is not open when this is called there will be a GREYAssert.
++ (void)tapAccountsMenuButton:(id<GREYMatcher>)buttonMatcher;
+
 // Open a new tab via the tools menu.
 + (void)openNewTab;
 
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
index 80be4165..97639d80 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 
+#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/privacy_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
@@ -100,6 +101,13 @@
       performAction:grey_tap()];
 }
 
++ (void)tapAccountsMenuButton:(id<GREYMatcher>)buttonMatcher {
+  [[[EarlGrey selectElementWithMatcher:buttonMatcher]
+         usingSearchAction:ScrollDown()
+      onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)]
+      performAction:grey_tap()];
+}
+
 + (void)openNewTab {
   [ChromeEarlGreyUI openToolsMenu];
   id<GREYMatcher> newTabButtonMatcher =
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h
index 2670692..c2df86e 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -95,6 +95,12 @@
 // Returns matcher for the account consistency setup signin button.
 id<GREYMatcher> AccountConsistencySetupSigninButton();
 
+// Returns matcher for the account consistency confirmation button.
+id<GREYMatcher> AccountConsistencyConfirmationOkButton();
+
+// Returns matcher for the sign out accounts button.
+id<GREYMatcher> SignOutAccountsButton();
+
 // Returns matcher for the clear browsing data collection view.
 id<GREYMatcher> ClearBrowsingDataCollectionView();
 
@@ -104,6 +110,16 @@
 // Returns matcher for the OK button.
 id<GREYMatcher> OKButton();
 
+// Returns matcher for the signin button in the settings menu.
+id<GREYMatcher> SignInMenuButton();
+
+// Returns matcher for the button for the currently signed in account in the
+// settings menu.
+id<GREYMatcher> SettingsAccountButton();
+
+// Returns matcher for the menu button to sync accounts.
+id<GREYMatcher> AccountsSyncButton();
+
 }  // namespace chrome_test_util
 
 #endif  // IOS_CHROME_TEST_EARL_GREY_CHROME_MATCHERS_H_
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index a8f244ee..6fd9cef6 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -14,7 +14,9 @@
 #include "components/strings/grit/components_strings.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"
 #import "ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
 #import "ios/chrome/browser/ui/static_content/static_html_view_controller.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
@@ -178,6 +180,15 @@
       IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON);
 }
 
+id<GREYMatcher> AccountConsistencyConfirmationOkButton() {
+  return ButtonWithAccessibilityLabelId(
+      IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON);
+}
+
+id<GREYMatcher> SignOutAccountsButton() {
+  return grey_accessibilityID(kSettingsAccountsSignoutCellId);
+}
+
 id<GREYMatcher> ClearBrowsingDataCollectionView() {
   return grey_accessibilityID(kClearBrowsingDataCollectionViewId);
 }
@@ -190,4 +201,16 @@
   return ButtonWithAccessibilityLabelId(IDS_OK);
 }
 
+id<GREYMatcher> SignInMenuButton() {
+  return grey_accessibilityID(kSettingsSignInCellId);
+}
+
+id<GREYMatcher> SettingsAccountButton() {
+  return grey_accessibilityID(kSettingsAccountCellId);
+}
+
+id<GREYMatcher> AccountsSyncButton() {
+  return grey_accessibilityID(kSettingsAccountsSyncCellId);
+}
+
 }  // namespace chrome_test_util
diff --git a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm
index df2e69a..530f059 100644
--- a/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm
+++ b/ios/clean/chrome/browser/ui/tab/tab_coordinator_unittest.mm
@@ -5,6 +5,7 @@
 #import "ios/clean/chrome/browser/ui/tab/tab_coordinator.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/clean/chrome/browser/ui/tab/tab_container_view_controller.h"
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index 61ba0b8c..67f408b 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: d15c5d7a61b2aa4d0e05ef994857999bddb85452
+Revision: 2f9ba14f1e13bb077c4b01c96199ca2df7b7494d
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/web/test/test_web_thread.cc b/ios/web/test/test_web_thread.cc
index 825a34ed..33c709b 100644
--- a/ios/web/test/test_web_thread.cc
+++ b/ios/web/test/test_web_thread.cc
@@ -5,6 +5,7 @@
 #include "ios/web/public/test/test_web_thread.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "ios/web/web_thread_impl.h"
 
 namespace web {
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index 2db5b9b..ca10329 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -11,10 +11,9 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #import "ios/net/cookies/cookie_store_ios_persistent.h"
 #import "ios/web/public/web_client.h"
-#include "ios/web/public/web_thread.h"
 #include "ios/web_view/internal/web_view_network_delegate.h"
 #include "net/base/cache_type.h"
 #include "net/cert/cert_verifier.h"
@@ -79,8 +78,8 @@
     scoped_refptr<net::CookieMonster::PersistentCookieStore> persistent_store =
         new net::SQLitePersistentCookieStore(
             cookie_path, network_task_runner_,
-            web::WebThread::GetBlockingPool()->GetSequencedTaskRunner(
-                web::WebThread::GetBlockingPool()->GetSequenceToken()),
+            base::CreateSequencedTaskRunnerWithTraits(
+                {base::MayBlock(), base::TaskPriority::BACKGROUND}),
             true, nullptr);
     std::unique_ptr<net::CookieStoreIOS> cookie_store(
         new net::CookieStoreIOSPersistent(persistent_store.get()));
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index a3aaaa3..95f35f3 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -129,12 +129,13 @@
   }
 }
 
-mojom_component("mojom") {
-  output_prefix = "ipc_mojom"
-  macro_prefix = "IPC_MOJOM"
+mojom("mojom") {
   sources = [
     "ipc.mojom",
   ]
+  export_class_attribute = "IPC_EXPORT"
+  export_define = "IPC_IMPLEMENTATION"
+  export_header = "ipc/ipc_export.h"
 }
 
 mojom("test_interfaces") {
diff --git a/ipc/ipc_channel_proxy_unittest.cc b/ipc/ipc_channel_proxy_unittest.cc
index befbf524..f059099 100644
--- a/ipc/ipc_channel_proxy_unittest.cc
+++ b/ipc/ipc_channel_proxy_unittest.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <memory>
 
+#include "base/message_loop/message_loop.h"
 #include "base/pickle.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
diff --git a/ipc/ipc_mojo_perftest.cc b/ipc/ipc_mojo_perftest.cc
index ecf4099..d02acda 100644
--- a/ipc/ipc_mojo_perftest.cc
+++ b/ipc/ipc_mojo_perftest.cc
@@ -6,6 +6,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/process_metrics.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
diff --git a/ipc/ipc_send_fds_test.cc b/ipc/ipc_send_fds_test.cc
index 3c814bb..0b8a2798e 100644
--- a/ipc/ipc_send_fds_test.cc
+++ b/ipc/ipc_send_fds_test.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 
 #if defined(OS_POSIX)
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc
index 35a70dd..36effbc 100644
--- a/ipc/ipc_sync_channel.cc
+++ b/ipc/ipc_sync_channel.cc
@@ -15,6 +15,7 @@
 #include "base/logging.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/synchronization/waitable_event.h"
 #include "base/threading/thread_local.h"
diff --git a/ipc/ipc_sync_channel_unittest.cc b/ipc/ipc_sync_channel_unittest.cc
index 55c5711..63d5e46 100644
--- a/ipc/ipc_sync_channel_unittest.cc
+++ b/ipc/ipc_sync_channel_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/process_handle.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index 67253aa..e220281b 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/mash/catalog_viewer/catalog_viewer.cc b/mash/catalog_viewer/catalog_viewer.cc
index 621a541..75abf03a 100644
--- a/mash/catalog_viewer/catalog_viewer.cc
+++ b/mash/catalog_viewer/catalog_viewer.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/catalog/public/interfaces/catalog.mojom.h"
diff --git a/mash/task_viewer/task_viewer.cc b/mash/task_viewer/task_viewer.cc
index 239f5c5f..706e989 100644
--- a/mash/task_viewer/task_viewer.cc
+++ b/mash/task_viewer/task_viewer.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/process.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/media/audio/audio_input_unittest.cc b/media/audio/audio_input_unittest.cc
index 77d977d9..1571d302 100644
--- a/media/audio/audio_input_unittest.cc
+++ b/media/audio/audio_input_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/environment.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_message_loop.h"
 #include "base/threading/platform_thread.h"
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index c94c3f6..5bebbdab 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/environment.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/audio/audio_system_impl_unittest.cc b/media/audio/audio_system_impl_unittest.cc
index 618bf929..7aa5fbf 100644
--- a/media/audio/audio_system_impl_unittest.cc
+++ b/media/audio/audio_system_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "media/audio/audio_system_impl.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/task_runner_util.h"
diff --git a/media/audio/mac/audio_auhal_mac_unittest.cc b/media/audio/mac/audio_auhal_mac_unittest.cc
index 1f68f3d6..1cbba31 100644
--- a/media/audio/mac/audio_auhal_mac_unittest.cc
+++ b/media/audio/mac/audio_auhal_mac_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_message_loop.h"
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index 5d933462..307034e4 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -18,6 +18,7 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/cast/test/utility/standalone_cast_environment.cc b/media/cast/test/utility/standalone_cast_environment.cc
index 02fb810..272f04d 100644
--- a/media/cast/test/utility/standalone_cast_environment.cc
+++ b/media/cast/test/utility/standalone_cast_environment.cc
@@ -5,6 +5,7 @@
 #include "media/cast/test/utility/standalone_cast_environment.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/time/default_tick_clock.h"
 
 namespace media {
diff --git a/media/cast/test/utility/tap_proxy.cc b/media/cast/test/utility/tap_proxy.cc
index 9a4a48f7..12878a5 100644
--- a/media/cast/test/utility/tap_proxy.cc
+++ b/media/cast/test/utility/tap_proxy.cc
@@ -28,6 +28,7 @@
 #include "base/command_line.h"
 #include "base/files/file_descriptor_watcher_posix.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc
index cade4f7..2d2dda7e 100644
--- a/media/cast/test/utility/udp_proxy.cc
+++ b/media/cast/test/utility/udp_proxy.cc
@@ -11,6 +11,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 5e9bc04..7ef340b6 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/filters/vpx_video_decoder_fuzzertest.cc b/media/filters/vpx_video_decoder_fuzzertest.cc
index 15eefda..5fd22b5 100644
--- a/media/filters/vpx_video_decoder_fuzzertest.cc
+++ b/media/filters/vpx_video_decoder_fuzzertest.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/media.h"
diff --git a/media/gpu/avda_codec_allocator.h b/media/gpu/avda_codec_allocator.h
index b6d10232..7c6b05d 100644
--- a/media/gpu/avda_codec_allocator.h
+++ b/media/gpu/avda_codec_allocator.h
@@ -12,6 +12,7 @@
 #include "base/android/build_info.h"
 #include "base/bind.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/sys_info.h"
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index aaa16e1..9cd26a4 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -38,6 +38,7 @@
 #include "base/macros.h"
 #include "base/md5.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/process_handle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc b/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
index c0c7407..033c40c 100644
--- a/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
+++ b/media/mojo/common/mojo_decoder_buffer_converter_unittest.cc
@@ -10,6 +10,7 @@
 
 #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/mock_callback.h"
 #include "media/base/decoder_buffer.h"
diff --git a/media/muxers/webm_muxer_fuzzertest.cc b/media/muxers/webm_muxer_fuzzertest.cc
index dd68c69..7c29901 100644
--- a/media/muxers/webm_muxer_fuzzertest.cc
+++ b/media/muxers/webm_muxer_fuzzertest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
 #include "media/base/audio_parameters.h"
diff --git a/media/remoting/demuxer_stream_adapter_unittest.cc b/media/remoting/demuxer_stream_adapter_unittest.cc
index 38187eb..e28772dc0 100644
--- a/media/remoting/demuxer_stream_adapter_unittest.cc
+++ b/media/remoting/demuxer_stream_adapter_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/callback_helpers.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/demuxer_stream.h"
diff --git a/media/renderers/audio_renderer_impl_unittest.cc b/media/renderers/audio_renderer_impl_unittest.cc
index 7085987..123ec32 100644
--- a/media/renderers/audio_renderer_impl_unittest.cc
+++ b/media/renderers/audio_renderer_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/format_macros.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/stringprintf.h"
diff --git a/mojo/public/interfaces/bindings/BUILD.gn b/mojo/public/interfaces/bindings/BUILD.gn
index 650e8bf7e..c2cadcd7 100644
--- a/mojo/public/interfaces/bindings/BUILD.gn
+++ b/mojo/public/interfaces/bindings/BUILD.gn
@@ -11,14 +11,9 @@
     "pipe_control_messages.mojom",
   ]
 
-  component_output_prefix = "mojo_public_interfaces_bindings"
   export_class_attribute = "MOJO_CPP_BINDINGS_EXPORT"
   export_define = "MOJO_CPP_BINDINGS_IMPLEMENTATION"
   export_header = "mojo/public/cpp/bindings/bindings_export.h"
-
-  export_class_attribute_shared = "MOJO_CPP_BINDINGS_EXPORT"
-  export_define_shared = "MOJO_CPP_BINDINGS_IMPLEMENTATION"
-  export_header_shared = "mojo/public/cpp/bindings/bindings_export.h"
 }
 
 # TODO(yzshen): Remove this target and use the one above once
diff --git a/mojo/public/tools/bindings/blink_bindings_configuration.gni b/mojo/public/tools/bindings/blink_bindings_configuration.gni
index 36e9fda..bb0fc43 100644
--- a/mojo/public/tools/bindings/blink_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/blink_bindings_configuration.gni
@@ -31,4 +31,3 @@
 }
 
 blacklist = []
-component_macro_suffix = "_BLINK"
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index 6fe0750..0d020488 100644
--- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -80,5 +80,3 @@
         config = read_file(typemap, "scope")
       } ]
 }
-
-component_macro_suffix = ""
diff --git a/mojo/public/tools/bindings/generate_export_header.py b/mojo/public/tools/bindings/generate_export_header.py
deleted file mode 100755
index a1639c6..0000000
--- a/mojo/public/tools/bindings/generate_export_header.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python
-# 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.
-"""Generates a C++ header to define a component export macro."""
-
-import argparse
-import os
-import sys
-
-
-_TEMPLATE = """// 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 {{guard}}
-#define {{guard}}
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined({{impl_macro}})
-#define {{export_macro}} __declspec(dllexport)
-#else
-#define {{export_macro}} __declspec(dllimport)
-#endif  // defined({{impl_macro}})
-
-#else  // defined(WIN32)
-
-#if defined({{impl_macro}})
-#define {{export_macro}} __attribute__((visibility("default")))
-#else
-#define {{export_macro}}
-#endif
-
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define {{export_macro}}
-#endif
-
-#endif  // {{guard}}
-"""
-
-
-def WriteHeader(output_file, relative_path, impl_macro, export_macro):
-  # Allow inputs for impl_macro to be of the form FOO_IMPL=1. Drop the "=1".
-  impl_macro = impl_macro.split("=")[0]
-
-  substitutions = {
-    "guard": relative_path.replace("/", "_").replace(".", "_").upper() + "_",
-    "impl_macro": impl_macro,
-    "export_macro": export_macro,
-  }
-  contents = _TEMPLATE
-  for k, v in substitutions.iteritems():
-    contents = contents.replace("{{%s}}" % k, v)
-  with open(output_file, "w") as f:
-    f.write(contents)
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description=__doc__,
-      formatter_class=argparse.RawDescriptionHelpFormatter)
-  parser.add_argument(
-      "--impl_macro", type=str, required=True,
-      help=("The name of the macro to emit for component IMPL blocks."))
-  parser.add_argument(
-      "--export_macro", type=str, required=True,
-      help=("The name of the macro to emit for component EXPORT attributes."))
-  parser.add_argument(
-      "--output_file", type=str, required=True,
-      help=("The file path to which the generated header should be written."))
-  parser.add_argument(
-      "--relative_path", type=str, required=True,
-      help=("The generated header's path relative to the generated output"
-            " root. Used to generate header guards."))
-
-  params, _ = parser.parse_known_args()
-  WriteHeader(params.output_file, params.relative_path, params.impl_macro,
-              params.export_macro)
-
-
-if __name__ == "__main__":
-  sys.exit(main())
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl
index 3033a99..c400868 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module-shared-internal.h.tmpl
@@ -22,10 +22,6 @@
 #include "{{import.path}}-shared-internal.h"
 {%- endfor %}
 
-{%- if export_header %}
-#include "{{export_header}}"
-{%- endif %}
-
 namespace mojo {
 namespace internal {
 class ValidationContext;
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl
index 148dc7ae..b7c3070 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.h.tmpl
@@ -57,10 +57,6 @@
 #include "{{import.path}}-shared.h"
 {%- endfor %}
 
-{%- if export_header %}
-#include "{{export_header}}"
-{%- endif %}
-
 {{namespace_begin()}}
 
 {#--- Struct Forward Declarations -#}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
index cc2dcb2..156f7742 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -1,8 +1,10 @@
 {%- set class_name = struct.name ~ "_Data" -%}
 
-class {{export_attribute}} {{class_name}} {
+class {{class_name}} {
  public:
-  static {{class_name}}* New(mojo::internal::Buffer* buf);
+  static {{class_name}}* New(mojo::internal::Buffer* buf) {
+    return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
+  }
 
   static bool Validate(const void* data,
                        mojo::internal::ValidationContext* validation_context);
@@ -36,7 +38,8 @@
 {%- endif %}
 
  private:
-  {{class_name}}();
+  {{class_name}}() : header_({sizeof(*this), {{struct.versions[-1].version}}}) {
+  }
   ~{{class_name}}() = delete;
 };
 static_assert(sizeof({{class_name}}) == {{struct.versions[-1].num_bytes}},
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
index ad816ab..60dca401 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -2,11 +2,6 @@
 {%- set class_name = struct.name ~ "_Data" %}
 
 // static
-{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) {
-  return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
-}
-
-// static
 bool {{class_name}}::Validate(
     const void* data,
     mojo::internal::ValidationContext* validation_context) {
@@ -73,5 +68,3 @@
   return true;
 }
 
-{{class_name}}::{{class_name}}()
-    : header_({sizeof(*this), {{struct.versions[-1].version}}}) {}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index a249eb6..005ba76b 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -2,7 +2,7 @@
 {%- set enum_name = union.name ~ "_Tag" -%}
 {%- import "struct_macros.tmpl" as struct_macros %}
 
-class {{export_attribute}} {{class_name}} {
+class {{class_name}} {
  public:
   // Used to identify Mojom Union Data Classes.
   typedef void MojomUnionDataType;
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index 8abf2042..51497f1 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -36,9 +36,6 @@
   "$mojom_generator_script",
 ]
 
-generate_export_header_script =
-    "$mojom_generator_root/generate_export_header.py"
-
 if (enable_mojom_typemapping) {
   if (!is_ios) {
     _bindings_configuration_files = [
@@ -75,11 +72,9 @@
   _bindings_configurations = [
     {
       typemaps = []
-      component_macro_suffix = ""
     },
     {
       variant = "blink"
-      component_macro_suffix = "_BLINK"
       for_blink = true
       typemaps = []
     },
@@ -146,30 +141,10 @@
 #       TODO(yzshen): Switch all existing users to use_new_js_bindings=true and
 #       remove the old mode.
 #
-#   component_output_prefix (optional)
-#       The prefix to use for the output_name of any component library emitted
-#       for generated C++ bindings. If this is omitted, C++ bindings targets are
-#       emitted as source_sets instead. Because this controls the name of the
-#       output shared library binary in the root output directory, it must be
-#       unique across the entire build configuration.
-#
-#       This is required if |component_macro_prefix| is specified.
-#
-#   component_macro_prefix (optional)
-#       This specifies a macro prefix to use for component export macros and
-#       should therefore be globally unique in the project. For example if this
-#       is "FOO_BAR", then the generated C++ sources will be built with
-#       FOO_BAR_IMPL defined, and the generated public headers will affix
-#       FOO_BAR_EXPORT to all public symbol definitions; the meaning of the
-#       EXPORT macro depends on whether the corresponding IMPL macro is defined,
-#       per standard practice with Chromium component exports.
-#
 # The following parameters are used to support the component build. They are
 # needed so that bindings which are linked with a component can use the same
 # export settings for classes. The first three are for the chromium variant, and
-# the last three are for the blink variant. These parameters are mutually
-# exclusive to |component_macro_prefix|, but |component_output_prefix| may still
-# be used to uniqueify the generated invariant (i.e. shared) output component.
+# the last three are for the blink variant.
 #   export_class_attribute (optional)
 #       The attribute to add to the class declaration. e.g. "CONTENT_EXPORT"
 #   export_define (optional)
@@ -205,7 +180,6 @@
     assert(defined(invoker.export_class_attribute))
     assert(defined(invoker.export_define))
     assert(defined(invoker.export_header))
-    assert(!defined(invoker.component_macro_prefix))
   }
   if (defined(invoker.export_class_attribute_blink) ||
       defined(invoker.export_define_blink) ||
@@ -213,7 +187,6 @@
     assert(defined(invoker.export_class_attribute_blink))
     assert(defined(invoker.export_define_blink))
     assert(defined(invoker.export_header_blink))
-    assert(!defined(invoker.component_macro_prefix))
   }
   if (defined(invoker.overridden_deps) || defined(invoker.component_deps)) {
     assert(defined(invoker.overridden_deps))
@@ -234,10 +207,6 @@
     all_deps += invoker.public_deps
   }
 
-  if (defined(invoker.component_macro_prefix)) {
-    assert(defined(invoker.component_output_prefix))
-  }
-
   group("${target_name}__is_mojom") {
   }
 
@@ -277,47 +246,6 @@
       }
     }
 
-    if (defined(invoker.component_macro_prefix)) {
-      shared_component_export_macro =
-          "${invoker.component_macro_prefix}_SHARED_EXPORT"
-      shared_component_impl_macro =
-          "${invoker.component_macro_prefix}_SHARED_IMPL"
-      shared_component_output_name = "${invoker.component_output_prefix}_shared"
-    } else if (defined(invoker.export_class_attribute_shared) ||
-               defined(invoker.export_class_attribute)) {
-      if (defined(invoker.export_class_attribute_shared)) {
-        assert(defined(invoker.export_header_shared))
-        shared_component_export_macro = invoker.export_class_attribute_shared
-        shared_component_impl_macro = invoker.export_define_shared
-      } else {
-        assert(!defined(invoker.export_header_shared))
-
-        # If no explicit shared attribute/define was provided by the invoker,
-        # we derive some reasonable settings frorm the default variant. A new
-        # export header will be generated for these and used by shared code.
-        shared_component_export_macro =
-            "MOJOM_SHARED_" + invoker.export_class_attribute
-        shared_component_impl_macro = "MOJOM_SHARED_" + invoker.export_define
-      }
-
-      if (defined(invoker.component_output_prefix)) {
-        shared_component_output_name =
-            "${invoker.component_output_prefix}_shared"
-      } else {
-        shared_component_output_name = "${target_name}_shared"
-      }
-    }
-
-    if (defined(shared_component_export_macro) &&
-        !defined(invoker.export_header_shared)) {
-      generated_shared_export_header =
-          rebase_path("${target_name}_shared_export.h", "", target_gen_dir)
-      shared_export_header =
-          rebase_path(generated_shared_export_header, root_gen_dir)
-    } else if (defined(invoker.export_header_shared)) {
-      shared_export_header = invoker.export_header_shared
-    }
-
     generator_shared_cpp_outputs = [
       "{{source_gen_dir}}/{{source_name_part}}.mojom-shared-internal.h",
       "{{source_gen_dir}}/{{source_name_part}}.mojom-shared.cc",
@@ -345,40 +273,11 @@
         "--depfile_target",
         "{{source_gen_dir}}/{{source_name_part}}.mojom-shared-internal.h",
       ]
-
-      if (defined(shared_component_export_macro)) {
-        args += [
-          "--export_attribute",
-          shared_component_export_macro,
-          "--export_header",
-          shared_export_header,
-        ]
-      }
     }
   }
 
-  if (defined(generated_shared_export_header)) {
-    shared_export_generator_target_name =
-        "${target_name}__generate_shared_export_header"
-    action(shared_export_generator_target_name) {
-      script = generate_export_header_script
-      outputs = [
-        get_path_info(generated_shared_export_header, "abspath"),
-      ]
-      args = [
-        "--export_macro",
-        shared_component_export_macro,
-        "--impl_macro",
-        shared_component_impl_macro,
-        "--output_file",
-        generated_shared_export_header,
-        "--relative_path",
-        rebase_path(generated_shared_export_header, root_gen_dir),
-      ]
-    }
-  }
-
-  shared_cpp_sources_target_name = "${target_name}_shared_cpp_sources"
+  shared_cpp_sources_suffix = "shared_cpp_sources"
+  shared_cpp_sources_target_name = "${target_name}_${shared_cpp_sources_suffix}"
   source_set(shared_cpp_sources_target_name) {
     if (defined(invoker.testonly)) {
       testonly = invoker.testonly
@@ -389,44 +288,13 @@
           process_file_template(invoker.sources, generator_shared_cpp_outputs)
       deps += [ ":$generator_shared_target_name" ]
     }
-    public_deps = [
-      "//mojo/public/cpp/bindings",
-    ]
+    public_deps = []
     foreach(d, all_deps) {
       # Resolve the name, so that a target //mojo/something becomes
       # //mojo/something:something and we can append shared_cpp_sources_suffix
       # to get the cpp dependency name.
       full_name = get_label_info("$d", "label_no_toolchain")
-      public_deps += [ "${full_name}_shared" ]
-    }
-    if (defined(shared_component_impl_macro)) {
-      defines = [ shared_component_impl_macro ]
-    }
-    if (defined(generated_shared_export_header)) {
-      sources += [ get_path_info(generated_shared_export_header, "abspath") ]
-      public_deps += [ ":$shared_export_generator_target_name" ]
-    }
-  }
-
-  shared_cpp_library_target_name = "${target_name}_shared"
-  if (defined(shared_component_output_name)) {
-    component(shared_cpp_library_target_name) {
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-      output_name = "$shared_component_output_name"
-      public_deps = [
-        ":$shared_cpp_sources_target_name",
-      ]
-    }
-  } else {
-    group(shared_cpp_library_target_name) {
-      if (defined(invoker.testonly)) {
-        testonly = invoker.testonly
-      }
-      public_deps = [
-        ":$shared_cpp_sources_target_name",
-      ]
+      public_deps += [ "${full_name}_${shared_cpp_sources_suffix}" ]
     }
   }
 
@@ -497,31 +365,6 @@
         }
       }
 
-      if (defined(invoker.component_macro_prefix)) {
-        export_header_generator_target_name =
-            "${target_name}${variant_suffix}__generate_export_header"
-        generated_export_header =
-            rebase_path("${target_name}${variant_suffix}_export.h",
-                        "",
-                        target_gen_dir)
-        action(export_header_generator_target_name) {
-          script = generate_export_header_script
-          outputs = [
-            get_path_info(generated_export_header, "abspath"),
-          ]
-          args = [
-            "--export_macro",
-            "${invoker.component_macro_prefix}${bindings_configuration.component_macro_suffix}_EXPORT",
-            "--impl_macro",
-            "${invoker.component_macro_prefix}${bindings_configuration.component_macro_suffix}_IMPL",
-            "--output_file",
-            generated_export_header,
-            "--relative_path",
-            rebase_path(generated_export_header, root_gen_dir),
-          ]
-        }
-      }
-
       if (!cpp_only) {
         generator_js_outputs =
             [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ]
@@ -573,15 +416,6 @@
           rebase_path(type_mappings_path, root_build_dir),
         ]
 
-        if (defined(invoker.component_macro_prefix)) {
-          args += [
-            "--export_attribute",
-            "${invoker.component_macro_prefix}${bindings_configuration.component_macro_suffix}_EXPORT",
-            "--export_header",
-            rebase_path(generated_export_header, root_gen_dir),
-          ]
-        }
-
         if (defined(bindings_configuration.for_blink) &&
             bindings_configuration.for_blink) {
           args += [ "--for_blink" ]
@@ -677,13 +511,7 @@
       }
     }
 
-    if (defined(invoker.component_macro_prefix)) {
-      output_target_type = "component"
-    } else {
-      output_target_type = "source_set"
-    }
-
-    target(output_target_type, "${target_name}${variant_suffix}") {
+    source_set("${target_name}${variant_suffix}") {
       if (defined(bindings_configuration.for_blink) &&
           bindings_configuration.for_blink &&
           defined(invoker.visibility_blink)) {
@@ -716,19 +544,13 @@
         "//mojo/public/interfaces/bindings:bindings_shared__generator",
       ]
       public_deps = [
-        ":$shared_cpp_library_target_name",
+        ":$shared_cpp_sources_target_name",
         "//base",
         "//mojo/public/cpp/bindings",
       ]
       if (enabled_sources != []) {
         public_deps += [ ":$generator_target_name" ]
       }
-      if (defined(invoker.component_macro_prefix)) {
-        output_name = "${invoker.component_output_prefix}${variant_suffix}"
-        defines += [ "${invoker.component_macro_prefix}${bindings_configuration.component_macro_suffix}_IMPL" ]
-        sources += [ get_path_info(generated_export_header, "abspath") ]
-        deps += [ ":$export_header_generator_target_name" ]
-      }
       foreach(d, all_deps) {
         # Resolve the name, so that a target //mojo/something becomes
         # //mojo/something:something and we can append variant_suffix to
@@ -840,23 +662,3 @@
     }
   }
 }
-
-# A helper for the mojom() template above when component libraries are desired
-# for generated C++ bindings units. Supports all the same arguments as mojom()
-# except for the optional |component_output_prefix| and |component_macro_prefix|
-# arguments. These are instead shortened to |output_prefix| and |macro_prefix|
-# and are *required*.
-template("mojom_component") {
-  assert(defined(invoker.output_prefix) && defined(invoker.macro_prefix))
-
-  mojom(target_name) {
-    forward_variables_from(invoker,
-                           "*",
-                           [
-                             "output_prefix",
-                             "macro_prefix",
-                           ])
-    component_output_prefix = invoker.output_prefix
-    component_macro_prefix = invoker.macro_prefix
-  }
-}
diff --git a/net/OWNERS b/net/OWNERS
index 321cc06..0ad797e4 100644
--- a/net/OWNERS
+++ b/net/OWNERS
@@ -18,11 +18,8 @@
 xunjieli@chromium.org
 zhongyi@chromium.org
 
-per-file BUILD.gn=bengr@chromium.org
-per-file net.gyp*=bengr@chromium.org
-
+per-file BUILD.gn=file://net/nqe/OWNERS
 per-file BUILD.gn=file://net/websockets/OWNERS
-per-file net.gyp*=file://net/websockets/OWNERS
 
 # TEAM: net-dev@chromium.org
 # COMPONENT: Internals>Network
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index cc98d5a3..a6db1fd 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -63,6 +63,7 @@
 
 #include "base/android/build_info.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/thread.h"
 #include "net/base/address_tracker_linux.h"
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index 77cd65a..f3a77a2 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 8e55f3b..8b2bd578 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "net/base/address_tracker_linux.h"
 #include "net/dns/dns_config_service.h"
diff --git a/net/base/network_change_notifier_mac.cc b/net/base/network_change_notifier_mac.cc
index b50c785..0082153 100644
--- a/net/base/network_change_notifier_mac.cc
+++ b/net/base/network_change_notifier_mac.cc
@@ -8,6 +8,7 @@
 #include <resolv.h>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "net/dns/dns_config_service.h"
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc
index 42727f4..9b2b35e 100644
--- a/net/base/network_change_notifier_win.cc
+++ b/net/base/network_change_notifier_win.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc
index 067e6fe..6669cfd 100644
--- a/net/cert_net/cert_net_fetcher_impl_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/synchronization/lock.h"
 #include "net/cert/cert_net_fetcher.h"
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index ca0e0ee..07bd519 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/files/file.h"
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc
index d993937..0776572 100644
--- a/net/disk_cache/disk_cache_test_base.cc
+++ b/net/disk_cache/disk_cache_test_base.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/disk_cache/simple/simple_index_file_unittest.cc b/net/disk_cache/simple/simple_index_file_unittest.cc
index 54ce895..f4b574b 100644
--- a/net/disk_cache/simple/simple_index_file_unittest.cc
+++ b/net/disk_cache/simple/simple_index_file_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/hash.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pickle.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 9c356a8..c189841 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/sys_byteorder.h"
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index 3bc6c3af..f0ee33e 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -438,6 +438,7 @@
     case CONNECTION_INFO_QUIC_37:
     case CONNECTION_INFO_QUIC_38:
     case CONNECTION_INFO_QUIC_39:
+    case CONNECTION_INFO_QUIC_40:
       return true;
     case NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
@@ -486,6 +487,8 @@
       return "http/2+quic/38";
     case CONNECTION_INFO_QUIC_39:
       return "http/2+quic/39";
+    case CONNECTION_INFO_QUIC_40:
+      return "http/2+quic/40";
     case CONNECTION_INFO_HTTP0_9:
       return "http/0.9";
     case CONNECTION_INFO_HTTP1_0:
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 89366f4..9757bb47 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -51,6 +51,7 @@
     CONNECTION_INFO_QUIC_37 = 15,
     CONNECTION_INFO_QUIC_38 = 16,
     CONNECTION_INFO_QUIC_39 = 17,
+    CONNECTION_INFO_QUIC_40 = 18,
     NUM_OF_CONNECTION_INFOS,
   };
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index ef97215..21e2425 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/compiler_specific.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/histogram_tester.h"
 #include "net/base/port_util.h"
diff --git a/net/log/file_net_log_observer_unittest.cc b/net/log/file_net_log_observer_unittest.cc
index 84dcc98..7ee076f 100644
--- a/net/log/file_net_log_observer_unittest.cc
+++ b/net/log/file_net_log_observer_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
diff --git a/net/nqe/OWNERS b/net/nqe/OWNERS
index 6bb7ca3..93f44fa 100644
--- a/net/nqe/OWNERS
+++ b/net/nqe/OWNERS
@@ -1,3 +1,6 @@
 bengr@chromium.org
 tbansal@chromium.org
-ryansturm@chromium.org
\ No newline at end of file
+ryansturm@chromium.org
+
+# TEAM: nqe-dev@chromium.org
+# COMPONENT: Internals>Network>NetworkQuality
\ No newline at end of file
diff --git a/net/proxy/proxy_config_service_linux_unittest.cc b/net/proxy/proxy_config_service_linux_unittest.cc
index ae17d54..8530b42a 100644
--- a/net/proxy/proxy_config_service_linux_unittest.cc
+++ b/net/proxy/proxy_config_service_linux_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/format_macros.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
diff --git a/net/proxy/proxy_resolver_v8_tracing_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
index 3456f55..8219f64 100644
--- a/net/proxy/proxy_resolver_v8_tracing_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index 095f86b..730a8efa 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -141,6 +141,8 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_38;
     case QUIC_VERSION_39:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_39;
+    case QUIC_VERSION_40:
+      return HttpResponseInfo::CONNECTION_INFO_QUIC_40;
   }
   NOTREACHED();
   return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc
index b4663374..c36a771 100644
--- a/net/quic/core/congestion_control/bbr_sender.cc
+++ b/net/quic/core/congestion_control/bbr_sender.cc
@@ -333,10 +333,6 @@
 
 QuicByteCount BbrSender::GetTargetCongestionWindow(float gain) const {
   QuicByteCount bdp = GetMinRtt() * BandwidthEstimate();
-  if (FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt &&
-      mode_ == PROBE_BW && gain >= 1 && !rtt_stats_->smoothed_rtt().IsZero()) {
-    bdp = rtt_stats_->smoothed_rtt() * BandwidthEstimate();
-  }
   QuicByteCount congestion_window = gain * bdp;
 
   // BDP estimate will be zero if no bandwidth samples are available yet.
diff --git a/net/quic/core/congestion_control/bbr_sender_test.cc b/net/quic/core/congestion_control/bbr_sender_test.cc
index 400b3d4..bc7a0ff 100644
--- a/net/quic/core/congestion_control/bbr_sender_test.cc
+++ b/net/quic/core/congestion_control/bbr_sender_test.cc
@@ -93,10 +93,10 @@
     // These will be changed by the appropriate tests as necessary.
     FLAGS_quic_reloadable_flag_quic_bbr_slow_recent_delivery = false;
     FLAGS_quic_reloadable_flag_quic_bbr_add_tso_cwnd = false;
-    // TODO(ianswett): Determine why tests become flaky with CWND based on SRTT.
-    FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt = false;
+
     FLAGS_quic_reloadable_flag_quic_bbr_extra_conservation = true;
     FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2 = true;
+
     rtt_stats_ = bbr_sender_.connection()->sent_packet_manager().GetRttStats();
     sender_ = SetupBbrSender(&bbr_sender_);
 
diff --git a/net/quic/core/congestion_control/send_algorithm_interface.cc b/net/quic/core/congestion_control/send_algorithm_interface.cc
index b9bb452..385d46ed 100644
--- a/net/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/core/congestion_control/send_algorithm_interface.cc
@@ -9,7 +9,9 @@
 #include "net/quic/core/congestion_control/tcp_cubic_sender_packets.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
+#include "net/quic/platform/api/quic_pcc_sender.h"
 
 namespace net {
 
@@ -32,8 +34,17 @@
                              initial_congestion_window, max_congestion_window,
                              random);
       }
-
     // Fall back to CUBIC if BBR is disabled.
+    // FALLTHROUGH_INTENDED
+    case kPCC:
+      if (FLAGS_quic_reloadable_flag_quic_enable_pcc) {
+        QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_pcc);
+        return CreatePccSender(clock, rtt_stats, unacked_packets, random, stats,
+                               initial_congestion_window,
+                               max_congestion_window);
+      }
+    // Fall back to CUBIC if PCC is disabled.
+    // FALLTHROUGH_INTENDED
     case kCubic:
       return new TcpCubicSenderPackets(
           clock, rtt_stats, false /* don't use Reno */,
diff --git a/net/quic/core/congestion_control/send_algorithm_test.cc b/net/quic/core/congestion_control/send_algorithm_test.cc
index e89fb0551..134b2de 100644
--- a/net/quic/core/congestion_control/send_algorithm_test.cc
+++ b/net/quic/core/congestion_control/send_algorithm_test.cc
@@ -114,6 +114,8 @@
       return "RENO_BYTES";
     case kBBR:
       return "BBR";
+    case kPCC:
+      return "PCC";
     default:
       QUIC_DLOG(FATAL) << "Unexpected CongestionControlType";
       return nullptr;
@@ -163,7 +165,7 @@
 std::vector<TestParams> GetTestParams() {
   std::vector<TestParams> params;
   for (const CongestionControlType congestion_control_type :
-       {kBBR, kCubic, kCubicBytes, kReno, kRenoBytes}) {
+       {kBBR, kCubic, kCubicBytes, kReno, kRenoBytes, kPCC}) {
     if (congestion_control_type != kCubic &&
         congestion_control_type != kCubicBytes) {
       params.push_back(
diff --git a/net/quic/core/crypto/crypto_protocol.h b/net/quic/core/crypto/crypto_protocol.h
index 6e9a355..d073226 100644
--- a/net/quic/core/crypto/crypto_protocol.h
+++ b/net/quic/core/crypto/crypto_protocol.h
@@ -82,6 +82,8 @@
 const QuicTag k1RTT = TAG('1', 'R', 'T', 'T');   // STARTUP in BBR for 1 RTT
 const QuicTag k2RTT = TAG('2', 'R', 'T', 'T');   // STARTUP in BBR for 2 RTTs
 const QuicTag kRENO = TAG('R', 'E', 'N', 'O');   // Reno Congestion Control
+const QuicTag kTPCC = TAG('P', 'C', 'C', '\0');  // Performance-Oriented
+                                                 // Congestion Control
 const QuicTag kBYTE = TAG('B', 'Y', 'T', 'E');   // TCP cubic or reno in bytes
 const QuicTag kRATE = TAG('R', 'A', 'T', 'E');   // TCP cubic rate based sending
 const QuicTag kIW03 = TAG('I', 'W', '0', '3');   // Force ICWND to 3
@@ -111,6 +113,7 @@
 const QuicTag kSSLR = TAG('S', 'S', 'L', 'R');   // Slow Start Large Reduction.
 const QuicTag kNPRR = TAG('N', 'P', 'R', 'R');   // Pace at unity instead of PRR
 const QuicTag k5RTO = TAG('5', 'R', 'T', 'O');   // Close connection on 5 RTOs
+const QuicTag k3RTO = TAG('3', 'R', 'T', 'O');   // Close connection on 3 RTOs
 const QuicTag kCTIM = TAG('C', 'T', 'I', 'M');   // Client timestamp in seconds
                                                  // since UNIX epoch.
 const QuicTag kDHDT = TAG('D', 'H', 'D', 'T');   // Disable HPACK dynamic table.
diff --git a/net/quic/core/crypto/crypto_utils.cc b/net/quic/core/crypto/crypto_utils.cc
index b8a6120d..0e005bff2 100644
--- a/net/quic/core/crypto/crypto_utils.cc
+++ b/net/quic/core/crypto/crypto_utils.cc
@@ -137,7 +137,7 @@
   }
 
   if (subkey_secret != nullptr) {
-    hkdf.subkey_secret().CopyToString(subkey_secret);
+    *subkey_secret = string(hkdf.subkey_secret());
   }
 
   return true;
@@ -168,7 +168,7 @@
 
   crypto::HKDF hkdf(subkey_secret, QuicStringPiece() /* no salt */, info,
                     result_len, 0 /* no fixed IV */, 0 /* no subkey secret */);
-  hkdf.client_write_key().CopyToString(result);
+  *result = string(hkdf.client_write_key());
   return true;
 }
 
diff --git a/net/quic/core/crypto/quic_crypto_client_config.cc b/net/quic/core/crypto/quic_crypto_client_config.cc
index d70f79aa5..2a80d68 100644
--- a/net/quic/core/crypto/quic_crypto_client_config.cc
+++ b/net/quic/core/crypto/quic_crypto_client_config.cc
@@ -284,9 +284,10 @@
     return false;
   }
 
-  chlo_hash.CopyToString(&chlo_hash_);
-  signature.CopyToString(&server_config_sig_);
-  source_address_token.CopyToString(&source_address_token_);
+  chlo_hash_.assign(chlo_hash.data(), chlo_hash.size());
+  server_config_sig_.assign(signature.data(), signature.size());
+  source_address_token_.assign(source_address_token.data(),
+                               source_address_token.size());
   certs_ = certs;
   cert_sct_ = cert_sct;
   return true;
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 0d6e88a..f803e2f 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -207,6 +207,7 @@
       idle_timeout_connection_close_behavior_(
           ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET),
       close_connection_after_five_rtos_(false),
+      close_connection_after_three_rtos_(false),
       received_packet_manager_(&stats_),
       ack_queued_(false),
       num_retransmittable_packets_received_since_last_ack_sent_(0),
@@ -351,6 +352,11 @@
   if (config.HasClientSentConnectionOption(k5RTO, perspective_)) {
     close_connection_after_five_rtos_ = true;
   }
+  if (FLAGS_quic_reloadable_flag_quic_enable_3rtos &&
+      config.HasClientSentConnectionOption(k3RTO, perspective_)) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_3rtos);
+    close_connection_after_three_rtos_ = true;
+  }
   if (packet_generator_.latched_flag_no_stop_waiting_frames() &&
       version() > QUIC_VERSION_37 &&
       config.HasClientSentConnectionOption(kNSTP, perspective_)) {
@@ -1123,6 +1129,8 @@
     ClearSerializedPacket(&(*packet_iterator));
     packet_iterator = queued_packets_.erase(packet_iterator);
   }
+  // TODO(ianswett): Consider checking for 3 RTOs when the last stream is
+  // cancelled as well.
 }
 
 void QuicConnection::SendWindowUpdate(QuicStreamId id,
@@ -1786,6 +1794,14 @@
 void QuicConnection::OnRetransmissionTimeout() {
   DCHECK(sent_packet_manager_.HasUnackedPackets());
 
+  if (close_connection_after_three_rtos_ &&
+      sent_packet_manager_.GetConsecutiveRtoCount() >= 2 &&
+      !visitor_->HasOpenDynamicStreams()) {
+    // Close on the 3rd consecutive RTO, so after 2 previous RTOs have occurred.
+    CloseConnection(QUIC_TOO_MANY_RTOS, "3 consecutive retransmission timeouts",
+                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return;
+  }
   if (close_connection_after_five_rtos_ &&
       sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
     // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h
index ef664ab..fd78c93 100644
--- a/net/quic/core/quic_connection.h
+++ b/net/quic/core/quic_connection.h
@@ -930,6 +930,9 @@
   // When true, close the QUIC connection after 5 RTOs.  Due to the min rto of
   // 200ms, this is over 5 seconds.
   bool close_connection_after_five_rtos_;
+  // When true, close the QUIC connection when there are no open streams after
+  // 3 consecutive RTOs.
+  bool close_connection_after_three_rtos_;
 
   QuicReceivedPacketManager received_packet_manager_;
 
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index f6df716..1ac6285 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -583,6 +583,7 @@
     QuicTagVector connection_options;
     connection_options.push_back(kMTUH);
     config.SetConnectionOptionsToSend(connection_options);
+    EXPECT_CALL(*send_algorithm, GetCongestionControlType());
     EXPECT_CALL(*send_algorithm, SetFromConfig(_, _));
     SetFromConfig(config);
 
@@ -2695,6 +2696,7 @@
 
 TEST_P(QuicConnectionTest, BufferNonDecryptablePackets) {
   // SetFromConfig is always called after construction from InitializeSession.
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -2724,6 +2726,7 @@
 
 TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
   // SetFromConfig is always called after construction from InitializeSession.
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   config.set_max_undecryptable_packets(100);
@@ -2862,6 +2865,7 @@
   EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
 
   // SetFromConfig sets the initial timeouts before negotiation.
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -3298,6 +3302,7 @@
 
 TEST_P(QuicConnectionTest, TimeoutAfterSend) {
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -3344,6 +3349,7 @@
 TEST_P(QuicConnectionTest, TimeoutAfterRetransmission) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -3418,6 +3424,7 @@
   // Same test as above, but complete a handshake which enables silent close,
   // causing no connection close packet to be sent.
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
 
@@ -3480,6 +3487,7 @@
 TEST_P(QuicConnectionTest, TimeoutAfterReceive) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -3528,6 +3536,7 @@
 TEST_P(QuicConnectionTest, TimeoutAfterReceiveNotSendWhenUnacked) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   connection_.SetFromConfig(config);
@@ -3587,6 +3596,7 @@
 TEST_P(QuicConnectionTest, TimeoutAfter5ClientRTOs) {
   connection_.SetMaxTailLossProbes(2);
   EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   QuicConfig config;
   QuicTagVector connection_options;
@@ -3617,6 +3627,41 @@
   EXPECT_FALSE(connection_.connected());
 }
 
+TEST_P(QuicConnectionTest, TimeoutAfter3ClientRTOs) {
+  FLAGS_quic_reloadable_flag_quic_enable_3rtos = true;
+  connection_.SetMaxTailLossProbes(2);
+  EXPECT_TRUE(connection_.connected());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  QuicConfig config;
+  QuicTagVector connection_options;
+  connection_options.push_back(k3RTO);
+  config.SetConnectionOptionsToSend(connection_options);
+  connection_.SetFromConfig(config);
+
+  // Send stream data.
+  SendStreamDataToPeer(kClientDataStreamId1, "foo", 0, FIN, nullptr);
+
+  EXPECT_CALL(visitor_, OnPathDegrading());
+  // Fire the retransmission alarm 4 times, twice for TLP and 2 times for RTO.
+  for (int i = 0; i < 4; ++i) {
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+    connection_.GetRetransmissionAlarm()->Fire();
+    EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
+    EXPECT_TRUE(connection_.connected());
+  }
+
+  EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveTlpCount());
+  EXPECT_EQ(2u, connection_.sent_packet_manager().GetConsecutiveRtoCount());
+  // This time, we should time out.
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_TOO_MANY_RTOS, _,
+                                           ConnectionCloseSource::FROM_SELF));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  connection_.GetRetransmissionAlarm()->Fire();
+  EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
+  EXPECT_FALSE(connection_.connected());
+}
+
 TEST_P(QuicConnectionTest, SendScheduler) {
   // Test that if we send a packet without delay, it is not queued.
   QuicPacket* packet = ConstructDataPacket(1, !kHasStopWaiting);
@@ -3690,6 +3735,7 @@
 TEST_P(QuicConnectionTest, LoopThroughSendingPacketsWithTruncation) {
   // Set up a larger payload than will fit in one packet.
   const string payload(connection_.max_packet_length(), 'a');
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType()).Times(AnyNumber());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
 
   // Now send some packets with no truncation.
diff --git a/net/quic/core/quic_crypto_server_stream.cc b/net/quic/core/quic_crypto_server_stream.cc
index dfd0c4ac..6912d2f 100644
--- a/net/quic/core/quic_crypto_server_stream.cc
+++ b/net/quic/core/quic_crypto_server_stream.cc
@@ -97,6 +97,7 @@
       use_stateless_rejects_if_peer_supported_(
           use_stateless_rejects_if_peer_supported),
       peer_supports_stateless_rejects_(false),
+      zero_rtt_attempted_(false),
       chlo_packet_size_(0),
       validate_client_hello_cb_(nullptr),
       process_client_hello_cb_(nullptr) {
@@ -161,7 +162,7 @@
   DCHECK(process_client_hello_cb_ == nullptr);
   validate_client_hello_cb_ = cb.get();
   crypto_config_->ValidateClientHello(
-      message, session()->connection()->peer_address().host(),
+      message, GetClientAddress().host(),
       session()->connection()->self_address(), version(),
       session()->connection()->clock(), signed_config_, std::move(cb));
 }
@@ -300,8 +301,7 @@
   crypto_config_->BuildServerConfigUpdateMessage(
       session()->connection()->version(), chlo_hash_,
       previous_source_address_tokens_, session()->connection()->self_address(),
-      session()->connection()->peer_address().host(),
-      session()->connection()->clock(),
+      GetClientAddress().host(), session()->connection()->clock(),
       session()->connection()->random_generator(), compressed_certs_cache_,
       *crypto_negotiated_params_, cached_network_params,
       (session()->config()->HasReceivedConnectionOptions()
@@ -374,6 +374,10 @@
   return peer_supports_stateless_rejects_;
 }
 
+bool QuicCryptoServerStream::ZeroRttAttempted() const {
+  return zero_rtt_attempted_;
+}
+
 void QuicCryptoServerStream::SetPeerSupportsStatelessRejects(
     bool peer_supports_stateless_rejects) {
   peer_supports_stateless_rejects_ = peer_supports_stateless_rejects;
@@ -414,10 +418,16 @@
                  nullptr);
     return;
   }
-
   if (!result->info.server_nonce.empty()) {
     ++num_handshake_messages_with_server_nonces_;
   }
+
+  if (num_handshake_messages_ == 1) {
+    // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
+    QuicStringPiece public_value;
+    zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
+  }
+
   // Store the bandwidth estimate from the client.
   if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
     previous_cached_network_params_.reset(
@@ -433,7 +443,7 @@
       GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
   crypto_config_->ProcessClientHello(
       result, /*reject_only=*/false, connection->connection_id(),
-      connection->self_address(), connection->peer_address(), version(),
+      connection->self_address(), GetClientAddress(), version(),
       connection->supported_versions(), use_stateless_rejects_in_crypto_config,
       server_designated_connection_id, connection->clock(),
       connection->random_generator(), compressed_certs_cache_,
@@ -470,4 +480,8 @@
       session()->connection()->connection_id());
 }
 
+const QuicSocketAddress QuicCryptoServerStream::GetClientAddress() {
+  return session()->connection()->peer_address();
+}
+
 }  // namespace net
diff --git a/net/quic/core/quic_crypto_server_stream.h b/net/quic/core/quic_crypto_server_stream.h
index 4701be7..3f836753 100644
--- a/net/quic/core/quic_crypto_server_stream.h
+++ b/net/quic/core/quic_crypto_server_stream.h
@@ -57,6 +57,7 @@
   virtual uint8_t NumHandshakeMessagesWithServerNonces() const = 0;
   virtual bool UseStatelessRejectsIfPeerSupported() const = 0;
   virtual bool PeerSupportsStatelessRejects() const = 0;
+  virtual bool ZeroRttAttempted() const = 0;
   virtual void SetPeerSupportsStatelessRejects(bool set) = 0;
   virtual const CachedNetworkParameters* PreviousCachedNetworkParams()
       const = 0;
@@ -112,6 +113,7 @@
   const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
   bool UseStatelessRejectsIfPeerSupported() const override;
   bool PeerSupportsStatelessRejects() const override;
+  bool ZeroRttAttempted() const override;
   void SetPeerSupportsStatelessRejects(
       bool peer_supports_stateless_rejects) override;
   void SetPreviousCachedNetworkParams(
@@ -137,6 +139,9 @@
   // before going through the parameter negotiation step.
   virtual void OverrideQuicConfigDefaults(QuicConfig* config);
 
+  // Returns client address used to generate and validate source address token.
+  virtual const QuicSocketAddress GetClientAddress();
+
  private:
   friend class test::QuicCryptoServerStreamPeer;
 
@@ -260,6 +265,11 @@
   // becomes the default.
   bool peer_supports_stateless_rejects_;
 
+  // True if client attempts 0-rtt handshake (which can succeed or fail). If
+  // stateless rejects are used, this variable will be false for the stateless
+  // rejected connection and true for subsequent connections.
+  bool zero_rtt_attempted_;
+
   // Size of the packet containing the most recently received CHLO.
   QuicByteCount chlo_packet_size_;
 
diff --git a/net/quic/core/quic_crypto_server_stream_test.cc b/net/quic/core/quic_crypto_server_stream_test.cc
index 1cedb36..b60c22d 100644
--- a/net/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/quic/core/quic_crypto_server_stream_test.cc
@@ -333,6 +333,7 @@
   // Do a first handshake in order to prime the client config with the server's
   // information.
   AdvanceHandshakeWithFakeClient();
+  EXPECT_FALSE(server_stream()->ZeroRttAttempted());
 
   // Now do another handshake, hopefully in 0-RTT.
   QUIC_LOG(INFO) << "Resetting for 0-RTT handshake attempt";
@@ -345,6 +346,7 @@
       client_connection_, client_stream(), server_connection_, server_stream());
 
   EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
+  EXPECT_TRUE(server_stream()->ZeroRttAttempted());
 }
 
 TEST_P(QuicCryptoServerStreamTest, FailByPolicy) {
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index 199df68..3f36de6 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -120,11 +120,6 @@
 // Congestion window gain for QUIC BBR during PROBE_BW phase.
 QUIC_FLAG(double, FLAGS_quic_bbr_cwnd_gain, 2.0f)
 
-// If true, bidi streaming is always enabled in QUIC.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming,
-          true)
-
 // If true, allows the 1RTT and 2RTT connection options to reduce the time
 // in BBR STARTUP to 1 or 2 RTTs with no bandwidth increase from 3.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_allow_2_rtt_bbr_startup, true)
@@ -186,9 +181,6 @@
 // reordering window for every spurious retransmit.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_adaptive_time_loss, false)
 
-// Base CWND on SRTT instead of min_rtt for QUIC BBR.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_base_cwnd_on_srtt, false)
-
 // If true, enable random padding of size [1, 256] when response body is
 // compressed for QUIC version >= 38.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_random_padding, false)
@@ -220,3 +212,23 @@
 
 // A second take on fixing QUIC BBR packet conservation.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_fix_conservation2, false)
+
+// If true, GFEs generate and validate source address token using the actual
+// client IP for proxied session.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_use_client_address_for_stk_in_proxy,
+          false)
+
+// If true, export a varz mapping QUIC non 0-rtt handshake with corresponding
+// frontend service.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_account_handshake, false)
+
+// Allows the 3RTO QUIC connection option to close a QUIC connection after
+// 3RTOs if there are no open streams.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_3rtos, false)
+
+// If true, enable experiment for testing PCC congestion-control.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc, false)
+
+// If true, enable QUIC v40.
+QUIC_FLAG(bool, FLAGS_quic_enable_version_40, false)
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc
index afb8eff..9b3b3dc9 100644
--- a/net/quic/core/quic_sent_packet_manager.cc
+++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -117,8 +117,18 @@
     }
   } else if (config.HasClientRequestedIndependentOption(kBYTE, perspective_)) {
     SetSendAlgorithm(kCubic);
+  } else if (FLAGS_quic_reloadable_flag_quic_enable_pcc &&
+             config.HasClientRequestedIndependentOption(kTPCC, perspective_)) {
+    SetSendAlgorithm(kPCC);
   }
-  using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests;
+
+  // The PCCSender implements its own version of pacing through the
+  // SendAlgorithm::TimeUntilSend() function.  Do not wrap a
+  // PacingSender around it, since wrapping a PacingSender around an
+  // already paced SendAlgorithm produces a DCHECK.  TODO(fayang):
+  // Change this if/when the PCCSender uses the PacingSender.
+  using_pacing_ = !FLAGS_quic_disable_pacing_for_perf_tests &&
+                  send_algorithm_->GetCongestionControlType() != kPCC;
 
   if (config.HasClientSentConnectionOption(k1CON, perspective_)) {
     send_algorithm_->SetNumEmulatedConnections(1);
@@ -796,9 +806,8 @@
                  static_cast<int64_t>(0.5 * srtt.ToMilliseconds())));
   }
   if (!unacked_packets_.HasMultipleInFlightPackets()) {
-    return std::max(2 * srtt,
-                    1.5 * srtt + QuicTime::Delta::FromMilliseconds(
-                                     kMinRetransmissionTimeMs / 2));
+    return std::max(2 * srtt, 1.5 * srtt + QuicTime::Delta::FromMilliseconds(
+                                               kMinRetransmissionTimeMs / 2));
   }
   return QuicTime::Delta::FromMilliseconds(
       std::max(kMinTailLossProbeTimeoutMs,
diff --git a/net/quic/core/quic_sent_packet_manager_test.cc b/net/quic/core/quic_sent_packet_manager_test.cc
index 6aa1015e..25608411 100644
--- a/net/quic/core/quic_sent_packet_manager_test.cc
+++ b/net/quic/core/quic_sent_packet_manager_test.cc
@@ -967,6 +967,7 @@
   QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   EXPECT_CALL(*send_algorithm_, PacingRate(_))
       .WillRepeatedly(Return(QuicBandwidth::Zero()));
@@ -1117,6 +1118,7 @@
   QuicTagVector options;
   options.push_back(kCONH);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   manager_.SetFromConfig(config);
@@ -1358,6 +1360,7 @@
   QuicTagVector options;
   options.push_back(kTIME);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   manager_.SetFromConfig(config);
@@ -1377,6 +1380,7 @@
   manager_.SetFromConfig(config);
   EXPECT_EQ(kReno, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                        ->GetCongestionControlType());
+  EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
 
   options.clear();
   options.push_back(kTBBR);
@@ -1385,6 +1389,7 @@
   manager_.SetFromConfig(config);
   EXPECT_EQ(kBBR, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                       ->GetCongestionControlType());
+  EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
 
   options.clear();
   options.push_back(kBYTE);
@@ -1393,6 +1398,7 @@
   manager_.SetFromConfig(config);
   EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                         ->GetCongestionControlType());
+  EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
 
   options.clear();
   options.push_back(kRENO);
@@ -1402,10 +1408,55 @@
   manager_.SetFromConfig(config);
   EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                             ->GetCongestionControlType());
+  EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
+
+  // Test with PCC enabled and disabled.
+  FLAGS_quic_reloadable_flag_quic_enable_pcc = false;
+  const CongestionControlType prior_cc_type =
+      QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+          ->GetCongestionControlType();
+  options.clear();
+  options.push_back(kTPCC);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  // No change will be made to the congestion-control algorithm.
+  // Defaults to current type, as set in previous test.
+  EXPECT_NE(kPCC, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                      ->GetCongestionControlType());
+  EXPECT_EQ(prior_cc_type, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                               ->GetCongestionControlType());
+  EXPECT_TRUE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
+
+  FLAGS_quic_reloadable_flag_quic_enable_pcc = true;
+  options.clear();
+  options.push_back(kTPCC);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  // Don't check the tag, since the actual implementation is
+  // platform-specific (i.e. it may be stubbed out).  If the
+  // implementation does return PCC as the type, however, make sure
+  // that the packet manager does NOT wrap it with a PacingSender.
+  const bool should_pace = QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                               ->GetCongestionControlType() != kPCC;
+  EXPECT_EQ(should_pace, QuicSentPacketManagerPeer::UsingPacing(&manager_));
+
+  // Make sure that the flag for disabling pacing actually works.
+  FLAGS_quic_disable_pacing_for_perf_tests = true;
+  options.clear();
+  options.push_back(kBYTE);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                        ->GetCongestionControlType());
+  EXPECT_FALSE(QuicSentPacketManagerPeer::UsingPacing(&manager_));
 }
 
 TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
   FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true;
+  FLAGS_quic_reloadable_flag_quic_enable_pcc = true;
   QuicConfig config;
   QuicTagVector options;
 
@@ -1414,6 +1465,7 @@
       QuicSentPacketManagerPeer::GetSendAlgorithm(manager_);
   options.push_back(kRENO);
   config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   manager_.SetFromConfig(config);
@@ -1460,6 +1512,7 @@
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   EXPECT_CALL(*send_algorithm_, SetNumEmulatedConnections(1));
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
 
@@ -1468,6 +1521,7 @@
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   EXPECT_CALL(*send_algorithm_, SetNumEmulatedConnections(1));
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(client_config);
 }
@@ -1482,6 +1536,7 @@
   options.push_back(kNCON);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
 
@@ -1496,6 +1551,7 @@
   options.push_back(kNTLP);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
   EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
@@ -1509,6 +1565,7 @@
   QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(client_config);
   EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_));
@@ -1521,6 +1578,7 @@
   options.push_back(kTLPR);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
   EXPECT_TRUE(
@@ -1535,6 +1593,7 @@
   QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(client_config);
   EXPECT_TRUE(
@@ -1549,6 +1608,7 @@
   options.push_back(kNRTO);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
   EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
@@ -1563,6 +1623,7 @@
   QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(client_config);
   EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
@@ -1576,6 +1637,7 @@
   options.push_back(kUNDO);
   QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(config);
   EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_));
@@ -1628,6 +1690,7 @@
   QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
   client_config.SetConnectionOptionsToSend(options);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   manager_.SetFromConfig(client_config);
   EXPECT_TRUE(QuicSentPacketManagerPeer::GetUndoRetransmits(&manager_));
@@ -1640,6 +1703,7 @@
 
   QuicConfig config;
   config.SetInitialRoundTripTimeUsToSend(initial_rtt_us);
+  EXPECT_CALL(*send_algorithm_, GetCongestionControlType());
   EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
   manager_.SetFromConfig(config);
diff --git a/net/quic/core/quic_spdy_stream.cc b/net/quic/core/quic_spdy_stream.cc
index 76c480a..a1034f0 100644
--- a/net/quic/core/quic_spdy_stream.cc
+++ b/net/quic/core/quic_spdy_stream.cc
@@ -27,7 +27,6 @@
     : QuicStream(id, spdy_session),
       spdy_session_(spdy_session),
       visitor_(nullptr),
-      allow_bidirectional_data_(false),
       headers_decompressed_(false),
       priority_(kDefaultPriority),
       trailers_decompressed_(false),
diff --git a/net/quic/core/quic_spdy_stream.h b/net/quic/core/quic_spdy_stream.h
index 130b2e9..2e4d2fc 100644
--- a/net/quic/core/quic_spdy_stream.h
+++ b/net/quic/core/quic_spdy_stream.h
@@ -174,15 +174,6 @@
   // will be available.
   bool IsClosed() { return sequencer()->IsClosed(); }
 
-  void set_allow_bidirectional_data(bool value) {
-    allow_bidirectional_data_ = value;
-  }
-
-  bool allow_bidirectional_data() const {
-    return FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming ||
-           allow_bidirectional_data_;
-  }
-
   using QuicStream::CloseWriteSide;
 
  protected:
@@ -214,9 +205,6 @@
   QuicSpdySession* spdy_session_;
 
   Visitor* visitor_;
-  // If true, allow sending of a request to continue while the response is
-  // arriving.
-  bool allow_bidirectional_data_;
   // True if the headers have been completely decompressed.
   bool headers_decompressed_;
   // The priority of the stream, once parsed.
diff --git a/net/quic/core/quic_time.h b/net/quic/core/quic_time.h
index ee4a38c..18ef46f 100644
--- a/net/quic/core/quic_time.h
+++ b/net/quic/core/quic_time.h
@@ -24,6 +24,8 @@
 
 namespace net {
 
+class QuicClock;
+
 // A QuicTime is a purely relative time. QuicTime values from different clocks
 // cannot be compared to each other. If you need an absolute time, see
 // QuicWallTime, below.
@@ -104,8 +106,6 @@
     friend class QuicClock;
   };
 
-  explicit QuicTime(base::TimeTicks ticks) : time_(ticks.ToInternalValue()) {}
-
   // Creates a new QuicTime with an internal value of 0.  IsInitialized()
   // will return false for these times.
   static QUICTIME_CONSTEXPR QuicTime Zero() { return QuicTime(0); }
@@ -124,6 +124,8 @@
   inline bool IsInitialized() const { return 0 != time_; }
 
  private:
+  friend class QuicClock;
+
   friend inline bool operator==(QuicTime lhs, QuicTime rhs);
   friend inline bool operator<(QuicTime lhs, QuicTime rhs);
   friend inline QuicTime operator+(QuicTime lhs, QuicTime::Delta rhs);
diff --git a/net/quic/core/quic_types.h b/net/quic/core/quic_types.h
index ed978cf4..d46dbe29 100644
--- a/net/quic/core/quic_types.h
+++ b/net/quic/core/quic_types.h
@@ -223,6 +223,7 @@
   kReno,
   kRenoBytes,
   kBBR,
+  kPCC
 };
 
 enum LossDetectionType {
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc
index c67534c..198976d 100644
--- a/net/quic/core/quic_version_manager.cc
+++ b/net/quic/core/quic_version_manager.cc
@@ -10,7 +10,8 @@
 namespace net {
 
 QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
-    : enable_version_39_(FLAGS_quic_reloadable_flag_quic_enable_version_39),
+    : enable_version_40_(GetQuicFlag(FLAGS_quic_enable_version_40)),
+      enable_version_39_(FLAGS_quic_reloadable_flag_quic_enable_version_39),
       enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38),
       allowed_supported_versions_(supported_versions),
       filtered_supported_versions_(
@@ -24,8 +25,10 @@
 }
 
 void QuicVersionManager::MaybeRefilterSupportedVersions() {
-  if (enable_version_39_ != FLAGS_quic_reloadable_flag_quic_enable_version_39 ||
+  if (enable_version_40_ != GetQuicFlag(FLAGS_quic_enable_version_40) ||
+      enable_version_39_ != FLAGS_quic_reloadable_flag_quic_enable_version_39 ||
       enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38) {
+    enable_version_40_ = GetQuicFlag(FLAGS_quic_enable_version_40);
     enable_version_39_ = FLAGS_quic_reloadable_flag_quic_enable_version_39;
     enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38;
     RefilterSupportedVersions();
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h
index 481cf6c..8ef9da1 100644
--- a/net/quic/core/quic_version_manager.h
+++ b/net/quic/core/quic_version_manager.h
@@ -31,6 +31,8 @@
   }
 
  private:
+  // FLAGS_quic_enable_version_40
+  bool enable_version_40_;
   // FLAGS_quic_reloadable_flag_quic_enable_version_39
   bool enable_version_39_;
   // FLAGS_quic_reloadable_flag_quic_enable_version_38
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc
index 89f7222..6a3f9c13 100644
--- a/net/quic/core/quic_version_manager_test.cc
+++ b/net/quic/core/quic_version_manager_test.cc
@@ -16,6 +16,7 @@
 class QuicVersionManagerTest : public QuicTest {};
 
 TEST_F(QuicVersionManagerTest, QuicVersionManager) {
+  SetQuicFlag(&FLAGS_quic_enable_version_40, false);
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = false;
   QuicVersionManager manager(AllSupportedVersions());
@@ -41,14 +42,24 @@
   EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]);
   EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
 
+  SetQuicFlag(&FLAGS_quic_enable_version_40, true);
+  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
+
   EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
             manager.GetSupportedVersions());
-  ASSERT_EQ(5u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[3]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
+  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_36, manager.GetSupportedVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
 }
 
 }  // namespace
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc
index a959726..3a92624 100644
--- a/net/quic/core/quic_versions.cc
+++ b/net/quic/core/quic_versions.cc
@@ -30,7 +30,13 @@
   QuicVersionVector filtered_versions(versions.size());
   filtered_versions.clear();  // Guaranteed by spec not to change capacity.
   for (QuicVersion version : versions) {
-    if (version == QUIC_VERSION_39) {
+    if (version == QUIC_VERSION_40) {
+      if (GetQuicFlag(FLAGS_quic_enable_version_40) &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_39 &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_38) {
+        filtered_versions.push_back(version);
+      }
+    } else if (version == QUIC_VERSION_39) {
       if (FLAGS_quic_reloadable_flag_quic_enable_version_39 &&
           FLAGS_quic_reloadable_flag_quic_enable_version_38) {
         filtered_versions.push_back(version);
@@ -69,6 +75,8 @@
       return MakeQuicTag('Q', '0', '3', '8');
     case QUIC_VERSION_39:
       return MakeQuicTag('Q', '0', '3', '9');
+    case QUIC_VERSION_40:
+      return MakeQuicTag('Q', '0', '4', '0');
     default:
       // This shold be an ERROR because we should never attempt to convert an
       // invalid QuicVersion to be written to the wire.
@@ -100,6 +108,7 @@
     RETURN_STRING_LITERAL(QUIC_VERSION_37);
     RETURN_STRING_LITERAL(QUIC_VERSION_38);
     RETURN_STRING_LITERAL(QUIC_VERSION_39);
+    RETURN_STRING_LITERAL(QUIC_VERSION_40);
     default:
       return "QUIC_VERSION_UNSUPPORTED";
   }
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h
index 7bd12ec..1ddffe1 100644
--- a/net/quic/core/quic_versions.h
+++ b/net/quic/core/quic_versions.h
@@ -33,6 +33,11 @@
                          // endian. Dot not ack acks. Send a connection level
                          // WINDOW_UPDATE every 20 sent packets which do not
                          // contain retransmittable frames.
+  QUIC_VERSION_40 = 40,  // Initial packet number is randomly chosen from
+                         // [0:2^31], WINDOW_UPDATE for connection flow control
+                         // advertises value in 1024-byte units, WINDOW_UPDATE
+                         // splits into MAX_DATA and MAX_STREAM_DATA, BLOCKED
+                         // frame split into BLOCKED and STREAM_BLOCKED frames
 
   // IMPORTANT: if you are adding to this list, follow the instructions at
   // http://sites/quic/adding-and-removing-versions
@@ -46,8 +51,8 @@
 // IMPORTANT: if you are adding to this list, follow the instructions at
 // http://sites/quic/adding-and-removing-versions
 static const QuicVersion kSupportedQuicVersions[] = {
-    QUIC_VERSION_39, QUIC_VERSION_38, QUIC_VERSION_37, QUIC_VERSION_36,
-    QUIC_VERSION_35};
+    QUIC_VERSION_40, QUIC_VERSION_39, QUIC_VERSION_38,
+    QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35};
 
 typedef std::vector<QuicVersion> QuicVersionVector;
 
diff --git a/net/quic/platform/api/quic_clock.h b/net/quic/platform/api/quic_clock.h
index e95e0bc..554d590 100644
--- a/net/quic/platform/api/quic_clock.h
+++ b/net/quic/platform/api/quic_clock.h
@@ -33,6 +33,12 @@
   // Converts |walltime| to a QuicTime relative to this clock's epoch.
   virtual QuicTime ConvertWallTimeToQuicTime(
       const QuicWallTime& walltime) const;
+
+ protected:
+  // Creates a new QuicTime using |time_us| as the internal value.
+  QuicTime CreateTimeFromMicroseconds(uint64_t time_us) const {
+    return QuicTime(time_us);
+  }
 };
 
 }  // namespace net
diff --git a/net/quic/platform/impl/quic_chromium_clock.cc b/net/quic/platform/impl/quic_chromium_clock.cc
index cbf1ed1..fb591f84 100644
--- a/net/quic/platform/impl/quic_chromium_clock.cc
+++ b/net/quic/platform/impl/quic_chromium_clock.cc
@@ -4,6 +4,12 @@
 
 #include "net/quic/platform/impl/quic_chromium_clock.h"
 
+#if defined(OS_IOS)
+#include <time.h>
+
+#include "base/ios/ios_util.h"
+#endif
+
 #include "base/memory/singleton.h"
 #include "base/time/time.h"
 
@@ -23,7 +29,16 @@
 }
 
 QuicTime QuicChromiumClock::Now() const {
-  return QuicTime(base::TimeTicks::Now());
+#if defined(OS_IOS)
+  if (base::ios::IsRunningOnIOS10OrLater()) {
+    struct timespec tp;
+    if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
+      return CreateTimeFromMicroseconds(tp.tv_sec * 1000000 +
+                                        tp.tv_nsec / 1000);
+    }
+  }
+#endif
+  return CreateTimeFromMicroseconds(base::TimeTicks::Now().ToInternalValue());
 }
 
 QuicWallTime QuicChromiumClock::WallNow() const {
diff --git a/net/quic/platform/impl/quic_chromium_clock_test.cc b/net/quic/platform/impl/quic_chromium_clock_test.cc
index 562a1565..1d67f1da 100644
--- a/net/quic/platform/impl/quic_chromium_clock_test.cc
+++ b/net/quic/platform/impl/quic_chromium_clock_test.cc
@@ -12,9 +12,9 @@
 TEST(QuicChromiumClockTest, Now) {
   QuicChromiumClock clock;
 
-  QuicTime start(base::TimeTicks::Now());
+  QuicTime start = clock.Now();
   QuicTime now = clock.ApproximateNow();
-  QuicTime end(base::TimeTicks::Now());
+  QuicTime end = clock.Now();
 
   EXPECT_LE(start, now);
   EXPECT_LE(now, end);
diff --git a/net/quic/quartc/quartc_factory.cc b/net/quic/quartc/quartc_factory.cc
index ba21e4d..2591214 100644
--- a/net/quic/quartc/quartc_factory.cc
+++ b/net/quic/quartc/quartc_factory.cc
@@ -42,7 +42,7 @@
 
     DCHECK(task_runner_);
     DCHECK(!scheduled_task_);
-    scheduled_task_ = task_runner_->Schedule(this, delay_ms);
+    scheduled_task_.reset(task_runner_->Schedule(this, delay_ms).release());
   }
 
   void CancelImpl() override {
diff --git a/net/quic/quartc/quartc_packet_writer.cc b/net/quic/quartc/quartc_packet_writer.cc
index 295fce7..73ddbe8 100644
--- a/net/quic/quartc/quartc_packet_writer.cc
+++ b/net/quic/quartc/quartc_packet_writer.cc
@@ -4,8 +4,6 @@
 
 #include "net/quic/quartc/quartc_packet_writer.h"
 
-#include <errno.h>
-
 namespace net {
 
 QuartcPacketWriter::QuartcPacketWriter(
diff --git a/net/spdy/chromium/bidirectional_stream_spdy_impl.h b/net/spdy/chromium/bidirectional_stream_spdy_impl.h
index 5999bec9..b40f3c0 100644
--- a/net/spdy/chromium/bidirectional_stream_spdy_impl.h
+++ b/net/spdy/chromium/bidirectional_stream_spdy_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
-#define NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
+#ifndef NET_SPDY_CHROMIUM_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
+#define NET_SPDY_CHROMIUM_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
 
 #include <stdint.h>
 
@@ -133,4 +133,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
+#endif  // NET_SPDY_CHROMIUM_BIDIRECTIONAL_STREAM_SPDY_IMPL_H_
diff --git a/net/spdy/chromium/buffered_spdy_framer.h b/net/spdy/chromium/buffered_spdy_framer.h
index eb0c1d3..c175a11 100644
--- a/net/spdy/chromium/buffered_spdy_framer.h
+++ b/net/spdy/chromium/buffered_spdy_framer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_BUFFERED_SPDY_FRAMER_H_
-#define NET_SPDY_BUFFERED_SPDY_FRAMER_H_
+#ifndef NET_SPDY_CHROMIUM_BUFFERED_SPDY_FRAMER_H_
+#define NET_SPDY_CHROMIUM_BUFFERED_SPDY_FRAMER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -279,4 +279,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_BUFFERED_SPDY_FRAMER_H_
+#endif  // NET_SPDY_CHROMIUM_BUFFERED_SPDY_FRAMER_H_
diff --git a/net/spdy/chromium/http2_priority_dependencies.h b/net/spdy/chromium/http2_priority_dependencies.h
index bc96caf..e4ae005e 100644
--- a/net/spdy/chromium/http2_priority_dependencies.h
+++ b/net/spdy/chromium/http2_priority_dependencies.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
-#define NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
+#ifndef NET_SPDY_CHROMIUM_HTTP2_PRIORITY_DEPENDENCIES_H_
+#define NET_SPDY_CHROMIUM_HTTP2_PRIORITY_DEPENDENCIES_H_
 
 #include <list>
 #include <map>
+#include <utility>
+#include <vector>
 
 #include "net/base/net_export.h"
 #include "net/spdy/core/spdy_protocol.h"
@@ -87,4 +89,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_HTTP2_PRIORITY_DEPENDENCIES_H_
+#endif  // NET_SPDY_CHROMIUM_HTTP2_PRIORITY_DEPENDENCIES_H_
diff --git a/net/spdy/chromium/multiplexed_http_stream.h b/net/spdy/chromium/multiplexed_http_stream.h
index 15bd7ff..98b256d 100644
--- a/net/spdy/chromium/multiplexed_http_stream.h
+++ b/net/spdy/chromium/multiplexed_http_stream.h
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
-#define NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
+#ifndef NET_SPDY_CHROMIUM_MULTIPLEXED_HTTP_STREAM_H_
+#define NET_SPDY_CHROMIUM_MULTIPLEXED_HTTP_STREAM_H_
+
+#include <memory>
+#include <vector>
 
 #include "net/http/http_stream.h"
 #include "net/spdy/chromium/multiplexed_session.h"
@@ -41,4 +44,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_MULTIPLEXED_HTTP_STREAM_H_
+#endif  // NET_SPDY_CHROMIUM_MULTIPLEXED_HTTP_STREAM_H_
diff --git a/net/spdy/chromium/multiplexed_session.h b/net/spdy/chromium/multiplexed_session.h
index aaeb292..374529d 100644
--- a/net/spdy/chromium/multiplexed_session.h
+++ b/net/spdy/chromium/multiplexed_session.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_MULTIPLEXED_SESSION_H_
-#define NET_SPDY_MULTIPLEXED_SESSION_H_
+#ifndef NET_SPDY_CHROMIUM_MULTIPLEXED_SESSION_H_
+#define NET_SPDY_CHROMIUM_MULTIPLEXED_SESSION_H_
 
 #include <vector>
 
@@ -73,4 +73,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_MULTIPLEXED_SESSION_H_
+#endif  // NET_SPDY_CHROMIUM_MULTIPLEXED_SESSION_H_
diff --git a/net/spdy/chromium/server_push_delegate.h b/net/spdy/chromium/server_push_delegate.h
index 719ca8e..ba76715 100644
--- a/net/spdy/chromium/server_push_delegate.h
+++ b/net/spdy/chromium/server_push_delegate.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 NET_SPDY_SERVER_PUSH_DELEGATE_H_
-#define NET_SPDY_SERVER_PUSH_DELEGATE_H_
+#ifndef NET_SPDY_CHROMIUM_SERVER_PUSH_DELEGATE_H_
+#define NET_SPDY_CHROMIUM_SERVER_PUSH_DELEGATE_H_
+
+#include <memory>
 
 #include "net/base/net_export.h"
 #include "net/log/net_log_with_source.h"
@@ -36,4 +38,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SERVER_PUSH_DELEGATE_H_
+#endif  // NET_SPDY_CHROMIUM_SERVER_PUSH_DELEGATE_H_
diff --git a/net/spdy/chromium/spdy_buffer.h b/net/spdy/chromium/spdy_buffer.h
index c2271a5..becfde3 100644
--- a/net/spdy/chromium/spdy_buffer.h
+++ b/net/spdy/chromium/spdy_buffer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_BUFFER_H_
-#define NET_SPDY_SPDY_BUFFER_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_BUFFER_H_
+#define NET_SPDY_CHROMIUM_SPDY_BUFFER_H_
 
 #include <cstddef>
 #include <memory>
@@ -105,4 +105,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_BUFFER_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_BUFFER_H_
diff --git a/net/spdy/chromium/spdy_buffer_producer.h b/net/spdy/chromium/spdy_buffer_producer.h
index 5b18c187..921c1e7 100644
--- a/net/spdy/chromium/spdy_buffer_producer.h
+++ b/net/spdy/chromium/spdy_buffer_producer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_BUFFER_PRODUCER_H_
-#define NET_SPDY_SPDY_BUFFER_PRODUCER_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_BUFFER_PRODUCER_H_
+#define NET_SPDY_CHROMIUM_SPDY_BUFFER_PRODUCER_H_
 
 #include <memory>
 
@@ -53,4 +53,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_BUFFER_PRODUCER_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_BUFFER_PRODUCER_H_
diff --git a/net/spdy/chromium/spdy_http_stream.cc b/net/spdy/chromium/spdy_http_stream.cc
index c579ffb..c0c3b2c 100644
--- a/net/spdy/chromium/spdy_http_stream.cc
+++ b/net/spdy/chromium/spdy_http_stream.cc
@@ -6,7 +6,6 @@
 
 #include <algorithm>
 #include <list>
-#include <memory>
 #include <utility>
 
 #include "base/bind.h"
diff --git a/net/spdy/chromium/spdy_http_stream.h b/net/spdy/chromium/spdy_http_stream.h
index 4b5c85e..b3fa682 100644
--- a/net/spdy/chromium/spdy_http_stream.h
+++ b/net/spdy/chromium/spdy_http_stream.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_HTTP_STREAM_H_
-#define NET_SPDY_SPDY_HTTP_STREAM_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_HTTP_STREAM_H_
+#define NET_SPDY_CHROMIUM_SPDY_HTTP_STREAM_H_
 
 #include <stdint.h>
 
 #include <list>
+#include <memory>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -205,4 +206,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_HTTP_STREAM_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_HTTP_STREAM_H_
diff --git a/net/spdy/chromium/spdy_http_stream_unittest.cc b/net/spdy/chromium/spdy_http_stream_unittest.cc
index b95d518..4b243dd 100644
--- a/net/spdy/chromium/spdy_http_stream_unittest.cc
+++ b/net/spdy/chromium/spdy_http_stream_unittest.cc
@@ -6,8 +6,6 @@
 
 #include <stdint.h>
 
-#include <memory>
-
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -26,7 +24,6 @@
 #include "net/log/test_net_log.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/chromium/spdy_http_utils.h"
-#include "net/spdy/chromium/spdy_session.h"
 #include "net/spdy/chromium/spdy_test_util_common.h"
 #include "net/spdy/platform/api/spdy_string.h"
 #include "net/ssl/default_channel_id_store.h"
diff --git a/net/spdy/chromium/spdy_http_utils.h b/net/spdy/chromium/spdy_http_utils.h
index 4786df50..c777190 100644
--- a/net/spdy/chromium/spdy_http_utils.h
+++ b/net/spdy/chromium/spdy_http_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_HTTP_UTILS_H_
-#define NET_SPDY_SPDY_HTTP_UTILS_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_HTTP_UTILS_H_
+#define NET_SPDY_CHROMIUM_SPDY_HTTP_UTILS_H_
 
 #include "net/base/net_export.h"
 #include "net/base/request_priority.h"
@@ -51,4 +51,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_HTTP_UTILS_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_HTTP_UTILS_H_
diff --git a/net/spdy/chromium/spdy_log_util.h b/net/spdy/chromium/spdy_log_util.h
index 75f222e..86635ea 100644
--- a/net/spdy/chromium/spdy_log_util.h
+++ b/net/spdy/chromium/spdy_log_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_LOG_UTIL_H_
-#define NET_SPDY_SPDY_LOG_UTIL_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_LOG_UTIL_H_
+#define NET_SPDY_CHROMIUM_SPDY_LOG_UTIL_H_
 
 #include <memory>
 
@@ -32,4 +32,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_LOG_UTIL_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_LOG_UTIL_H_
diff --git a/net/spdy/chromium/spdy_proxy_client_socket.h b/net/spdy/chromium/spdy_proxy_client_socket.h
index d4adc419..6e707d1 100644
--- a/net/spdy/chromium/spdy_proxy_client_socket.h
+++ b/net/spdy/chromium/spdy_proxy_client_socket.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_
-#define NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_PROXY_CLIENT_SOCKET_H_
+#define NET_SPDY_CHROMIUM_SPDY_PROXY_CLIENT_SOCKET_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -186,4 +186,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_PROXY_CLIENT_SOCKET_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_PROXY_CLIENT_SOCKET_H_
diff --git a/net/spdy/chromium/spdy_read_queue.h b/net/spdy/chromium/spdy_read_queue.h
index 769c2c6..3d6a731 100644
--- a/net/spdy/chromium/spdy_read_queue.h
+++ b/net/spdy/chromium/spdy_read_queue.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_READ_QUEUE_H_
-#define NET_SPDY_SPDY_READ_QUEUE_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_READ_QUEUE_H_
+#define NET_SPDY_CHROMIUM_SPDY_READ_QUEUE_H_
 
 #include <cstddef>
 #include <deque>
@@ -50,4 +50,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_READ_QUEUE_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_READ_QUEUE_H_
diff --git a/net/spdy/chromium/spdy_session.h b/net/spdy/chromium/spdy_session.h
index 31d0d5e..2048392a 100644
--- a/net/spdy/chromium/spdy_session.h
+++ b/net/spdy/chromium/spdy_session.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_SESSION_H_
-#define NET_SPDY_SPDY_SESSION_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_SESSION_H_
+#define NET_SPDY_CHROMIUM_SPDY_SESSION_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -1232,4 +1232,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_SESSION_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_SESSION_H_
diff --git a/net/spdy/chromium/spdy_session_key.h b/net/spdy/chromium/spdy_session_key.h
index f6a8238..7aa59a0c 100644
--- a/net/spdy/chromium/spdy_session_key.h
+++ b/net/spdy/chromium/spdy_session_key.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_SESSION_KEY_H_
-#define NET_SPDY_SPDY_SESSION_KEY_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_SESSION_KEY_H_
+#define NET_SPDY_CHROMIUM_SPDY_SESSION_KEY_H_
 
 #include "net/base/net_export.h"
 #include "net/base/privacy_mode.h"
@@ -60,4 +60,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_SESSION_KEY_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_SESSION_KEY_H_
diff --git a/net/spdy/chromium/spdy_session_pool.h b/net/spdy/chromium/spdy_session_pool.h
index 1063199..186cca9 100644
--- a/net/spdy/chromium/spdy_session_pool.h
+++ b/net/spdy/chromium/spdy_session_pool.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_SESSION_POOL_H_
-#define NET_SPDY_SPDY_SESSION_POOL_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_SESSION_POOL_H_
+#define NET_SPDY_CHROMIUM_SPDY_SESSION_POOL_H_
 
 #include <stddef.h>
 
@@ -258,4 +258,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_SESSION_POOL_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_SESSION_POOL_H_
diff --git a/net/spdy/chromium/spdy_session_test_util.h b/net/spdy/chromium/spdy_session_test_util.h
index ceb385d4..656b8d8 100644
--- a/net/spdy/chromium/spdy_session_test_util.h
+++ b/net/spdy/chromium/spdy_session_test_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_SESSION_TEST_UTIL_H_
-#define NET_SPDY_SPDY_SESSION_TEST_UTIL_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_SESSION_TEST_UTIL_H_
+#define NET_SPDY_CHROMIUM_SPDY_SESSION_TEST_UTIL_H_
 
 #include <stdint.h>
 
@@ -43,4 +43,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_SESSION_TEST_UTIL_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_SESSION_TEST_UTIL_H_
diff --git a/net/spdy/chromium/spdy_stream.h b/net/spdy/chromium/spdy_stream.h
index 55373e0..4dcb0247 100644
--- a/net/spdy/chromium/spdy_stream.h
+++ b/net/spdy/chromium/spdy_stream.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_STREAM_H_
-#define NET_SPDY_SPDY_STREAM_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_STREAM_H_
+#define NET_SPDY_CHROMIUM_SPDY_STREAM_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -530,4 +530,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_STREAM_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_STREAM_H_
diff --git a/net/spdy/chromium/spdy_stream_test_util.h b/net/spdy/chromium/spdy_stream_test_util.h
index fc9045b..460f1ff 100644
--- a/net/spdy/chromium/spdy_stream_test_util.h
+++ b/net/spdy/chromium/spdy_stream_test_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_STREAM_TEST_UTIL_H_
-#define NET_SPDY_SPDY_STREAM_TEST_UTIL_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_STREAM_TEST_UTIL_H_
+#define NET_SPDY_CHROMIUM_SPDY_STREAM_TEST_UTIL_H_
 
 #include <memory>
 
@@ -137,4 +137,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_STREAM_TEST_UTIL_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_STREAM_TEST_UTIL_H_
diff --git a/net/spdy/chromium/spdy_test_util_common.h b/net/spdy/chromium/spdy_test_util_common.h
index 6f3cec8..0be418e 100644
--- a/net/spdy/chromium/spdy_test_util_common.h
+++ b/net/spdy/chromium/spdy_test_util_common.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
-#define NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_TEST_UTIL_COMMON_H_
+#define NET_SPDY_CHROMIUM_SPDY_TEST_UTIL_COMMON_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -542,4 +542,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_TEST_UTIL_COMMON_H_
diff --git a/net/spdy/chromium/spdy_write_queue.h b/net/spdy/chromium/spdy_write_queue.h
index 87d7a2fd..77b77d0 100644
--- a/net/spdy/chromium/spdy_write_queue.h
+++ b/net/spdy/chromium/spdy_write_queue.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_SPDY_SPDY_WRITE_QUEUE_H_
-#define NET_SPDY_SPDY_WRITE_QUEUE_H_
+#ifndef NET_SPDY_CHROMIUM_SPDY_WRITE_QUEUE_H_
+#define NET_SPDY_CHROMIUM_SPDY_WRITE_QUEUE_H_
 
 #include <deque>
 #include <memory>
@@ -81,6 +81,7 @@
 
     size_t EstimateMemoryUsage() const;
 
+   private:
     DISALLOW_COPY_AND_ASSIGN(PendingWrite);
   };
 
@@ -94,4 +95,4 @@
 
 }  // namespace net
 
-#endif  // NET_SPDY_SPDY_WRITE_QUEUE_H_
+#endif  // NET_SPDY_CHROMIUM_SPDY_WRITE_QUEUE_H_
diff --git a/net/spdy/core/hpack/hpack_header_table.h b/net/spdy/core/hpack/hpack_header_table.h
index 23941e0c..6192305e 100644
--- a/net/spdy/core/hpack/hpack_header_table.h
+++ b/net/spdy/core/hpack/hpack_header_table.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <unordered_map>
 #include <unordered_set>
+#include <utility>
 
 #include "base/macros.h"
 #include "net/spdy/core/hpack/hpack_entry.h"
diff --git a/net/spdy/core/spdy_framer.cc b/net/spdy/core/spdy_framer.cc
index d19bc04..e996805 100644
--- a/net/spdy/core/spdy_framer.cc
+++ b/net/spdy/core/spdy_framer.cc
@@ -11,7 +11,6 @@
 #include <ios>
 #include <iterator>
 #include <list>
-#include <memory>
 #include <new>
 #include <vector>
 
@@ -1637,16 +1636,17 @@
   }
 
   framer_->SetIsLastFrame(!has_next_frame_);
+  const size_t free_bytes_before = output->BytesFree();
+  bool ok = false;
   if (is_first_frame_) {
     is_first_frame_ = false;
-    size_t free_bytes_before = output->BytesFree();
-    bool ok = SerializeGivenEncoding(*encoding, output);
-    return ok ? free_bytes_before - output->BytesFree() : 0;
+    ok = SerializeGivenEncoding(*encoding, output);
   } else {
     SpdyContinuationIR continuation_ir(frame_ir->stream_id());
     continuation_ir.take_encoding(std::move(encoding));
-    return framer_->SerializeContinuation(continuation_ir, output);
+    ok = framer_->SerializeContinuation(continuation_ir, output);
   }
+  return ok ? free_bytes_before - output->BytesFree() : 0;
 }
 
 bool SpdyFramer::SpdyFrameIterator::HasNextFrame() const {
@@ -1713,12 +1713,12 @@
 size_t SpdyFramer::SpdyControlFrameIterator::NextFrame(
     ZeroCopyOutputBuffer* output) {
   size_t size_written = framer_->SerializeFrame(*frame_ir_, output);
-  frame_ir_.reset();
+  has_next_frame_ = false;
   return size_written;
 }
 
 bool SpdyFramer::SpdyControlFrameIterator::HasNextFrame() const {
-  return frame_ir_ != nullptr;
+  return has_next_frame_;
 }
 
 const SpdyFrameIR* SpdyFramer::SpdyControlFrameIterator::GetIR() const {
@@ -1731,23 +1731,22 @@
     std::unique_ptr<const SpdyFrameIR> frame_ir) {
   std::unique_ptr<SpdyFrameSequence> result = nullptr;
   switch (frame_ir->frame_type()) {
-    case SpdyFrameType::DATA: {
-      DLOG(ERROR) << "Data should use a different path to write";
-      result = nullptr;
-      break;
-    }
     case SpdyFrameType::HEADERS: {
       result = SpdyMakeUnique<SpdyHeaderFrameIterator>(
-          framer,
-          SpdyWrapUnique(static_cast<const SpdyHeadersIR*>(frame_ir.get())));
+          framer, SpdyWrapUnique(
+                      static_cast<const SpdyHeadersIR*>(frame_ir.release())));
       break;
     }
     case SpdyFrameType::PUSH_PROMISE: {
       result = SpdyMakeUnique<SpdyPushPromiseFrameIterator>(
-          framer, SpdyWrapUnique(
-                      static_cast<const SpdyPushPromiseIR*>(frame_ir.get())));
+          framer, SpdyWrapUnique(static_cast<const SpdyPushPromiseIR*>(
+                      frame_ir.release())));
       break;
     }
+    case SpdyFrameType::DATA: {
+      DVLOG(1) << "Serialize a stream end DATA frame for VTL";
+      // FALLTHROUGH_INTENDED
+    }
     default: {
       result =
           SpdyMakeUnique<SpdyControlFrameIterator>(framer, std::move(frame_ir));
diff --git a/net/spdy/core/spdy_framer.h b/net/spdy/core/spdy_framer.h
index 1972393..599ef0e7 100644
--- a/net/spdy/core/spdy_framer.h
+++ b/net/spdy/core/spdy_framer.h
@@ -6,7 +6,6 @@
 #define NET_SPDY_CORE_SPDY_FRAMER_H_
 
 #include <stddef.h>
-#include <stdint.h>
 
 #include <cstdint>
 #include <map>
@@ -725,6 +724,7 @@
 
    private:
     SpdyFramer* const framer_;
+    bool has_next_frame_ = true;
     std::unique_ptr<const SpdyFrameIR> frame_ir_;
   };
 
diff --git a/net/spdy/core/spdy_framer_test.cc b/net/spdy/core/spdy_framer_test.cc
index 92125ec..129c4a11 100644
--- a/net/spdy/core/spdy_framer_test.cc
+++ b/net/spdy/core/spdy_framer_test.cc
@@ -8,11 +8,8 @@
 #include <string.h>
 
 #include <algorithm>
-#include <cstdint>
 #include <limits>
-#include <memory>
 #include <tuple>
-#include <utility>
 #include <vector>
 
 #include "base/compiler_specific.h"
diff --git a/net/spdy/platform/api/spdy_ptr_util.h b/net/spdy/platform/api/spdy_ptr_util.h
index 32e5cb5..c3851cc 100644
--- a/net/spdy/platform/api/spdy_ptr_util.h
+++ b/net/spdy/platform/api/spdy_ptr_util.h
@@ -5,6 +5,9 @@
 #ifndef NET_SPDY_PLATFORM_API_SPDY_PTR_UTIL_H_
 #define NET_SPDY_PLATFORM_API_SPDY_PTR_UTIL_H_
 
+#include <memory>
+#include <utility>
+
 #include "net/spdy/platform/impl/spdy_ptr_util_impl.h"
 
 namespace net {
diff --git a/net/spdy/platform/impl/spdy_ptr_util_impl.h b/net/spdy/platform/impl/spdy_ptr_util_impl.h
index d099a8c..bcccbc24 100644
--- a/net/spdy/platform/impl/spdy_ptr_util_impl.h
+++ b/net/spdy/platform/impl/spdy_ptr_util_impl.h
@@ -5,6 +5,9 @@
 #ifndef NET_SPDY_PLATFORM_IMPL_SPDY_PTR_UTIL_IMPL_H_
 #define NET_SPDY_PLATFORM_IMPL_SPDY_PTR_UTIL_IMPL_H_
 
+#include <memory>
+#include <utility>
+
 #include "base/memory/ptr_util.h"
 
 namespace net {
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index fc647723..6d94dd0a7 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/test/spawned_test_server/spawner_communicator.cc b/net/test/spawned_test_server/spawner_communicator.cc
index 4b6d58e..aac8d9d 100644
--- a/net/test/spawned_test_server/spawner_communicator.cc
+++ b/net/test/spawned_test_server/spawner_communicator.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/supports_user_data.h"
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.cc b/net/tools/cert_verify_tool/verify_using_path_builder.cc
index 53c11ad..2426f61 100644
--- a/net/tools/cert_verify_tool/verify_using_path_builder.cc
+++ b/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -7,6 +7,7 @@
 #include <iostream>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc b/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
index 176c70b..6882724 100644
--- a/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
+++ b/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
@@ -15,6 +15,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 46e1ee9..ca66c54 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -166,7 +166,8 @@
   std::vector<TestParams> params;
   for (bool server_uses_stateless_rejects_if_peer_supported : {true, false}) {
     for (bool client_supports_stateless_rejects : {true, false}) {
-      for (const QuicTag congestion_control_tag : {kRENO, kTBBR, kQBIC}) {
+      for (const QuicTag congestion_control_tag :
+           {kRENO, kTBBR, kQBIC, kTPCC}) {
         for (bool disable_hpack_dynamic_table : {false}) {
           for (bool force_hol_blocking : {true, false}) {
             for (bool use_cheap_stateless_reject : {true, false}) {
@@ -425,6 +426,10 @@
         FLAGS_quic_reloadable_flag_quic_enable_cubic_per_ack_updates) {
       copt.push_back(kCPAU);
     }
+    if (GetParam().congestion_control_tag == kTPCC &&
+        FLAGS_quic_reloadable_flag_quic_enable_pcc) {
+      copt.push_back(kTPCC);
+    }
 
     if (support_server_push_) {
       copt.push_back(kSPSH);
@@ -1348,6 +1353,13 @@
 TEST_P(EndToEndTest, NegotiateCongestionControl) {
   FLAGS_quic_reloadable_flag_quic_allow_new_bbr = true;
   ASSERT_TRUE(Initialize());
+
+  // For PCC, the underlying implementation may be a stub with a
+  // different name-tag.  Skip the rest of this test.
+  if (GetParam().congestion_control_tag == kTPCC) {
+    return;
+  }
+
   EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
 
   CongestionControlType expected_congestion_control_type = kReno;
@@ -2543,49 +2555,6 @@
   server_thread_->Resume();
 }
 
-TEST_P(EndToEndTest, LargePostEarlyResponse) {
-  const uint32_t kWindowSize = 65536;
-  set_client_initial_stream_flow_control_receive_window(kWindowSize);
-  set_client_initial_session_flow_control_receive_window(kWindowSize);
-  set_server_initial_stream_flow_control_receive_window(kWindowSize);
-  set_server_initial_session_flow_control_receive_window(kWindowSize);
-
-  ASSERT_TRUE(Initialize());
-  if (FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    // This test is testing the same behavior as
-    // EarlyResponseWithQuicStreamNoError, except for the additional final check
-    // that the stream is reset on early response. Once this flag is deprecated
-    // the tests will be the same and this one can be removed.
-    return;
-  }
-
-  EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
-
-  // POST to a URL that gets an early error response, after the headers are
-  // received and before the body is received.
-  SpdyHeaderBlock headers;
-  headers[":method"] = "POST";
-  headers[":path"] = "/foo";
-  headers[":scheme"] = "https";
-  headers[":authority"] = server_hostname_;
-  headers["content-length"] = "-1";
-
-  // Tell the client to not close the stream if it receives an early response.
-  client_->set_allow_bidirectional_data(true);
-  // Send the headers.
-  client_->SendMessage(headers, "", /*fin=*/false);
-
-  // Receive the response and let the server close writing.
-  client_->WaitForInitialResponse();
-  EXPECT_EQ("500", client_->response_headers()->find(":status")->second);
-
-  // Receive the reset stream from server on early response.
-  QuicStream* stream = client_->client()->session()->GetOrCreateStream(
-      GetNthClientInitiatedId(0));
-  // The stream is reset by server's reset stream.
-  EXPECT_EQ(stream, nullptr);
-}
-
 TEST_P(EndToEndTest, Trailers) {
   // Test sending and receiving HTTP/2 Trailers (trailing HEADERS frames).
   ASSERT_TRUE(Initialize());
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 5e325f353..fda85001 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -779,6 +779,10 @@
   }
 }
 
+const QuicSocketAddress QuicDispatcher::GetClientAddress() const {
+  return current_client_address_;
+}
+
 bool QuicDispatcher::HandlePacketForTimeWait(
     const QuicPacketPublicHeader& header) {
   if (header.reset_flag) {
@@ -857,8 +861,7 @@
   std::unique_ptr<StatelessRejector> rejector(new StatelessRejector(
       version, GetSupportedVersions(), crypto_config_, &compressed_certs_cache_,
       helper()->GetClock(), helper()->GetRandomGenerator(),
-      current_packet_->length(), current_client_address_,
-      current_server_address_));
+      current_packet_->length(), GetClientAddress(), current_server_address_));
   ChloValidator validator(session_helper_.get(), current_server_address_,
                           rejector.get());
   if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 210d4ea4..877e602f 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -206,6 +206,10 @@
   // and delivers any buffered packets for that connection id.
   void ProcessChlo();
 
+  // Returns client address used for stateless rejector to generate and validate
+  // source address token.
+  virtual const QuicSocketAddress GetClientAddress() const;
+
   QuicTimeWaitListManager* time_wait_list_manager() {
     return time_wait_list_manager_.get();
   }
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index f14425d..6e9b8ec 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -529,10 +529,11 @@
 }
 
 TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
-  static_assert(arraysize(kSupportedQuicVersions) == 5u,
+  static_assert(arraysize(kSupportedQuicVersions) == 6u,
                 "Supported versions out of sync");
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = true;
+  SetQuicFlag(&FLAGS_quic_enable_version_40, true);
   QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
   server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
   QuicConnectionId connection_id = 1;
@@ -570,6 +571,31 @@
   ProcessPacket(client_address, connection_id, true, QuicVersionMax(),
                 SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
                 PACKET_6BYTE_PACKET_NUMBER, 1);
+  // Turn off version 40.
+  SetQuicFlag(&FLAGS_quic_enable_version_40, false);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+      .Times(0);
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_40,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
+
+  // Turn on version 40.
+  SetQuicFlag(&FLAGS_quic_enable_version_40, true);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
+      .WillOnce(testing::Return(CreateSession(
+          dispatcher_.get(), config_, connection_id, client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+              ProcessUdpPacket(_, _, _))
+      .WillOnce(testing::WithArgs<2>(
+          Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+                               base::Unretained(this), connection_id))));
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_40,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
 
   // Turn off version 39.
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = false;
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc
index 6fc2524..45621a8 100644
--- a/net/tools/quic/quic_server_bin.cc
+++ b/net/tools/quic/quic_server_bin.cc
@@ -10,6 +10,7 @@
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "net/quic/chromium/crypto/proof_source_chromium.h"
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc
index a6529836..aa57912 100644
--- a/net/tools/quic/quic_simple_server_bin.cc
+++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -10,6 +10,7 @@
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "net/base/ip_address.h"
diff --git a/net/tools/quic/quic_simple_server_stream.cc b/net/tools/quic/quic_simple_server_stream.cc
index c5737b9b..d7aad712 100644
--- a/net/tools/quic/quic_simple_server_stream.cc
+++ b/net/tools/quic/quic_simple_server_stream.cc
@@ -231,10 +231,6 @@
     SpdyHeaderBlock response_headers,
     QuicStringPiece body,
     SpdyHeaderBlock response_trailers) {
-  if (!allow_bidirectional_data() && !reading_stopped()) {
-    StopReading();
-  }
-
   // Send the headers, with a FIN if there's nothing else to send.
   bool send_fin = (body.empty() && response_trailers.empty());
   QUIC_DLOG(INFO) << "Stream " << id() << " writing headers (fin = " << send_fin
diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc
index 685f175..93b06cf5 100644
--- a/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/net/tools/quic/quic_simple_server_stream_test.cc
@@ -326,9 +326,6 @@
 
   QuicSimpleServerStreamPeer::SendResponse(stream_);
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
-  if (!FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_TRUE(stream_->reading_stopped());
-  }
   EXPECT_TRUE(stream_->write_side_closed());
 }
 
@@ -359,9 +356,6 @@
 
   QuicSimpleServerStreamPeer::SendResponse(stream_);
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
-  if (!FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_TRUE(stream_->reading_stopped());
-  }
   EXPECT_TRUE(stream_->write_side_closed());
 }
 
@@ -417,9 +411,6 @@
 
   QuicSimpleServerStreamPeer::SendResponse(stream_);
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
-  if (!FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_TRUE(stream_->reading_stopped());
-  }
   EXPECT_TRUE(stream_->write_side_closed());
 }
 
@@ -524,9 +515,6 @@
 
   QuicSimpleServerStreamPeer::SendErrorResponse(stream_);
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
-  if (!FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_TRUE(stream_->reading_stopped());
-  }
   EXPECT_TRUE(stream_->write_side_closed());
 }
 
@@ -585,22 +573,6 @@
   EXPECT_FALSE(stream_->write_side_closed());
 }
 
-TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorWithEarlyResponse) {
-  if (FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    return;
-  }
-  InSequence s;
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
-  EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
-      .Times(1)
-      .WillOnce(Return(QuicConsumedData(3, true)));
-  EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1);
-  EXPECT_FALSE(stream_->fin_received());
-  QuicSimpleServerStreamPeer::SendErrorResponse(stream_);
-  EXPECT_TRUE(stream_->reading_stopped());
-  EXPECT_TRUE(stream_->write_side_closed());
-}
-
 TEST_P(QuicSimpleServerStreamTest,
        DoNotSendQuicRstStreamNoErrorWithRstReceived) {
   InSequence s;
diff --git a/net/tools/quic/quic_spdy_client_stream.cc b/net/tools/quic/quic_spdy_client_stream.cc
index 53f1818..b5b6044 100644
--- a/net/tools/quic/quic_spdy_client_stream.cc
+++ b/net/tools/quic/quic_spdy_client_stream.cc
@@ -29,15 +29,6 @@
 
 QuicSpdyClientStream::~QuicSpdyClientStream() {}
 
-void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
-  if (!allow_bidirectional_data() && !write_side_closed()) {
-    QUIC_DLOG(INFO) << "Got a response before the request was complete.  "
-                    << "Aborting request.";
-    CloseWriteSide();
-  }
-  QuicSpdyStream::OnStreamFrame(frame);
-}
-
 void QuicSpdyClientStream::OnInitialHeadersComplete(
     bool fin,
     size_t frame_len,
diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h
index 9b3c505..2bff0e4 100644
--- a/net/tools/quic/quic_spdy_client_stream.h
+++ b/net/tools/quic/quic_spdy_client_stream.h
@@ -26,10 +26,6 @@
   QuicSpdyClientStream(QuicStreamId id, QuicClientSession* session);
   ~QuicSpdyClientStream() override;
 
-  // Override the base class to close the write side as soon as we get a
-  // response (if bidirectional streaming is not enabled).
-  void OnStreamFrame(const QuicStreamFrame& frame) override;
-
   // Override the base class to parse and store headers.
   void OnInitialHeadersComplete(bool fin,
                                 size_t frame_len,
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc
index 16e4fdfc..bd78c145 100644
--- a/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -154,19 +154,6 @@
   EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error());
 }
 
-TEST_F(QuicSpdyClientStreamTest, TestNoBidirectionalStreaming) {
-  if (FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    return;
-  }
-  QuicStreamFrame frame(
-      QuicSpdySessionPeer::GetNthClientInitiatedStreamId(session_, 0), false, 3,
-      QuicStringPiece("asd"));
-
-  EXPECT_FALSE(stream_->write_side_closed());
-  stream_->OnStreamFrame(frame);
-  EXPECT_TRUE(stream_->write_side_closed());
-}
-
 TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) {
   // Test that receiving trailing headers, containing a final offset, results in
   // the stream being closed at that byte offset.
@@ -188,14 +175,9 @@
 
   // Now send the body, which should close the stream as the FIN has been
   // received, as well as all data.
-  if (!FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_CALL(session_, CloseStream(stream_->id()));
-  }
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
-  if (FLAGS_quic_reloadable_flag_quic_always_enable_bidi_streaming) {
-    EXPECT_TRUE(stream_->reading_stopped());
-  }
+  EXPECT_TRUE(stream_->reading_stopped());
 }
 
 }  // namespace
diff --git a/net/tools/quic/synchronous_host_resolver.cc b/net/tools/quic/synchronous_host_resolver.cc
index ba1e51b..165fafe 100644
--- a/net/tools/quic/synchronous_host_resolver.cc
+++ b/net/tools/quic/synchronous_host_resolver.cc
@@ -8,6 +8,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/simple_thread.h"
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 0655c80..9a2fad6f 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -215,8 +215,7 @@
                                                   PRIVACY_MODE_DISABLED),
                                      config,
                                      supported_versions,
-                                     &epoll_server_)),
-      allow_bidirectional_data_(false) {
+                                     &epoll_server_)) {
   Initialize();
 }
 
@@ -232,12 +231,11 @@
                                      config,
                                      supported_versions,
                                      &epoll_server_,
-                                     std::move(proof_verifier))),
-      allow_bidirectional_data_(false) {
+                                     std::move(proof_verifier))) {
   Initialize();
 }
 
-QuicTestClient::QuicTestClient() : allow_bidirectional_data_(false) {}
+QuicTestClient::QuicTestClient() {}
 
 QuicTestClient::~QuicTestClient() {
   for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
@@ -440,8 +438,6 @@
     SetLatestCreatedStream(client_->CreateClientStream());
     if (latest_created_stream_) {
       latest_created_stream_->SetPriority(priority_);
-      latest_created_stream_->set_allow_bidirectional_data(
-          allow_bidirectional_data_);
     }
   }
 
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 1db57a2..26fca3c 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -245,10 +245,6 @@
 
   EpollServer* epoll_server() { return &epoll_server_; }
 
-  void set_allow_bidirectional_data(bool value) {
-    allow_bidirectional_data_ = value;
-  }
-
   size_t num_requests() const { return num_requests_; }
 
   size_t num_responses() const { return num_responses_; }
@@ -373,9 +369,6 @@
   bool auto_reconnect_;
   // Should we buffer the response body? Defaults to true.
   bool buffer_body_;
-  // When true allows the sending of a request to continue while the response is
-  // arriving.
-  bool allow_bidirectional_data_;
   // For async push promise rendezvous, validation may fail in which
   // case the request should be retried.
   std::unique_ptr<TestClientDataToResend> push_promise_data_to_resend_;
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index 198da58..2cb0c5e 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 90c240bc..40e842d 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread.h"
@@ -181,15 +182,15 @@
 URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() {}
 
 URLRequestContextBuilder::HttpNetworkSessionParams::HttpNetworkSessionParams()
-    : ignore_certificate_errors(false),
-      host_mapping_rules(NULL),
+    : host_mapping_rules(nullptr),
+      ignore_certificate_errors(false),
       testing_fixed_http_port(0),
       testing_fixed_https_port(0),
       enable_http2(true),
       enable_quic(false),
       quic_max_server_configs_stored_in_properties(0),
-      quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
       quic_close_sessions_on_ip_change(false),
+      quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds),
       quic_migrate_sessions_on_network_change(false),
       quic_migrate_sessions_early(false),
       quic_disable_bidirectional_streams(false),
@@ -198,6 +199,34 @@
 URLRequestContextBuilder::HttpNetworkSessionParams::~HttpNetworkSessionParams()
 {}
 
+void URLRequestContextBuilder::HttpNetworkSessionParams::ConfigureSessionParams(
+    HttpNetworkSession::Params* network_session_params) const {
+  network_session_params->host_mapping_rules = host_mapping_rules;
+  network_session_params->ignore_certificate_errors = ignore_certificate_errors;
+  network_session_params->testing_fixed_http_port = testing_fixed_http_port;
+  network_session_params->testing_fixed_https_port = testing_fixed_https_port;
+
+  network_session_params->enable_http2 = enable_http2;
+
+  network_session_params->enable_quic = enable_quic;
+  network_session_params->quic_user_agent_id = quic_user_agent_id;
+  network_session_params->quic_max_server_configs_stored_in_properties =
+      quic_max_server_configs_stored_in_properties;
+  network_session_params->quic_connection_options = quic_connection_options;
+  network_session_params->quic_close_sessions_on_ip_change =
+      quic_close_sessions_on_ip_change;
+  network_session_params->quic_idle_connection_timeout_seconds =
+      quic_idle_connection_timeout_seconds;
+  network_session_params->quic_migrate_sessions_on_network_change =
+      quic_migrate_sessions_on_network_change;
+  network_session_params->quic_migrate_sessions_early =
+      quic_migrate_sessions_early;
+  network_session_params->quic_disable_bidirectional_streams =
+      quic_disable_bidirectional_streams;
+  network_session_params->quic_race_cert_verification =
+      quic_race_cert_verification;
+}
+
 URLRequestContextBuilder::URLRequestContextBuilder()
     : name_(nullptr),
       enable_brotli_(false),
@@ -413,36 +442,8 @@
 
   HttpNetworkSession::Params network_session_params;
   SetHttpNetworkSessionComponents(context.get(), &network_session_params);
+  http_network_session_params_.ConfigureSessionParams(&network_session_params);
 
-  network_session_params.ignore_certificate_errors =
-      http_network_session_params_.ignore_certificate_errors;
-  network_session_params.host_mapping_rules =
-      http_network_session_params_.host_mapping_rules;
-  network_session_params.testing_fixed_http_port =
-      http_network_session_params_.testing_fixed_http_port;
-  network_session_params.testing_fixed_https_port =
-      http_network_session_params_.testing_fixed_https_port;
-  network_session_params.enable_http2 =
-      http_network_session_params_.enable_http2;
-  network_session_params.enable_quic = http_network_session_params_.enable_quic;
-  network_session_params.quic_max_server_configs_stored_in_properties =
-      http_network_session_params_.quic_max_server_configs_stored_in_properties;
-  network_session_params.quic_idle_connection_timeout_seconds =
-      http_network_session_params_.quic_idle_connection_timeout_seconds;
-  network_session_params.quic_connection_options =
-      http_network_session_params_.quic_connection_options;
-  network_session_params.quic_close_sessions_on_ip_change =
-      http_network_session_params_.quic_close_sessions_on_ip_change;
-  network_session_params.quic_migrate_sessions_on_network_change =
-      http_network_session_params_.quic_migrate_sessions_on_network_change;
-  network_session_params.quic_user_agent_id =
-      http_network_session_params_.quic_user_agent_id;
-  network_session_params.quic_migrate_sessions_early =
-      http_network_session_params_.quic_migrate_sessions_early;
-  network_session_params.quic_disable_bidirectional_streams =
-      http_network_session_params_.quic_disable_bidirectional_streams;
-  network_session_params.quic_race_cert_verification =
-      http_network_session_params_.quic_race_cert_verification;
   if (proxy_delegate_) {
     network_session_params.proxy_delegate = proxy_delegate_.get();
     storage->set_proxy_delegate(std::move(proxy_delegate_));
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index cc5448d0..2c04437 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -88,18 +88,23 @@
     HttpNetworkSessionParams();
     ~HttpNetworkSessionParams();
 
+    // Configutes |params| to match the settings in |this|.
+    // TODO(mmenke):  Temporary utility function. Once everything is using a
+    // URLRequestContextBuilder, can make this no longer publicly accessible.
+    void ConfigureSessionParams(HttpNetworkSession::Params* params) const;
+
     // These fields mirror those in HttpNetworkSession::Params;
-    bool ignore_certificate_errors;
     HostMappingRules* host_mapping_rules;
+    bool ignore_certificate_errors;
     uint16_t testing_fixed_http_port;
     uint16_t testing_fixed_https_port;
     bool enable_http2;
     bool enable_quic;
     std::string quic_user_agent_id;
     int quic_max_server_configs_stored_in_properties;
-    int quic_idle_connection_timeout_seconds;
     QuicTagVector quic_connection_options;
     bool quic_close_sessions_on_ip_change;
+    int quic_idle_connection_timeout_seconds;
     bool quic_migrate_sessions_on_network_change;
     bool quic_migrate_sessions_early;
     bool quic_disable_bidirectional_streams;
diff --git a/ppapi/host/resource_message_filter_unittest.cc b/ppapi/host/resource_message_filter_unittest.cc
index 951c6bf..62c0131 100644
--- a/ppapi/host/resource_message_filter_unittest.cc
+++ b/ppapi/host/resource_message_filter_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/ppapi/nacl_irt/irt_pnacl_translator_compile.cc b/ppapi/nacl_irt/irt_pnacl_translator_compile.cc
index 74022d71b..116b3f3 100644
--- a/ppapi/nacl_irt/irt_pnacl_translator_compile.cc
+++ b/ppapi/nacl_irt/irt_pnacl_translator_compile.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "ipc/ipc_listener.h"
diff --git a/ppapi/nacl_irt/irt_pnacl_translator_link.cc b/ppapi/nacl_irt/irt_pnacl_translator_link.cc
index 5ecd980..ccd1919 100644
--- a/ppapi/nacl_irt/irt_pnacl_translator_link.cc
+++ b/ppapi/nacl_irt/irt_pnacl_translator_link.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "ipc/ipc_listener.h"
diff --git a/ppapi/nacl_irt/irt_ppapi.cc b/ppapi/nacl_irt/irt_ppapi.cc
index b32f83a..c7506eea 100644
--- a/ppapi/nacl_irt/irt_ppapi.cc
+++ b/ppapi/nacl_irt/irt_ppapi.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "ipc/ipc_logging.h"
diff --git a/ppapi/nacl_irt/plugin_startup.cc b/ppapi/nacl_irt/plugin_startup.cc
index 2e9392c7..b99a7002 100644
--- a/ppapi/nacl_irt/plugin_startup.cc
+++ b/ppapi/nacl_irt/plugin_startup.cc
@@ -8,6 +8,7 @@
 #include "base/file_descriptor_posix.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc
index 862031a..740cefe9 100644
--- a/ppapi/proxy/plugin_globals.cc
+++ b/ppapi/proxy/plugin_globals.cc
@@ -5,6 +5,7 @@
 #include "ppapi/proxy/plugin_globals.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/task_runner.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h
index 670753e..fdb373c 100644
--- a/ppapi/proxy/ppapi_proxy_test.h
+++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -11,6 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task_runner.h"
 #include "base/threading/simple_thread.h"
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 5cd5c99..cc48c78 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/memory/free_deleter.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "printing/backend/print_backend.h"
diff --git a/remoting/base/auto_thread_unittest.cc b/remoting/base/auto_thread_unittest.cc
index 5c72e351..a825753 100644
--- a/remoting/base/auto_thread_unittest.cc
+++ b/remoting/base/auto_thread_unittest.cc
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "remoting/base/auto_thread.h"
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/scoped_native_library.h"
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
-#include "remoting/base/auto_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
diff --git a/remoting/base/run_all_unittests.cc b/remoting/base/run_all_unittests.cc
index b20ac233..110e0ca 100644
--- a/remoting/base/run_all_unittests.cc
+++ b/remoting/base/run_all_unittests.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
 #include "base/threading/thread.h"
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn
index d3ded033..592747e 100644
--- a/remoting/client/BUILD.gn
+++ b/remoting/client/BUILD.gn
@@ -102,6 +102,10 @@
       "OpenSLES",
     ]
   }
+  if (is_ios) {
+    sources += [ "native_device_keymap_ios.cc" ]
+    sources -= [ "native_device_keymap.cc" ]
+  }
 }
 
 source_set("unit_tests") {
diff --git a/remoting/client/native_device_keymap_ios.cc b/remoting/client/native_device_keymap_ios.cc
new file mode 100644
index 0000000..ebaaa71
--- /dev/null
+++ b/remoting/client/native_device_keymap_ios.cc
@@ -0,0 +1,217 @@
+// 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 "remoting/client/native_device_keymap.h"
+
+#include "base/logging.h"
+
+namespace {
+
+// TODO(nicholss): Copied from Android, no changes yet. See how broken this is.
+
+// These must be defined in the same order as the Android keycodes in
+// <android/keycodes.h> and
+// "ui/events/keycodes/keyboard_code_conversion_android.cc" . Some of these
+// mappings assume a US keyboard layout for now.
+const uint32_t usb_keycodes[] = {
+    0,  // UNKNOWN
+    0,  // SOFT_LEFT
+    0,  // SOFT_RIGHT
+    0,  // HOME
+    0,  // BACK
+    0,  // CALL
+    0,  // ENDCALL
+
+    0x070027,  // 0
+    0x07001e,  // 1
+    0x07001f,  // 2
+    0x070020,  // 3
+    0x070021,  // 4
+    0x070022,  // 5
+    0x070023,  // 6
+    0x070024,  // 7
+    0x070025,  // 8
+    0x070026,  // 9
+
+    0,         // STAR
+    0,         // POUND
+    0x070052,  // DPAD_UP
+    0x070051,  // DPAD_DOWN
+    0x070050,  // DPAD_LEFT
+    0x07004f,  // DPAD_RIGHT
+    0,         // DPAD_CENTER
+    0,         // VOLUME_UP
+    0,         // VOLUME_DOWN
+    0,         // POWER
+    0,         // CAMERA
+    0,         // CLEAR
+
+    0x070004,  // A
+    0x070005,  // B
+    0x070006,  // C
+    0x070007,  // D
+    0x070008,  // E
+    0x070009,  // F
+    0x07000a,  // G
+    0x07000b,  // H
+    0x07000c,  // I
+    0x07000d,  // J
+    0x07000e,  // K
+    0x07000f,  // L
+    0x070010,  // M
+    0x070011,  // N
+    0x070012,  // O
+    0x070013,  // P
+    0x070014,  // Q
+    0x070015,  // R
+    0x070016,  // S
+    0x070017,  // T
+    0x070018,  // U
+    0x070019,  // V
+    0x07001a,  // W
+    0x07001b,  // X
+    0x07001c,  // Y
+    0x07001d,  // Z
+
+    0x070036,  // COMMA
+    0x070037,  // PERIOD
+
+    0x0700e2,  // ALT_LEFT
+    0x0700e6,  // ALT_RIGHT
+    0x0700e1,  // SHIFT_LEFT
+    0x0700e5,  // SHIFT_RIGHT
+
+    0x07002b,  // TAB
+    0x07002c,  // SPACE
+
+    0,  // SYM
+    0,  // EXPLORER
+    0,  // ENVELOPE
+
+    0x070028,  // ENTER
+    0x07002a,  // DEL (backspace)
+
+    0x070035,  // GRAVE (backtick)
+    0x07002d,  // MINUS
+    0x07002e,  // EQUALS
+    0x07002f,  // LEFT_BRACKET
+    0x070030,  // RIGHT_BRACKET
+    0x070031,  // BACKSLASH
+    0x070033,  // SEMICOLON
+    0x070034,  // APOSTROPHE
+    0x070038,  // SLASH
+
+    0,  // AT
+    0,  // NUM
+    0,  // HEADSETHOOK
+    0,  // FOCUS
+    0,  // PLUS
+    0,  // MENU
+    0,  // NOTIFICATION
+    0,  // SEARCH
+    0,  // MEDIA_PLAY_PAUSE
+    0,  // MEDIA_STOP
+    0,  // MEDIA_NEXT
+    0,  // MEDIA_PREVIOUS
+    0,  // MEDIA_REWIND
+    0,  // MEDIA_FAST_FORWARD
+    0,  // MUTE
+
+    0x07004b,  // PAGE_UP
+    0x07004e,  // PAGE_DOWN
+
+    0,  // PICTSYMBOLS
+    0,  // SWITCH_CHARSET
+    0,  // BUTTON_A
+    0,  // BUTTON_B
+    0,  // BUTTON_C
+    0,  // BUTTON_X
+    0,  // BUTTON_Y
+    0,  // BUTTON_Z
+    0,  // BUTTON_L1
+    0,  // BUTTON_R1
+    0,  // BUTTON_L2
+    0,  // BUTTON_R2
+    0,  // BUTTON_THUMBL
+    0,  // BUTTON_THUMBR
+    0,  // BUTTON_START
+    0,  // BUTTON_SELECT
+    0,  // BUTTON_MODE
+
+    0x070029,  // ESCAPE
+    0x07004c,  // FORWARD_DEL
+
+    0x0700e0,  // CTRL_LEFT
+    0x0700e4,  // CTRL_RIGHT
+    0,         // CAPS_LOCK
+    0,         // SCROLL_LOCK
+    0x0700e3,  // META_LEFT
+    0x0700e7,  // META_RIGHT
+    0,         // FUNCTION
+
+    0x070046,  // SYSRQ (printscreen)
+    0x070048,  // BREAK (pause)
+    0x07004a,  // MOVE_HOME (home)
+    0x07004d,  // MOVE_END (end)
+    0x070049,  // INSERT
+
+    0,  // FORWARD
+    0,  // MEDIA_PLAY
+    0,  // MEDIA_PAUSE
+    0,  // MEDIA_CLOSE
+    0,  // MEDIA_EJECT
+    0,  // MEDIA_RECORD
+
+    0x07003a,  // F1
+    0x07003b,  // F2
+    0x07003c,  // F3
+    0x07003d,  // F4
+    0x07003e,  // F5
+    0x07003f,  // F6
+    0x070040,  // F7
+    0x070041,  // F8
+    0x070042,  // F9
+    0x070043,  // F10
+    0x070044,  // F11
+    0x070045,  // F12
+
+    0,  // NUM_LOCK
+
+    0x070062,  // NUMPAD_0
+    0x070059,  // NUMPAD_1
+    0x07005a,  // NUMPAD_2
+    0x07005b,  // NUMPAD_3
+    0x07005c,  // NUMPAD_4
+    0x07005d,  // NUMPAD_5
+    0x07005e,  // NUMPAD_6
+    0x07005f,  // NUMPAD_7
+    0x070060,  // NUMPAD_8
+    0x070061,  // NUMPAD_9
+
+    0x070054,  // NUMPAD_DIVIDE
+    0x070055,  // NUMPAD_MULTIPLY
+    0x070056,  // NUMPAD_SUBTRACT
+    0x070057,  // NUMPAD_ADD
+    0x070063,  // NUMPAD_DOT
+    0x070085,  // NUMPAD_COMMA
+    0x070058,  // NUMPAD_ENTER
+    0x070067,  // NUMPAD_EQUALS
+    0x0700b6,  // NUMPAD_LEFT_PAREN
+    0x0700b7,  // NUMPAD_RIGHT_PAREN
+};
+
+}  // namespace
+
+namespace remoting {
+
+uint32_t NativeDeviceKeycodeToUsbKeycode(size_t device_keycode) {
+  if (device_keycode >= sizeof(usb_keycodes) / sizeof(uint32_t)) {
+    LOG(WARNING) << "Attempted to decode out-of-range Android keycode";
+    return 0;
+  }
+
+  return usb_keycodes[device_keycode];
+}
+
+}  // namespace remoting
diff --git a/remoting/host/chromoting_host_context.cc b/remoting/host/chromoting_host_context.cc
index 8807af4f..437a2f13 100644
--- a/remoting/host/chromoting_host_context.cc
+++ b/remoting/host/chromoting_host_context.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "remoting/base/auto_thread.h"
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc
index 8dbf7d4..74498a63 100644
--- a/remoting/host/chromoting_host_unittest.cc
+++ b/remoting/host/chromoting_host_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "remoting/base/auto_thread_task_runner.h"
 #include "remoting/host/audio_capturer.h"
diff --git a/remoting/host/daemon_process_unittest.cc b/remoting/host/daemon_process_unittest.cc
index cbaeb7a..c27b79a9 100644
--- a/remoting/host/daemon_process_unittest.cc
+++ b/remoting/host/daemon_process_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/remoting/host/it2me/it2me_confirmation_dialog_proxy_unittest.cc b/remoting/host/it2me/it2me_confirmation_dialog_proxy_unittest.cc
index a18f3126..dff77915 100644
--- a/remoting/host/it2me/it2me_confirmation_dialog_proxy_unittest.cc
+++ b/remoting/host/it2me/it2me_confirmation_dialog_proxy_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/remoting/host/linux/certificate_watcher_unittest.cc b/remoting/host/linux/certificate_watcher_unittest.cc
index 6738812..3f9fa85 100644
--- a/remoting/host/linux/certificate_watcher_unittest.cc
+++ b/remoting/host/linux/certificate_watcher_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/remoting/host/native_messaging/native_messaging_reader.cc b/remoting/host/native_messaging/native_messaging_reader.cc
index 2ded6a7..112a5db 100644
--- a/remoting/host/native_messaging/native_messaging_reader.cc
+++ b/remoting/host/native_messaging/native_messaging_reader.cc
@@ -13,6 +13,7 @@
 #include "base/json/json_reader.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/remoting/host/security_key/security_key_message_reader.cc b/remoting/host/security_key/security_key_message_reader.cc
index a53d0d0..bb222110 100644
--- a/remoting/host/security_key/security_key_message_reader.cc
+++ b/remoting/host/security_key/security_key_message_reader.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/files/file.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/remoting/host/security_key/security_key_message_reader_impl.cc b/remoting/host/security_key/security_key_message_reader_impl.cc
index 0d283f9..14b8f03 100644
--- a/remoting/host/security_key/security_key_message_reader_impl.cc
+++ b/remoting/host/security_key/security_key_message_reader_impl.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/files/file.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/remoting/host/setup/daemon_controller.cc b/remoting/host/setup/daemon_controller.cc
index 78659f0b..67201a2 100644
--- a/remoting/host/setup/daemon_controller.cc
+++ b/remoting/host/setup/daemon_controller.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
diff --git a/remoting/host/setup/start_host_main.cc b/remoting/host/setup/start_host_main.cc
index 210b454f..4c0d14b5 100644
--- a/remoting/host/setup/start_host_main.cc
+++ b/remoting/host/setup/start_host_main.cc
@@ -9,6 +9,7 @@
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
diff --git a/remoting/host/token_validator_factory_impl_unittest.cc b/remoting/host/token_validator_factory_impl_unittest.cc
index 0a530e3f..76e0567e 100644
--- a/remoting/host/token_validator_factory_impl_unittest.cc
+++ b/remoting/host/token_validator_factory_impl_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "net/base/net_errors.h"
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc
index b1a537f..81ec5b9e 100644
--- a/remoting/host/win/rdp_client.cc
+++ b/remoting/host/win/rdp_client.cc
@@ -12,6 +12,7 @@
 #include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/single_thread_task_runner.h"
 #include "net/base/ip_address.h"
diff --git a/remoting/ios/BUILD.gn b/remoting/ios/BUILD.gn
index c273cdd..4390299 100644
--- a/remoting/ios/BUILD.gn
+++ b/remoting/ios/BUILD.gn
@@ -25,6 +25,8 @@
   sources = [
     "client_gestures.h",
     "client_gestures.mm",
+    "client_keyboard.h",
+    "client_keyboard.mm",
     "host_preferences.h",
     "host_preferences.mm",
     "host_preferences_persistence.h",
diff --git a/remoting/ios/app/host_view_controller.mm b/remoting/ios/app/host_view_controller.mm
index e866d769..8ed12dc 100644
--- a/remoting/ios/app/host_view_controller.mm
+++ b/remoting/ios/app/host_view_controller.mm
@@ -14,17 +14,20 @@
 
 #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h"
 #import "remoting/ios/client_gestures.h"
+#import "remoting/ios/client_keyboard.h"
 #import "remoting/ios/session/remoting_client.h"
 
 #include "remoting/client/gesture_interpreter.h"
 
 static const CGFloat kFabInset = 15.f;
+static const CGFloat kKeyboardAnimationTime = 0.3;
 
 @interface HostViewController () {
   RemotingClient* _client;
   MDCFloatingButton* _floatingButton;
-
   ClientGestures* _clientGestures;
+  ClientKeyboard* _clientKeyboard;
+  CGSize _keyboardSize;
 }
 @end
 
@@ -34,6 +37,7 @@
   self = [super init];
   if (self) {
     _client = client;
+    _keyboardSize = CGSizeZero;
   }
   return self;
 }
@@ -90,12 +94,24 @@
 
   _clientGestures =
       [[ClientGestures alloc] initWithView:self.view client:_client];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(keyboardWillShow:)
+             name:UIKeyboardWillShowNotification
+           object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(keyboardWillHide:)
+             name:UIKeyboardWillHideNotification
+           object:nil];
 }
 
 - (void)viewWillDisappear:(BOOL)animated {
   [super viewWillDisappear:animated];
 
   _clientGestures = nil;
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
 - (void)viewDidLayoutSubviews {
@@ -114,14 +130,95 @@
                  btnSize.width, btnSize.height);
 }
 
+#pragma mark - Keyboard
+
+- (BOOL)isKeyboardActive {
+  if (_clientKeyboard) {
+    return [_clientKeyboard isFirstResponder];
+  }
+  return NO;
+}
+
+- (void)showKeyboard {
+  if (!_clientKeyboard) {
+    _clientKeyboard = [[ClientKeyboard alloc] init];
+    [self.view addSubview:_clientKeyboard];
+    // TODO(nicholss): need to pass some keyboard injection interface here.
+  }
+  [_clientKeyboard becomeFirstResponder];
+}
+
+- (void)hideKeyboard {
+  [_clientKeyboard resignFirstResponder];
+}
+
+#pragma mark - Keyboard Notifications
+
+- (void)keyboardWillShow:(NSNotification*)notification {
+  CGSize keyboardSize =
+      [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey]
+          CGRectValue]
+          .size;
+  if (_keyboardSize.height != keyboardSize.height) {
+    CGFloat deltaHeight = keyboardSize.height - _keyboardSize.height;
+    [UIView animateWithDuration:0.3
+                     animations:^{
+                       CGRect f = self.view.frame;
+                       f.size.height += deltaHeight;
+                       self.view.frame = f;
+                     }];
+    _keyboardSize = keyboardSize;
+  }
+}
+
+- (void)keyboardWillHide:(NSNotification*)notification {
+  [UIView animateWithDuration:kKeyboardAnimationTime
+                   animations:^{
+                     CGRect f = self.view.frame;
+                     f.size.height += _keyboardSize.height;
+                     self.view.frame = f;
+                   }];
+  _keyboardSize = CGSizeZero;
+}
+
 #pragma mark - Private
 
 - (void)didTap:(id)sender {
-  // TODO(nicholss): The FAB is being used to close the window at the moment
-  // just as a demo  as the integration continues. This will not be the case
-  // in the final app.
-  [_client disconnectFromHost];
-  [self dismissViewControllerAnimated:YES completion:nil];
+  // TODO(nicholss): The FAB is being used to launch an alert window with
+  // more options. This is not ideal but it gets us an easy way to make a
+  // modal window option selector. Replace this with a real menu later.
+
+  UIAlertController* alert =
+      [UIAlertController alertControllerWithTitle:@"Remote Settings"
+                                          message:nil
+                                   preferredStyle:UIAlertControllerStyleAlert];
+
+  if ([self isKeyboardActive]) {
+    void (^hideKeyboardHandler)(UIAlertAction*) = ^(UIAlertAction*) {
+      NSLog(@"Will hide keyboard.");
+      [self hideKeyboard];
+    };
+    [alert addAction:[UIAlertAction actionWithTitle:@"Hide Keyboard"
+                                              style:UIAlertActionStyleDefault
+                                            handler:hideKeyboardHandler]];
+  } else {
+    void (^showKeyboardHandler)(UIAlertAction*) = ^(UIAlertAction*) {
+      NSLog(@"Will show keyboard.");
+      [self showKeyboard];
+    };
+    [alert addAction:[UIAlertAction actionWithTitle:@"Show Keyboard"
+                                              style:UIAlertActionStyleDefault
+                                            handler:showKeyboardHandler]];
+  }
+  void (^disconnectHandler)(UIAlertAction*) = ^(UIAlertAction*) {
+    [_client disconnectFromHost];
+    [self dismissViewControllerAnimated:YES completion:nil];
+  };
+  [alert addAction:[UIAlertAction actionWithTitle:@"Disconnect"
+                                            style:UIAlertActionStyleCancel
+                                          handler:disconnectHandler]];
+
+  [self presentViewController:alert animated:YES completion:nil];
 }
 
 @end
diff --git a/remoting/ios/client_gestures.h b/remoting/ios/client_gestures.h
index 455609ed7..cca9d82 100644
--- a/remoting/ios/client_gestures.h
+++ b/remoting/ios/client_gestures.h
@@ -7,8 +7,6 @@
 
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
-#include "base/logging.h"
-#import "remoting/ios/key_input.h"
 
 @class RemotingClient;
 
@@ -24,12 +22,10 @@
 };
 
 typedef NS_ENUM(NSInteger, MouseButton) {
-
   NO_BUTTON = 0,
   LEFT_BUTTON = 1,
   MIDDLE_BUTTON = 2,
   RIGHT_BUTTON = 3,
-
 };
 
 @interface ClientGestures : NSObject<UIGestureRecognizerDelegate> {
diff --git a/remoting/ios/client_gestures.mm b/remoting/ios/client_gestures.mm
index 20e4701c..86f3dbe4 100644
--- a/remoting/ios/client_gestures.mm
+++ b/remoting/ios/client_gestures.mm
@@ -7,8 +7,11 @@
 #endif
 
 #import "remoting/ios/client_gestures.h"
+
+#import "remoting/ios/key_input.h"
 #import "remoting/ios/session/remoting_client.h"
 
+#include "base/logging.h"
 #include "remoting/client/gesture_interpreter.h"
 
 @implementation ClientGestures
diff --git a/remoting/ios/client_keyboard.h b/remoting/ios/client_keyboard.h
new file mode 100644
index 0000000..c846122
--- /dev/null
+++ b/remoting/ios/client_keyboard.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_CLIENT_IOS_CLIENT_KEYBOARD_H_
+#define REMOTING_CLIENT_IOS_CLIENT_KEYBOARD_H_
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface ClientKeyboard : UIView<UIKeyInput, UITextInputTraits>
+
+@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
+@property(nonatomic) UIKeyboardType keyboardType;
+@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
+@property(nonatomic) UITextAutocorrectionType autocorrectionType;
+@property(nonatomic) UITextSpellCheckingType spellCheckingType;
+
+@end
+
+#endif  //  REMOTING_CLIENT_IOS_CLIENT_KEYBOARD_H_
diff --git a/remoting/ios/client_keyboard.mm b/remoting/ios/client_keyboard.mm
new file mode 100644
index 0000000..dccefab
--- /dev/null
+++ b/remoting/ios/client_keyboard.mm
@@ -0,0 +1,62 @@
+// 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.
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#import "remoting/ios/client_keyboard.h"
+
+// TODO(nicholss): Look into inputAccessoryView to get the top bar for sending
+// special keys.
+// TODO(nicholss): Look into inputView - The custom input view to display when
+// the receiver becomes the first responder
+
+@implementation ClientKeyboard
+
+@synthesize autocapitalizationType = _autocapitalizationType;
+@synthesize autocorrectionType = _autocorrectionType;
+@synthesize keyboardAppearance = _keyboardAppearance;
+@synthesize keyboardType = _keyboardType;
+@synthesize spellCheckingType = _spellCheckingType;
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _autocapitalizationType = UITextAutocapitalizationTypeNone;
+    _autocorrectionType = UITextAutocorrectionTypeNo;
+    _autocorrectionType = UITextAutocorrectionTypeNo;
+    _keyboardType = UIKeyboardTypeASCIICapable;
+    _spellCheckingType = UITextSpellCheckingTypeNo;
+  }
+  return self;
+}
+
+#pragma mark - UIKeyInput
+
+- (void)insertText:(NSString*)text {
+  NSLog(@"insertText: %@", text);
+}
+
+- (void)deleteBackward {
+  NSLog(@"deleteBackward");
+}
+
+- (BOOL)hasText {
+  return NO;  // not sure if this enables the back button.
+}
+
+#pragma mark - UIResponder
+
+- (BOOL)canBecomeFirstResponder {
+  return YES;
+}
+
+- (UIView*)inputAccessoryView {
+  return nil;
+}
+
+#pragma mark - UITextInputTraits
+
+@end
diff --git a/remoting/ios/session/remoting_client.h b/remoting/ios/session/remoting_client.h
index 6dbe9f2..8c48a43 100644
--- a/remoting/ios/session/remoting_client.h
+++ b/remoting/ios/session/remoting_client.h
@@ -77,6 +77,8 @@
 // This is valid only after the client has connected to the host. Always use
 // RemotingClient.gestureInterpreter instead of storing the pointer separately.
 @property(nonatomic, readonly) remoting::GestureInterpreter* gestureInterpreter;
+// @property(nonatomic, readonly)
+//     remoting::KeyboardInterpreter* keyboardInterpreter;
 
 @end
 
diff --git a/remoting/ios/session/remoting_client.mm b/remoting/ios/session/remoting_client.mm
index 235400d0..3e9abbd 100644
--- a/remoting/ios/session/remoting_client.mm
+++ b/remoting/ios/session/remoting_client.mm
@@ -40,6 +40,7 @@
   // Call _secretFetchedCallback on the network thread.
   remoting::protocol::SecretFetchedCallback _secretFetchedCallback;
   std::unique_ptr<remoting::GestureInterpreter> _gestureInterpreter;
+  //  std::unique_ptr<remoting::KeyboardInterpreter> _keyboardInterpreter;
 }
 @end
 
diff --git a/remoting/protocol/pseudotcp_adapter_unittest.cc b/remoting/protocol/pseudotcp_adapter_unittest.cc
index 0059204..7118330 100644
--- a/remoting/protocol/pseudotcp_adapter_unittest.cc
+++ b/remoting/protocol/pseudotcp_adapter_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "jingle/glue/thread_wrapper.h"
diff --git a/rlz/lib/rlz_lib_test.cc b/rlz/lib/rlz_lib_test.cc
index a81f317..2b106b8 100644
--- a/rlz/lib/rlz_lib_test.cc
+++ b/rlz/lib/rlz_lib_test.cc
@@ -18,17 +18,17 @@
 #include <memory>
 
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
 #include "rlz/lib/financial_ping.h"
 #include "rlz/lib/net_response_check.h"
 #include "rlz/lib/rlz_lib.h"
 #include "rlz/lib/rlz_value_store.h"
 #include "rlz/test/rlz_test_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_WIN)
 #include <Windows.h>
diff --git a/services/device/battery/battery_status_manager_linux.cc b/services/device/battery/battery_status_manager_linux.cc
index 0448499..a2ed6a51 100644
--- a/services/device/battery/battery_status_manager_linux.cc
+++ b/services/device/battery/battery_status_manager_linux.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc b/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
index 55d08e9e..4cc1840 100644
--- a/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
+++ b/services/resource_coordinator/memory/coordinator/coordinator_impl.cc
@@ -34,8 +34,11 @@
     : failed_memory_dump_count_(0),
       initialize_memory_dump_manager_(initialize_memory_dump_manager) {
   if (initialize_memory_dump_manager) {
+    // TODO(primiano): the current state where the coordinator also creates a
+    // client (ProcessLocalDumpManagerImpl) is contra-intuitive. BrowserMainLoop
+    // should be doing this.
     ProcessLocalDumpManagerImpl::CreateInstance(
-        ProcessLocalDumpManagerImpl::Config(this));
+        ProcessLocalDumpManagerImpl::Config(this, mojom::ProcessType::BROWSER));
     base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id(
         mojom::kServiceTracingProcessId);
   }
@@ -81,7 +84,8 @@
                 << base::trace_event::MemoryDumpLevelOfDetailToString(
                        args.level_of_detail)
                 << ") is already in the queue";
-        callback.Run(args.dump_guid, false /* success */);
+        callback.Run(args.dump_guid, false /* success */,
+                     nullptr /* global_memory_dump */);
         return;
       }
     }
@@ -121,8 +125,7 @@
     DCHECK(!queued_memory_dump_requests_.empty());
     OnProcessMemoryDumpResponse(
         process_manager, queued_memory_dump_requests_.front().args.dump_guid,
-        false /* success */,
-        base::Optional<base::trace_event::MemoryDumpCallbackResult>());
+        false /* success */, nullptr /* process_memory_dump */);
   }
 }
 
@@ -150,15 +153,20 @@
     mojom::ProcessLocalDumpManager* process_manager,
     uint64_t dump_guid,
     bool success,
-    const base::Optional<base::trace_event::MemoryDumpCallbackResult>& result) {
+    mojom::ProcessMemoryDumpPtr process_memory_dump) {
   auto it = pending_process_managers_.find(process_manager);
 
-  DCHECK(!queued_memory_dump_requests_.empty());
-  if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid ||
+  if (queued_memory_dump_requests_.empty() ||
+      queued_memory_dump_requests_.front().args.dump_guid != dump_guid ||
       it == pending_process_managers_.end()) {
     VLOG(1) << "Received unexpected memory dump response: " << dump_guid;
     return;
   }
+  if (process_memory_dump) {
+    queued_memory_dump_requests_.front().process_memory_dumps.push_back(
+        std::move(process_memory_dump));
+  }
+
   pending_process_managers_.erase(it);
 
   if (!success) {
@@ -166,6 +174,7 @@
     VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
             << " failed because of NACK from provider";
   }
+
   FinalizeGlobalMemoryDumpIfAllManagersReplied();
 }
 
@@ -173,13 +182,20 @@
   if (pending_process_managers_.size() > 0)
     return;
 
-  DCHECK(!queued_memory_dump_requests_.empty());
-  {
-    const auto& callback = queued_memory_dump_requests_.front().callback;
-    const bool global_success = failed_memory_dump_count_ == 0;
-    callback.Run(queued_memory_dump_requests_.front().args.dump_guid,
-                 global_success);
+  if (queued_memory_dump_requests_.empty()) {
+    NOTREACHED();
+    return;
   }
+
+  // TODO(hjd,fmeawad): At this point the |process_memory_dumps| accumulated in
+  // queued_memory_dump_requests_.front() should be normalized (merge
+  // |extra_process_dump|, compute CMM) into a GlobalMemoryDumpPtr and passed
+  // below.
+
+  const auto& callback = queued_memory_dump_requests_.front().callback;
+  const bool global_success = failed_memory_dump_count_ == 0;
+  callback.Run(queued_memory_dump_requests_.front().args.dump_guid,
+               global_success, nullptr /* global_memory_dump */);
   queued_memory_dump_requests_.pop_front();
 
   // Schedule the next queued dump (if applicable).
diff --git a/services/resource_coordinator/memory/coordinator/coordinator_impl.h b/services/resource_coordinator/memory/coordinator/coordinator_impl.h
index da41c42..096847b 100644
--- a/services/resource_coordinator/memory/coordinator/coordinator_impl.h
+++ b/services/resource_coordinator/memory/coordinator/coordinator_impl.h
@@ -6,8 +6,8 @@
 #define SERVICES_RESOURCE_COORDINATOR_MEMORY_COORDINATOR_COORDINATOR_IMPL_H_
 
 #include <list>
+#include <map>
 #include <set>
-#include <unordered_map>
 
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
@@ -45,6 +45,9 @@
     ~QueuedMemoryDumpRequest();
     const base::trace_event::MemoryDumpRequestArgs args;
     const RequestGlobalMemoryDumpCallback callback;
+
+    // Collects the data received from OnProcessMemoryDumpResponse().
+    std::vector<mojom::ProcessMemoryDumpPtr> process_memory_dumps;
   };
 
   ~CoordinatorImpl() override;
@@ -69,8 +72,7 @@
       mojom::ProcessLocalDumpManager* process_manager,
       uint64_t dump_guid,
       bool success,
-      const base::Optional<base::trace_event::MemoryDumpCallbackResult>&
-          result);
+      mojom::ProcessMemoryDumpPtr process_memory_dump);
 
   void PerformNextQueuedGlobalMemoryDump();
   void FinalizeGlobalMemoryDumpIfAllManagersReplied();
@@ -78,8 +80,7 @@
   mojo::BindingSet<mojom::Coordinator> bindings_;
 
   // Registered ProcessLocalDumpManagers.
-  std::unordered_map<mojom::ProcessLocalDumpManager*,
-                     mojom::ProcessLocalDumpManagerPtr>
+  std::map<mojom::ProcessLocalDumpManager*, mojom::ProcessLocalDumpManagerPtr>
       process_managers_;
 
   // Pending process managers for RequestGlobalMemoryDump.
diff --git a/services/resource_coordinator/memory/coordinator/coordinator_impl_unittest.cc b/services/resource_coordinator/memory/coordinator/coordinator_impl_unittest.cc
index 521f8f2..f743a2b 100644
--- a/services/resource_coordinator/memory/coordinator/coordinator_impl_unittest.cc
+++ b/services/resource_coordinator/memory/coordinator/coordinator_impl_unittest.cc
@@ -47,7 +47,8 @@
 
   void OnGlobalMemoryDumpResponse(base::Closure closure,
                                   uint64_t dump_guid,
-                                  bool success) {
+                                  bool success,
+                                  mojom::GlobalMemoryDumpPtr) {
     dump_response_args_ = {dump_guid, success};
     closure.Run();
   }
@@ -82,8 +83,7 @@
       const base::trace_event::MemoryDumpRequestArgs& args,
       const RequestProcessMemoryDumpCallback& callback) override {
     expected_calls_--;
-    base::trace_event::MemoryDumpCallbackResult result;
-    callback.Run(args.dump_guid, true, result);
+    callback.Run(args.dump_guid, true, mojom::ProcessMemoryDumpPtr());
   }
 
  private:
diff --git a/services/resource_coordinator/public/cpp/memory/memory_instrumentation.typemap b/services/resource_coordinator/public/cpp/memory/memory_instrumentation.typemap
index f75b5a8..7312558 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_instrumentation.typemap
+++ b/services/resource_coordinator/public/cpp/memory/memory_instrumentation.typemap
@@ -19,5 +19,4 @@
   "memory_instrumentation.mojom.PlatformPrivateFootprint=base::trace_event::ProcessMemoryTotals::PlatformPrivateFootprint",
   "memory_instrumentation.mojom.ChromeMemDump=base::trace_event::MemoryDumpCallbackResult::ChromeMemDump",
   "memory_instrumentation.mojom.OSMemDump=base::trace_event::MemoryDumpCallbackResult::OSMemDump",
-  "memory_instrumentation.mojom.MemoryDumpCallbackResult=base::trace_event::MemoryDumpCallbackResult",
 ]
diff --git a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
index 71ddde7a..b581afe 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
+++ b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.cc
@@ -149,19 +149,4 @@
   return true;
 }
 
-// static
-bool StructTraits<
-    memory_instrumentation::mojom::MemoryDumpCallbackResultDataView,
-    base::trace_event::MemoryDumpCallbackResult>::
-    Read(memory_instrumentation::mojom::MemoryDumpCallbackResultDataView input,
-         base::trace_event::MemoryDumpCallbackResult* out) {
-  if (!input.ReadChromeDump(&out->chrome_dump))
-    return false;
-  if (!input.ReadOsDump(&out->os_dump))
-    return false;
-  if (!input.ReadExtraProcessesDump(&out->extra_processes_dump))
-    return false;
-  return true;
-}
-
 }  // namespace mojo
diff --git a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
index 85af5b88..d94e62f9 100644
--- a/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
+++ b/services/resource_coordinator/public/cpp/memory/memory_instrumentation_struct_traits.h
@@ -130,29 +130,6 @@
                    base::trace_event::MemoryDumpCallbackResult::OSMemDump* out);
 };
 
-template <>
-struct SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT StructTraits<
-    memory_instrumentation::mojom::MemoryDumpCallbackResultDataView,
-    base::trace_event::MemoryDumpCallbackResult> {
-  static base::trace_event::MemoryDumpCallbackResult::OSMemDump os_dump(
-      const base::trace_event::MemoryDumpCallbackResult& args) {
-    return args.os_dump;
-  }
-  static base::trace_event::MemoryDumpCallbackResult::ChromeMemDump chrome_dump(
-      const base::trace_event::MemoryDumpCallbackResult& args) {
-    return args.chrome_dump;
-  }
-  static const std::map<base::ProcessId,
-                        base::trace_event::MemoryDumpCallbackResult::OSMemDump>&
-  extra_processes_dump(
-      const base::trace_event::MemoryDumpCallbackResult& args) {
-    return args.extra_processes_dump;
-  }
-  static bool Read(
-      memory_instrumentation::mojom::MemoryDumpCallbackResultDataView input,
-      base::trace_event::MemoryDumpCallbackResult* out);
-};
-
 }  // namespace mojo
 
 #endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_MEMORY_INSTRUMENTATION_STRUCT_TRAITS_H_
diff --git a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
index 3b9fb7b3..eee8fff078 100644
--- a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.cc
@@ -58,7 +58,30 @@
     const base::trace_event::MemoryDumpRequestArgs& args,
     const RequestProcessMemoryDumpCallback& callback) {
   base::trace_event::MemoryDumpManager::GetInstance()->CreateProcessDump(
-      args, callback);
+      args, base::Bind(&ProcessLocalDumpManagerImpl::OnProcessMemoryDumpDone,
+                       base::Unretained(this), callback));
+}
+
+void ProcessLocalDumpManagerImpl::OnProcessMemoryDumpDone(
+    const RequestProcessMemoryDumpCallback& callback,
+    uint64_t dump_guid,
+    bool success,
+    const base::Optional<base::trace_event::MemoryDumpCallbackResult>& result) {
+  mojom::ProcessMemoryDumpPtr process_memory_dump(
+      mojom::ProcessMemoryDump::New());
+  process_memory_dump->process_type = config_.process_type();
+  if (result) {
+    process_memory_dump->os_dump = result->os_dump;
+    process_memory_dump->chrome_dump = result->chrome_dump;
+    for (const auto& kv : result->extra_processes_dump) {
+      const base::ProcessId pid = kv.first;
+      const base::trace_event::MemoryDumpCallbackResult::OSMemDump&
+          os_mem_dump = kv.second;
+      DCHECK_EQ(0u, process_memory_dump->extra_processes_dump.count(pid));
+      process_memory_dump->extra_processes_dump[pid] = os_mem_dump;
+    }
+  }
+  callback.Run(dump_guid, success, std::move(process_memory_dump));
 }
 
 void ProcessLocalDumpManagerImpl::RequestGlobalMemoryDump(
@@ -70,23 +93,33 @@
   // CoordinatorImpl::RequestGlobalMemoryDump). If the delegate is in a child
   // process, parallel requests will be cancelled.
   //
-  // TODO(chiniforooshan): Unify the child and browser behavior.
+  // TODO(primiano): Remove all this boilerplate. There should be no need of
+  // any lock, proxy, callback adaption or early out. The service is able to
+  // deal with queueing.
   if (task_runner_) {
+    auto callback_proxy =
+        base::Bind(&ProcessLocalDumpManagerImpl::MemoryDumpCallbackProxy,
+                   base::Unretained(this), callback);
     task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&mojom::Coordinator::RequestGlobalMemoryDump,
-                   base::Unretained(coordinator_.get()), args, callback));
+                   base::Unretained(coordinator_.get()), args, callback_proxy));
     return;
   }
 
+  bool early_out_because_of_another_dump_pending = false;
   {
     base::AutoLock lock(pending_memory_dump_guid_lock_);
-    if (pending_memory_dump_guid_) {
-      callback.Run(args.dump_guid, false);
-      return;
-    }
-    pending_memory_dump_guid_ = args.dump_guid;
+    if (pending_memory_dump_guid_)
+      early_out_because_of_another_dump_pending = true;
+    else
+      pending_memory_dump_guid_ = args.dump_guid;
   }
+  if (early_out_because_of_another_dump_pending) {
+    callback.Run(args.dump_guid, false);
+    return;
+  }
+
   auto callback_proxy =
       base::Bind(&ProcessLocalDumpManagerImpl::MemoryDumpCallbackProxy,
                  base::Unretained(this), callback);
@@ -96,12 +129,17 @@
 void ProcessLocalDumpManagerImpl::MemoryDumpCallbackProxy(
     const base::trace_event::GlobalMemoryDumpCallback& callback,
     uint64_t dump_guid,
-    bool success) {
+    bool success,
+    mojom::GlobalMemoryDumpPtr) {
   {
     base::AutoLock lock(pending_memory_dump_guid_lock_);
-    DCHECK_NE(0U, pending_memory_dump_guid_);
     pending_memory_dump_guid_ = 0;
   }
+
+  // The GlobalMemoryDumpPtr argument is ignored. The actual data of the dump
+  // is exposed only through the service and is not passed back to base.
+  // TODO(primiano): All these roundtrips are transitional until we move all
+  // the clients of memory-infra to use directly the service. crbug.com/720352 .
   callback.Run(dump_guid, success);
 }
 
diff --git a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
index 5647e454..5ee725e 100644
--- a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl.h
@@ -33,23 +33,30 @@
   class SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT Config {
    public:
     Config(service_manager::Connector* connector,
-           const std::string& service_name)
+           const std::string& service_name,
+           mojom::ProcessType process_type)
         : connector_(connector),
           service_name_(service_name),
+          process_type_(process_type),
           coordinator_(nullptr) {}
-    Config(Coordinator* coordinator)
-        : connector_(nullptr), coordinator_(coordinator) {}
+    Config(Coordinator* coordinator, mojom::ProcessType process_type)
+        : connector_(nullptr),
+          process_type_(process_type),
+          coordinator_(coordinator) {}
     ~Config();
 
     service_manager::Connector* connector() const { return connector_; }
 
     const std::string& service_name() const { return service_name_; }
 
+    mojom::ProcessType process_type() const { return process_type_; }
+
     Coordinator* coordinator() const { return coordinator_; }
 
    private:
     service_manager::Connector* connector_;
     const std::string service_name_;
+    const mojom::ProcessType process_type_;
     Coordinator* coordinator_;
     bool is_test_config_;
   };
@@ -77,11 +84,19 @@
       const base::trace_event::MemoryDumpRequestArgs& args,
       const RequestProcessMemoryDumpCallback& callback) override;
 
+  // Callback passed to base::MemoryDUmpManager::CreateProcessDump().
+  void OnProcessMemoryDumpDone(
+      const RequestProcessMemoryDumpCallback&,
+      uint64_t dump_guid,
+      bool success,
+      const base::Optional<base::trace_event::MemoryDumpCallbackResult>&);
+
   // A proxy callback for updating |pending_memory_dump_guid_|.
   void MemoryDumpCallbackProxy(
       const base::trace_event::GlobalMemoryDumpCallback& callback,
       uint64_t dump_guid,
-      bool success);
+      bool success,
+      mojom::GlobalMemoryDumpPtr global_memory_dump);
 
   mojom::CoordinatorPtr coordinator_;
   mojo::Binding<mojom::ProcessLocalDumpManager> binding_;
diff --git a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
index c5168a8..1d8aa11 100644
--- a/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
+++ b/services/resource_coordinator/public/cpp/memory/process_local_dump_manager_impl_unittest.cc
@@ -36,7 +36,7 @@
   void RequestGlobalMemoryDump(
       const base::trace_event::MemoryDumpRequestArgs& args,
       const RequestGlobalMemoryDumpCallback& callback) override {
-    callback.Run(args.dump_guid, true);
+    callback.Run(args.dump_guid, true, mojom::GlobalMemoryDumpPtr());
   }
 
  private:
@@ -50,7 +50,9 @@
     coordinator_.reset(new MockCoordinator());
     mdm_.reset(new MemoryDumpManager());
     MemoryDumpManager::SetInstanceForTesting(mdm_.get());
-    ProcessLocalDumpManagerImpl::Config config(coordinator_.get());
+    auto process_type = mojom::ProcessType::OTHER;
+    ProcessLocalDumpManagerImpl::Config config(coordinator_.get(),
+                                               process_type);
     local_manager_impl_.reset(new ProcessLocalDumpManagerImpl(config));
     local_manager_impl_->SetAsNonCoordinatorForTesting();
 
diff --git a/services/resource_coordinator/public/interfaces/BUILD.gn b/services/resource_coordinator/public/interfaces/BUILD.gn
index a860ec3..dd081b6 100644
--- a/services/resource_coordinator/public/interfaces/BUILD.gn
+++ b/services/resource_coordinator/public/interfaces/BUILD.gn
@@ -21,7 +21,6 @@
     "//mojo/common:common_custom_types",
   ]
 
-  component_output_prefix = "resource_coordinator_public_interfaces_internal"
   export_class_attribute = "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_EXPORT"
   export_define = "SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_IMPLEMENTATION=1"
   export_header =
diff --git a/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom b/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
index 160ec124..aa1a583e 100644
--- a/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
+++ b/services/resource_coordinator/public/interfaces/memory/memory_instrumentation.mojom
@@ -10,7 +10,7 @@
   PERIODIC_INTERVAL,
   EXPLICITLY_TRIGGERED,
   PEAK_MEMORY_USAGE,
-  SUMMARY_ONLY 
+  SUMMARY_ONLY
 };
 
 enum LevelOfDetail {
@@ -45,25 +45,58 @@
   uint32 v8_total_kb = 0;
 };
 
-struct MemoryDumpCallbackResult {
+enum ProcessType {
+  OTHER,
+  BROWSER,
+  RENDERER,
+  GPU,
+  UTILITY,
+  PLUGIN
+};
+
+// This struct is used both for:
+// 1) The internal communication between the memory service (Coordinator) and
+//    the client library (ProcessLocalDumpManager).
+// 2) The public-facing API Coordinator::RequestGlobalMemoryDump().
+struct ProcessMemoryDump {
+  ProcessType process_type;
   OSMemDump os_dump;
   ChromeMemDump chrome_dump;
+
+  // TODO(hjd): add the computed Consistent Memory Metrics footprints here.
+
+  // This is used only in the use-case (1) and only on Linux/CrOS to get
+  // around sandboxing. See crbug.com/461788 .
   map<mojo.common.mojom.ProcessId, OSMemDump> extra_processes_dump;
 };
 
-// There should be at most one implementation of this interface per process.
-interface ProcessLocalDumpManager {
-  // When successful, the dump is appended in the process-local trace buffer of
-  // the target process and an ACK. A summary of the dump is also returned in
-  // case of success.
-  RequestProcessMemoryDump(RequestArgs args) =>
-      (uint64 dump_guid, bool success, MemoryDumpCallbackResult? result);
+
+// This struct is returned by the public-facing API
+// Coordinator::RequestGlobalMemoryDump().
+struct GlobalMemoryDump {
+  array<ProcessMemoryDump> process_dumps;
 };
 
-// Memory Infra service implements this interface. ProcessLocalDumpManagers
-// register themselves using the RegisterProcessLocalDumpManager method and
-// suggest a global memory dump using the RequestGlobalMemoryDump method.
+// This is the interface implemented by the client library. This allows a
+// remote process to contribute to memory-infra dumps. There should be at
+// most one instance of this per hosting process.
+interface ProcessLocalDumpManager {
+  // When |success| == true the dump is appended in the process-local trace
+  // buffer of the target process and an ACK. A summary of the dump is also
+  // returned in case of success.
+  RequestProcessMemoryDump(RequestArgs args) =>
+      (uint64 dump_guid, bool success, ProcessMemoryDump? process_memory_dump);
+};
+
+// The memory-infra service implements this interface.
 interface Coordinator {
+  // Used to register a client library to obtain a process-local dump from it
+  // when RequestGlobalMemoryDump() is called.
   RegisterProcessLocalDumpManager(ProcessLocalDumpManager local_manager);
-  RequestGlobalMemoryDump(RequestArgs args) => (uint64 dump_guid, bool success);
+
+  // Broadcasts a dump request to all registered client libraries, injects the
+  // dump in the trace buffer (if tracing is enabled) and returns a summarized
+  // dump back if args.dump_type == SUMMARY_ONLY.
+  RequestGlobalMemoryDump(RequestArgs args) =>
+      (uint64 dump_guid, bool success, GlobalMemoryDump? global_memory_dump);
 };
diff --git a/services/service_manager/background/tests/background_service_manager_unittest.cc b/services/service_manager/background/tests/background_service_manager_unittest.cc
index 3d9f43d..c24639b 100644
--- a/services/service_manager/background/tests/background_service_manager_unittest.cc
+++ b/services/service_manager/background/tests/background_service_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "services/service_manager/background/tests/test.mojom.h"
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc
index d20bb676..f4061db 100644
--- a/services/service_manager/embedder/main.cc
+++ b/services/service_manager/embedder/main.cc
@@ -14,6 +14,7 @@
 #include "base/i18n/icu_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/process/launch.h"
 #include "base/process/memory.h"
diff --git a/services/service_manager/tests/lifecycle/app_client.cc b/services/service_manager/tests/lifecycle/app_client.cc
index eb68ada..2df9e51 100644
--- a/services/service_manager/tests/lifecycle/app_client.cc
+++ b/services/service_manager/tests/lifecycle/app_client.cc
@@ -5,6 +5,7 @@
 #include "services/service_manager/tests/lifecycle/app_client.h"
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "services/service_manager/public/cpp/service_context.h"
 
 namespace service_manager {
diff --git a/services/service_manager/tests/shutdown/shutdown_client_app.cc b/services/service_manager/tests/shutdown/shutdown_client_app.cc
index b7ea364..1e600f7 100644
--- a/services/service_manager/tests/shutdown/shutdown_client_app.cc
+++ b/services/service_manager/tests/shutdown/shutdown_client_app.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/c/main.h"
diff --git a/services/shape_detection/barcode_detection_impl_mac_unittest.mm b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
index 55c2cd27..3184083 100644
--- a/services/shape_detection/barcode_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/barcode_detection_impl_mac_unittest.mm
@@ -9,6 +9,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/mac/sdk_forward_declarations.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm
index 0c04b13..d5f5275 100644
--- a/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -7,6 +7,7 @@
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/services/shape_detection/text_detection_impl_mac_unittest.mm b/services/shape_detection/text_detection_impl_mac_unittest.mm
index 5333a51..f316d8e 100644
--- a/services/shape_detection/text_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/text_detection_impl_mac_unittest.mm
@@ -9,6 +9,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/mac/sdk_forward_declarations.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/services/ui/input_devices/input_device_unittests.cc b/services/ui/input_devices/input_device_unittests.cc
index c11c2337..48f6a58 100644
--- a/services/ui/input_devices/input_device_unittests.cc
+++ b/services/ui/input_devices/input_device_unittests.cc
@@ -5,6 +5,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "services/ui/input_devices/input_device_server.h"
diff --git a/services/ui/main.cc b/services/ui/main.cc
index a2f79bf..faf37799 100644
--- a/services/ui/main.cc
+++ b/services/ui/main.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "services/service_manager/public/c/main.h"
+#include "base/message_loop/message_loop.h"
 #include "services/service_manager/public/cpp/service_runner.h"
 #include "services/ui/service.h"
 
diff --git a/services/ui/public/cpp/gpu/gpu.cc b/services/ui/public/cpp/gpu/gpu.cc
index e70ca6f..6285c21 100644
--- a/services/ui/public/cpp/gpu/gpu.cc
+++ b/services/ui/public/cpp/gpu/gpu.cc
@@ -5,6 +5,7 @@
 #include "services/ui/public/cpp/gpu/gpu.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/scheduling_priority.h"
diff --git a/services/ui/service.cc b/services/ui/service.cc
index 673110c..f44fe04 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/platform_thread.h"
 #include "base/trace_event/trace_event.h"
diff --git a/services/video_capture/test/mock_device_test.cc b/services/video_capture/test/mock_device_test.cc
index d6b66fd..e54edcb 100644
--- a/services/video_capture/test/mock_device_test.cc
+++ b/services/video_capture/test/mock_device_test.cc
@@ -5,6 +5,7 @@
 #include "services/video_capture/test/mock_device_test.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "media/capture/video/video_capture_jpeg_decoder.h"
 #include "media/capture/video/video_capture_system_impl.h"
diff --git a/storage/browser/blob/blob_url_request_job_unittest.cc b/storage/browser/blob/blob_url_request_job_unittest.cc
index 10c3113..7203422 100644
--- a/storage/browser/blob/blob_url_request_job_unittest.cc
+++ b/storage/browser/blob/blob_url_request_job_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index ce836b2..6e52575 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc
index 03b27dd..ed57309 100644
--- a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_piece.h"
diff --git a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
index 66ddc6f..e12134fe 100644
--- a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
+++ b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
@@ -13,6 +13,7 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
diff --git a/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
index 55da6da..ed6f701 100644
--- a/storage/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
index ab682226..f50de10 100644
--- a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/url_request/url_request.h"
diff --git a/storage/browser/fileapi/file_system_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
index bdb9c59..6a39933 100644
--- a/storage/browser/fileapi/file_system_url_request_job_unittest.cc
+++ b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/storage/browser/fileapi/file_writer_delegate_unittest.cc b/storage/browser/fileapi/file_writer_delegate_unittest.cc
index d0524f39..ca213c1f 100644
--- a/storage/browser/fileapi/file_writer_delegate_unittest.cc
+++ b/storage/browser/fileapi/file_writer_delegate_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/storage/browser/fileapi/local_file_stream_reader_unittest.cc b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
index d0c7c720..38b472d 100644
--- a/storage/browser/fileapi/local_file_stream_reader_unittest.cc
+++ b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/storage/browser/fileapi/local_file_stream_writer_unittest.cc b/storage/browser/fileapi/local_file_stream_writer_unittest.cc
index ca79846..265d9bd7 100644
--- a/storage/browser/fileapi/local_file_stream_writer_unittest.cc
+++ b/storage/browser/fileapi/local_file_stream_writer_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
diff --git a/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
index fa6ec78..acae5e0 100644
--- a/storage/browser/fileapi/obfuscated_file_util_unittest.cc
+++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
diff --git a/storage/browser/fileapi/timed_task_helper_unittest.cc b/storage/browser/fileapi/timed_task_helper_unittest.cc
index e3475df..9b5276a 100644
--- a/storage/browser/fileapi/timed_task_helper_unittest.cc
+++ b/storage/browser/fileapi/timed_task_helper_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/storage/browser/quota/storage_monitor_unittest.cc b/storage/browser/quota/storage_monitor_unittest.cc
index 9da7234..f3a2074 100644
--- a/storage/browser/quota/storage_monitor_unittest.cc
+++ b/storage/browser/quota/storage_monitor_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/url_util.h"
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
index c9da201f..ffd3788 100644
--- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -48,7 +48,6 @@
 -ManifestBrowserTest.UseCredentialsSendCookies
 -MediaSessionImplVisibilityBrowserTestInstances/MediaSessionImplVisibilityBrowserTest*
 -NavigationControllerBrowserTest.204Navigation
--NavigationControllerBrowserTest.CorrectLengthWithNewTabNavigatingFromWebUI
 -NavigationControllerBrowserTest.ErrorPageReplacement
 -NavigationControllerBrowserTest.NavigateFromLoadDataWithBaseURL
 -NavigationControllerBrowserTest.NoDialogsFromSwappedOutFrames
@@ -63,11 +62,8 @@
 -PreviewsStateResourceDispatcherHostBrowserTest.ShouldEnableLoFiModeReloadDisableLoFi
 -RenderFrameHostImplBrowserTest.IframeBeforeUnloadParentHang
 -RenderFrameHostManagerTest.ChromeSchemeSubframesStayInProcessWithParent
--RenderFrameHostManagerTest.ClearPendingWebUIOnCommit
 -RenderFrameHostManagerTest.ClickLinkAfter204Error
--RenderFrameHostManagerTest.ForceSwapAfterWebUIBindings
 -RenderFrameHostManagerTest.WebUIGetsBindings
--RenderFrameHostManagerTest.WebUIJavascriptDisallowedAfterSwapOut
 -RenderFrameMessageFilterBrowserTest.Cookies
 -RenderFrameMessageFilterBrowserTest.SameSiteCookies
 -RenderThreadImplBrowserTest.NonResourceDispatchIPCTasksDontGoThroughScheduler
@@ -115,15 +111,6 @@
 -WebContentsViewAuraTest.ScreenshotForSwappedOutRenderViews
 -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithFirstHdSecondVga
 -WebRtcGetUserMediaOldConstraintsBrowserTest.TwoGetUserMediaWithSecondVideoCropped
--WebRtcInternalsBrowserTest.AddAndRemovePeerConnection
--WebRtcInternalsBrowserTest.AddStats
--WebRtcInternalsBrowserTest.BweCompoundGraph
--WebRtcInternalsBrowserTest.ConvertedGraphs
--WebRtcInternalsBrowserTest.CreatePageDump
--WebRtcInternalsBrowserTest.ReceivedPropagationDelta
--WebRtcInternalsBrowserTest.UpdateAllPeerConnections
--WebRtcInternalsBrowserTest.UpdateGetUserMedia
--WebRtcInternalsBrowserTest.UpdatePeerConnection
 -WebUIMojoTest.EndToEndPing
 -WorkerTest.SharedWorkerHttpAuth
 -WorkerTest.WorkerHttpAuth
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 6b2d5dd7..e9540d6 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -226,6 +226,26 @@
             ]
         }
     ],
+    "AutofillUkmLogging": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "AutofillUkmLogging"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutomaticTabDiscarding": [
         {
             "platforms": [
@@ -1115,7 +1135,7 @@
                 {
                     "name": "Enabled",
                     "params": {
-                        "engagement_threshold_for_flash": "16"
+                        "engagement_threshold_for_flash": "32"
                     },
                     "enable_features": [
                         "PreferHtmlOverPlugins"
diff --git a/third_party/WebKit/LayoutTests/css1/font_properties/OWNERS b/third_party/WebKit/LayoutTests/css1/font_properties/OWNERS
index 261aa8c..75630178 100644
--- a/third_party/WebKit/LayoutTests/css1/font_properties/OWNERS
+++ b/third_party/WebKit/LayoutTests/css1/font_properties/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Fonts
diff --git a/third_party/WebKit/LayoutTests/css1/text_properties/OWNERS b/third_party/WebKit/LayoutTests/css1/text_properties/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/css1/text_properties/OWNERS
+++ b/third_party/WebKit/LayoutTests/css1/text_properties/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/css3/fonts/OWNERS b/third_party/WebKit/LayoutTests/css3/fonts/OWNERS
index 261aa8c..75630178 100644
--- a/third_party/WebKit/LayoutTests/css3/fonts/OWNERS
+++ b/third_party/WebKit/LayoutTests/css3/fonts/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Fonts
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-image-threshold-003-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-image-threshold-003-expected.txt
new file mode 100644
index 0000000..785404a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-image-threshold-003-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS shape-image-threshold can be assigned 'inherit' value 
+FAIL shape-image-threshold is not inherited and defaults to 0 assert_equals: expected (object) null but got (string) ""
+PASS shape-margin is not inherited 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-002-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-002-expected.txt
new file mode 100644
index 0000000..27f19c37
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-002-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+FAIL 10.12345px - inline assert_equals: expected "10.12345px" but got "10.1235px"
+PASS .5px - inline 
+PASS +15px - inline 
+PASS +10.678px - inline 
+FAIL 10.12345px - computed assert_equals: expected "10.123px" but got "10.124px"
+PASS .5px - computed 
+PASS +15px - computed 
+PASS +10.678px - computed 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-005-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-005-expected.txt
new file mode 100644
index 0000000..8160f7c8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-margin-005-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS shape-margin can be assigned 'inherit' value 
+FAIL shape-margin is not inherited and defaults to 0px assert_equals: expected (object) null but got (string) ""
+PASS shape-margin is not inherited 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-inset-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-inset-001-expected.txt
new file mode 100644
index 0000000..6986f6a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes-1/shape-outside/values/shape-outside-inset-001-expected.txt
@@ -0,0 +1,688 @@
+This is a testharness.js-based test.
+Found 684 tests; 668 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS One arg - cm - inline 
+PASS One arg - % - inline 
+PASS Two args - cm cm - inline 
+PASS Two args - cm % - inline 
+PASS Two args - % cm - inline 
+PASS Two args - % % - inline 
+PASS Three args - cm cm cm - inline 
+PASS Three args - cm cm % - inline 
+PASS Three args - cm % cm - inline 
+PASS Three args - cm % %  - inline 
+PASS Three args - % cm cm - inline 
+PASS Three args - % cm %  - inline 
+PASS Three args - % % cm  - inline 
+PASS Three args - % % %  - inline 
+PASS Four args - cm cm cm cm - inline 
+PASS Four args - cm cm cm % - inline 
+PASS Four args - cm cm % cm - inline 
+PASS Four args - cm cm % % - inline 
+PASS Four args - cm % cm cm - inline 
+PASS Four args - cm % cm % - inline 
+PASS Four args - cm % % cm - inline 
+PASS Four args - cm % % % - inline 
+PASS Four args - % cm cm cm - inline 
+PASS Four args - % cm cm % - inline 
+PASS Four args - % cm % cm - inline 
+PASS Four args - % cm % % - inline 
+PASS Four args - % % cm cm - inline 
+PASS Four args - % % cm % - inline 
+PASS Four args - % % % cm - inline 
+PASS Four args - % % % % - inline 
+PASS One arg - mm - inline 
+PASS Two args - mm mm - inline 
+PASS Two args - mm % - inline 
+PASS Two args - % mm - inline 
+PASS Three args - mm mm mm - inline 
+PASS Three args - mm mm % - inline 
+PASS Three args - mm % mm - inline 
+PASS Three args - mm % %  - inline 
+PASS Three args - % mm mm - inline 
+PASS Three args - % mm %  - inline 
+PASS Three args - % % mm  - inline 
+PASS Four args - mm mm mm mm - inline 
+PASS Four args - mm mm mm % - inline 
+PASS Four args - mm mm % mm - inline 
+PASS Four args - mm mm % % - inline 
+PASS Four args - mm % mm mm - inline 
+PASS Four args - mm % mm % - inline 
+PASS Four args - mm % % mm - inline 
+PASS Four args - mm % % % - inline 
+PASS Four args - % mm mm mm - inline 
+PASS Four args - % mm mm % - inline 
+PASS Four args - % mm % mm - inline 
+PASS Four args - % mm % % - inline 
+PASS Four args - % % mm mm - inline 
+PASS Four args - % % mm % - inline 
+PASS Four args - % % % mm - inline 
+PASS One arg - in - inline 
+PASS Two args - in in - inline 
+PASS Two args - in % - inline 
+PASS Two args - % in - inline 
+PASS Three args - in in in - inline 
+PASS Three args - in in % - inline 
+PASS Three args - in % in - inline 
+PASS Three args - in % %  - inline 
+PASS Three args - % in in - inline 
+PASS Three args - % in %  - inline 
+PASS Three args - % % in  - inline 
+PASS Four args - in in in in - inline 
+PASS Four args - in in in % - inline 
+PASS Four args - in in % in - inline 
+PASS Four args - in in % % - inline 
+PASS Four args - in % in in - inline 
+PASS Four args - in % in % - inline 
+PASS Four args - in % % in - inline 
+PASS Four args - in % % % - inline 
+PASS Four args - % in in in - inline 
+PASS Four args - % in in % - inline 
+PASS Four args - % in % in - inline 
+PASS Four args - % in % % - inline 
+PASS Four args - % % in in - inline 
+PASS Four args - % % in % - inline 
+PASS Four args - % % % in - inline 
+PASS One arg - pt - inline 
+PASS Two args - pt pt - inline 
+PASS Two args - pt % - inline 
+PASS Two args - % pt - inline 
+PASS Three args - pt pt pt - inline 
+PASS Three args - pt pt % - inline 
+PASS Three args - pt % pt - inline 
+PASS Three args - pt % %  - inline 
+PASS Three args - % pt pt - inline 
+PASS Three args - % pt %  - inline 
+PASS Three args - % % pt  - inline 
+PASS Four args - pt pt pt pt - inline 
+PASS Four args - pt pt pt % - inline 
+PASS Four args - pt pt % pt - inline 
+PASS Four args - pt pt % % - inline 
+PASS Four args - pt % pt pt - inline 
+PASS Four args - pt % pt % - inline 
+PASS Four args - pt % % pt - inline 
+PASS Four args - pt % % % - inline 
+PASS Four args - % pt pt pt - inline 
+PASS Four args - % pt pt % - inline 
+PASS Four args - % pt % pt - inline 
+PASS Four args - % pt % % - inline 
+PASS Four args - % % pt pt - inline 
+PASS Four args - % % pt % - inline 
+PASS Four args - % % % pt - inline 
+PASS One arg - pc - inline 
+PASS Two args - pc pc - inline 
+PASS Two args - pc % - inline 
+PASS Two args - % pc - inline 
+PASS Three args - pc pc pc - inline 
+PASS Three args - pc pc % - inline 
+PASS Three args - pc % pc - inline 
+PASS Three args - pc % %  - inline 
+PASS Three args - % pc pc - inline 
+PASS Three args - % pc %  - inline 
+PASS Three args - % % pc  - inline 
+PASS Four args - pc pc pc pc - inline 
+PASS Four args - pc pc pc % - inline 
+PASS Four args - pc pc % pc - inline 
+PASS Four args - pc pc % % - inline 
+PASS Four args - pc % pc pc - inline 
+PASS Four args - pc % pc % - inline 
+PASS Four args - pc % % pc - inline 
+PASS Four args - pc % % % - inline 
+PASS Four args - % pc pc pc - inline 
+PASS Four args - % pc pc % - inline 
+PASS Four args - % pc % pc - inline 
+PASS Four args - % pc % % - inline 
+PASS Four args - % % pc pc - inline 
+PASS Four args - % % pc % - inline 
+PASS Four args - % % % pc - inline 
+PASS One arg - em - inline 
+PASS Two args - em em - inline 
+PASS Two args - em % - inline 
+PASS Two args - % em - inline 
+PASS Three args - em em em - inline 
+PASS Three args - em em % - inline 
+PASS Three args - em % em - inline 
+PASS Three args - em % %  - inline 
+PASS Three args - % em em - inline 
+PASS Three args - % em %  - inline 
+PASS Three args - % % em  - inline 
+PASS Four args - em em em em - inline 
+PASS Four args - em em em % - inline 
+PASS Four args - em em % em - inline 
+PASS Four args - em em % % - inline 
+PASS Four args - em % em em - inline 
+PASS Four args - em % em % - inline 
+PASS Four args - em % % em - inline 
+PASS Four args - em % % % - inline 
+PASS Four args - % em em em - inline 
+PASS Four args - % em em % - inline 
+PASS Four args - % em % em - inline 
+PASS Four args - % em % % - inline 
+PASS Four args - % % em em - inline 
+PASS Four args - % % em % - inline 
+PASS Four args - % % % em - inline 
+PASS One arg - ex - inline 
+PASS Two args - ex ex - inline 
+PASS Two args - ex % - inline 
+PASS Two args - % ex - inline 
+PASS Three args - ex ex ex - inline 
+PASS Three args - ex ex % - inline 
+PASS Three args - ex % ex - inline 
+PASS Three args - ex % %  - inline 
+PASS Three args - % ex ex - inline 
+PASS Three args - % ex %  - inline 
+PASS Three args - % % ex  - inline 
+PASS Four args - ex ex ex ex - inline 
+PASS Four args - ex ex ex % - inline 
+PASS Four args - ex ex % ex - inline 
+PASS Four args - ex ex % % - inline 
+PASS Four args - ex % ex ex - inline 
+PASS Four args - ex % ex % - inline 
+PASS Four args - ex % % ex - inline 
+PASS Four args - ex % % % - inline 
+PASS Four args - % ex ex ex - inline 
+PASS Four args - % ex ex % - inline 
+PASS Four args - % ex % ex - inline 
+PASS Four args - % ex % % - inline 
+PASS Four args - % % ex ex - inline 
+PASS Four args - % % ex % - inline 
+PASS Four args - % % % ex - inline 
+PASS One arg - ch - inline 
+PASS Two args - ch ch - inline 
+PASS Two args - ch % - inline 
+PASS Two args - % ch - inline 
+PASS Three args - ch ch ch - inline 
+PASS Three args - ch ch % - inline 
+PASS Three args - ch % ch - inline 
+PASS Three args - ch % %  - inline 
+PASS Three args - % ch ch - inline 
+PASS Three args - % ch %  - inline 
+PASS Three args - % % ch  - inline 
+PASS Four args - ch ch ch ch - inline 
+PASS Four args - ch ch ch % - inline 
+PASS Four args - ch ch % ch - inline 
+PASS Four args - ch ch % % - inline 
+PASS Four args - ch % ch ch - inline 
+PASS Four args - ch % ch % - inline 
+PASS Four args - ch % % ch - inline 
+PASS Four args - ch % % % - inline 
+PASS Four args - % ch ch ch - inline 
+PASS Four args - % ch ch % - inline 
+PASS Four args - % ch % ch - inline 
+PASS Four args - % ch % % - inline 
+PASS Four args - % % ch ch - inline 
+PASS Four args - % % ch % - inline 
+PASS Four args - % % % ch - inline 
+PASS One arg - rem - inline 
+PASS Two args - rem rem - inline 
+PASS Two args - rem % - inline 
+PASS Two args - % rem - inline 
+PASS Three args - rem rem rem - inline 
+PASS Three args - rem rem % - inline 
+PASS Three args - rem % rem - inline 
+PASS Three args - rem % %  - inline 
+PASS Three args - % rem rem - inline 
+PASS Three args - % rem %  - inline 
+PASS Three args - % % rem  - inline 
+PASS Four args - rem rem rem rem - inline 
+PASS Four args - rem rem rem % - inline 
+PASS Four args - rem rem % rem - inline 
+PASS Four args - rem rem % % - inline 
+PASS Four args - rem % rem rem - inline 
+PASS Four args - rem % rem % - inline 
+PASS Four args - rem % % rem - inline 
+PASS Four args - rem % % % - inline 
+PASS Four args - % rem rem rem - inline 
+PASS Four args - % rem rem % - inline 
+PASS Four args - % rem % rem - inline 
+PASS Four args - % rem % % - inline 
+PASS Four args - % % rem rem - inline 
+PASS Four args - % % rem % - inline 
+PASS Four args - % % % rem - inline 
+PASS One arg - vw - inline 
+PASS Two args - vw vw - inline 
+PASS Two args - vw % - inline 
+PASS Two args - % vw - inline 
+PASS Three args - vw vw vw - inline 
+PASS Three args - vw vw % - inline 
+PASS Three args - vw % vw - inline 
+PASS Three args - vw % %  - inline 
+PASS Three args - % vw vw - inline 
+PASS Three args - % vw %  - inline 
+PASS Three args - % % vw  - inline 
+PASS Four args - vw vw vw vw - inline 
+PASS Four args - vw vw vw % - inline 
+PASS Four args - vw vw % vw - inline 
+PASS Four args - vw vw % % - inline 
+PASS Four args - vw % vw vw - inline 
+PASS Four args - vw % vw % - inline 
+PASS Four args - vw % % vw - inline 
+PASS Four args - vw % % % - inline 
+PASS Four args - % vw vw vw - inline 
+PASS Four args - % vw vw % - inline 
+PASS Four args - % vw % vw - inline 
+PASS Four args - % vw % % - inline 
+PASS Four args - % % vw vw - inline 
+PASS Four args - % % vw % - inline 
+PASS Four args - % % % vw - inline 
+PASS One arg - vh - inline 
+PASS Two args - vh vh - inline 
+PASS Two args - vh % - inline 
+PASS Two args - % vh - inline 
+PASS Three args - vh vh vh - inline 
+PASS Three args - vh vh % - inline 
+PASS Three args - vh % vh - inline 
+PASS Three args - vh % %  - inline 
+PASS Three args - % vh vh - inline 
+PASS Three args - % vh %  - inline 
+PASS Three args - % % vh  - inline 
+PASS Four args - vh vh vh vh - inline 
+PASS Four args - vh vh vh % - inline 
+PASS Four args - vh vh % vh - inline 
+PASS Four args - vh vh % % - inline 
+PASS Four args - vh % vh vh - inline 
+PASS Four args - vh % vh % - inline 
+PASS Four args - vh % % vh - inline 
+PASS Four args - vh % % % - inline 
+PASS Four args - % vh vh vh - inline 
+PASS Four args - % vh vh % - inline 
+PASS Four args - % vh % vh - inline 
+PASS Four args - % vh % % - inline 
+PASS Four args - % % vh vh - inline 
+PASS Four args - % % vh % - inline 
+PASS Four args - % % % vh - inline 
+PASS One arg - vmin - inline 
+PASS Two args - vmin vmin - inline 
+PASS Two args - vmin % - inline 
+PASS Two args - % vmin - inline 
+PASS Three args - vmin vmin vmin - inline 
+PASS Three args - vmin vmin % - inline 
+PASS Three args - vmin % vmin - inline 
+PASS Three args - vmin % %  - inline 
+PASS Three args - % vmin vmin - inline 
+PASS Three args - % vmin %  - inline 
+PASS Three args - % % vmin  - inline 
+PASS Four args - vmin vmin vmin vmin - inline 
+PASS Four args - vmin vmin vmin % - inline 
+PASS Four args - vmin vmin % vmin - inline 
+PASS Four args - vmin vmin % % - inline 
+PASS Four args - vmin % vmin vmin - inline 
+PASS Four args - vmin % vmin % - inline 
+PASS Four args - vmin % % vmin - inline 
+PASS Four args - vmin % % % - inline 
+PASS Four args - % vmin vmin vmin - inline 
+PASS Four args - % vmin vmin % - inline 
+PASS Four args - % vmin % vmin - inline 
+PASS Four args - % vmin % % - inline 
+PASS Four args - % % vmin vmin - inline 
+PASS Four args - % % vmin % - inline 
+PASS Four args - % % % vmin - inline 
+PASS One arg - vmax - inline 
+PASS Two args - vmax vmax - inline 
+PASS Two args - vmax % - inline 
+PASS Two args - % vmax - inline 
+PASS Three args - vmax vmax vmax - inline 
+PASS Three args - vmax vmax % - inline 
+PASS Three args - vmax % vmax - inline 
+PASS Three args - vmax % %  - inline 
+PASS Three args - % vmax vmax - inline 
+PASS Three args - % vmax %  - inline 
+PASS Three args - % % vmax  - inline 
+PASS Four args - vmax vmax vmax vmax - inline 
+PASS Four args - vmax vmax vmax % - inline 
+PASS Four args - vmax vmax % vmax - inline 
+PASS Four args - vmax vmax % % - inline 
+PASS Four args - vmax % vmax vmax - inline 
+PASS Four args - vmax % vmax % - inline 
+PASS Four args - vmax % % vmax - inline 
+PASS Four args - vmax % % % - inline 
+PASS Four args - % vmax vmax vmax - inline 
+PASS Four args - % vmax vmax % - inline 
+PASS Four args - % vmax % vmax - inline 
+PASS Four args - % vmax % % - inline 
+PASS Four args - % % vmax vmax - inline 
+PASS Four args - % % vmax % - inline 
+PASS Four args - % % % vmax - inline 
+PASS One arg - cm - computed 
+PASS One arg - % - computed 
+PASS Two args - cm cm - computed 
+PASS Two args - cm % - computed 
+PASS Two args - % cm - computed 
+PASS Two args - % % - computed 
+FAIL Three args - cm cm cm - computed assert_equals: expected "inset(377.953px 755.906px 1133.858px)" but got "inset(377.953px 755.906px 1133.86px)"
+PASS Three args - cm cm % - computed 
+FAIL Three args - cm % cm - computed assert_equals: expected "inset(377.953px 20% 1133.858px)" but got "inset(377.953px 20% 1133.86px)"
+PASS Three args - cm % %  - computed 
+FAIL Three args - % cm cm - computed assert_equals: expected "inset(10% 755.906px 1133.858px)" but got "inset(10% 755.906px 1133.86px)"
+PASS Three args - % cm %  - computed 
+FAIL Three args - % % cm  - computed assert_equals: expected "inset(10% 20% 1133.858px)" but got "inset(10% 20% 1133.86px)"
+PASS Three args - % % %  - computed 
+FAIL Four args - cm cm cm cm - computed assert_equals: expected "inset(377.953px 755.906px 1133.858px 1511.811px)" but got "inset(377.953px 755.906px 1133.86px 1511.81px)"
+FAIL Four args - cm cm cm % - computed assert_equals: expected "inset(377.953px 755.906px 1133.858px 40%)" but got "inset(377.953px 755.906px 1133.86px 40%)"
+FAIL Four args - cm cm % cm - computed assert_equals: expected "inset(377.953px 755.906px 30% 1511.811px)" but got "inset(377.953px 755.906px 30% 1511.81px)"
+PASS Four args - cm cm % % - computed 
+FAIL Four args - cm % cm cm - computed assert_equals: expected "inset(377.953px 20% 1133.858px 1511.811px)" but got "inset(377.953px 20% 1133.86px 1511.81px)"
+FAIL Four args - cm % cm % - computed assert_equals: expected "inset(377.953px 20% 1133.858px 40%)" but got "inset(377.953px 20% 1133.86px 40%)"
+FAIL Four args - cm % % cm - computed assert_equals: expected "inset(377.953px 20% 30% 1511.811px)" but got "inset(377.953px 20% 30% 1511.81px)"
+PASS Four args - cm % % % - computed 
+FAIL Four args - % cm cm cm - computed assert_equals: expected "inset(10% 755.906px 1133.858px 1511.811px)" but got "inset(10% 755.906px 1133.86px 1511.81px)"
+FAIL Four args - % cm cm % - computed assert_equals: expected "inset(10% 755.906px 1133.858px 40%)" but got "inset(10% 755.906px 1133.86px 40%)"
+FAIL Four args - % cm % cm - computed assert_equals: expected "inset(10% 755.906px 30% 1511.811px)" but got "inset(10% 755.906px 30% 1511.81px)"
+PASS Four args - % cm % % - computed 
+FAIL Four args - % % cm cm - computed assert_equals: expected "inset(10% 20% 1133.858px 1511.811px)" but got "inset(10% 20% 1133.86px 1511.81px)"
+FAIL Four args - % % cm % - computed assert_equals: expected "inset(10% 20% 1133.858px 40%)" but got "inset(10% 20% 1133.86px 40%)"
+FAIL Four args - % % % cm - computed assert_equals: expected "inset(10% 20% 30% 1511.811px)" but got "inset(10% 20% 30% 1511.81px)"
+PASS Four args - % % % % - computed 
+PASS One arg - mm - computed 
+PASS Two args - mm mm - computed 
+PASS Two args - mm % - computed 
+PASS Two args - % mm - computed 
+PASS Three args - mm mm mm - computed 
+PASS Three args - mm mm % - computed 
+PASS Three args - mm % mm - computed 
+PASS Three args - mm % %  - computed 
+PASS Three args - % mm mm - computed 
+PASS Three args - % mm %  - computed 
+PASS Three args - % % mm  - computed 
+PASS Four args - mm mm mm mm - computed 
+PASS Four args - mm mm mm % - computed 
+PASS Four args - mm mm % mm - computed 
+PASS Four args - mm mm % % - computed 
+PASS Four args - mm % mm mm - computed 
+PASS Four args - mm % mm % - computed 
+PASS Four args - mm % % mm - computed 
+PASS Four args - mm % % % - computed 
+PASS Four args - % mm mm mm - computed 
+PASS Four args - % mm mm % - computed 
+PASS Four args - % mm % mm - computed 
+PASS Four args - % mm % % - computed 
+PASS Four args - % % mm mm - computed 
+PASS Four args - % % mm % - computed 
+PASS Four args - % % % mm - computed 
+PASS One arg - in - computed 
+PASS Two args - in in - computed 
+PASS Two args - in % - computed 
+PASS Two args - % in - computed 
+PASS Three args - in in in - computed 
+PASS Three args - in in % - computed 
+PASS Three args - in % in - computed 
+PASS Three args - in % %  - computed 
+PASS Three args - % in in - computed 
+PASS Three args - % in %  - computed 
+PASS Three args - % % in  - computed 
+PASS Four args - in in in in - computed 
+PASS Four args - in in in % - computed 
+PASS Four args - in in % in - computed 
+PASS Four args - in in % % - computed 
+PASS Four args - in % in in - computed 
+PASS Four args - in % in % - computed 
+PASS Four args - in % % in - computed 
+PASS Four args - in % % % - computed 
+PASS Four args - % in in in - computed 
+PASS Four args - % in in % - computed 
+PASS Four args - % in % in - computed 
+PASS Four args - % in % % - computed 
+PASS Four args - % % in in - computed 
+PASS Four args - % % in % - computed 
+PASS Four args - % % % in - computed 
+PASS One arg - pt - computed 
+PASS Two args - pt pt - computed 
+PASS Two args - pt % - computed 
+PASS Two args - % pt - computed 
+PASS Three args - pt pt pt - computed 
+PASS Three args - pt pt % - computed 
+PASS Three args - pt % pt - computed 
+PASS Three args - pt % %  - computed 
+PASS Three args - % pt pt - computed 
+PASS Three args - % pt %  - computed 
+PASS Three args - % % pt  - computed 
+PASS Four args - pt pt pt pt - computed 
+PASS Four args - pt pt pt % - computed 
+PASS Four args - pt pt % pt - computed 
+PASS Four args - pt pt % % - computed 
+PASS Four args - pt % pt pt - computed 
+PASS Four args - pt % pt % - computed 
+PASS Four args - pt % % pt - computed 
+PASS Four args - pt % % % - computed 
+PASS Four args - % pt pt pt - computed 
+PASS Four args - % pt pt % - computed 
+PASS Four args - % pt % pt - computed 
+PASS Four args - % pt % % - computed 
+PASS Four args - % % pt pt - computed 
+PASS Four args - % % pt % - computed 
+PASS Four args - % % % pt - computed 
+PASS One arg - pc - computed 
+PASS Two args - pc pc - computed 
+PASS Two args - pc % - computed 
+PASS Two args - % pc - computed 
+PASS Three args - pc pc pc - computed 
+PASS Three args - pc pc % - computed 
+PASS Three args - pc % pc - computed 
+PASS Three args - pc % %  - computed 
+PASS Three args - % pc pc - computed 
+PASS Three args - % pc %  - computed 
+PASS Three args - % % pc  - computed 
+PASS Four args - pc pc pc pc - computed 
+PASS Four args - pc pc pc % - computed 
+PASS Four args - pc pc % pc - computed 
+PASS Four args - pc pc % % - computed 
+PASS Four args - pc % pc pc - computed 
+PASS Four args - pc % pc % - computed 
+PASS Four args - pc % % pc - computed 
+PASS Four args - pc % % % - computed 
+PASS Four args - % pc pc pc - computed 
+PASS Four args - % pc pc % - computed 
+PASS Four args - % pc % pc - computed 
+PASS Four args - % pc % % - computed 
+PASS Four args - % % pc pc - computed 
+PASS Four args - % % pc % - computed 
+PASS Four args - % % % pc - computed 
+PASS One arg - em - computed 
+PASS Two args - em em - computed 
+PASS Two args - em % - computed 
+PASS Two args - % em - computed 
+PASS Three args - em em em - computed 
+PASS Three args - em em % - computed 
+PASS Three args - em % em - computed 
+PASS Three args - em % %  - computed 
+PASS Three args - % em em - computed 
+PASS Three args - % em %  - computed 
+PASS Three args - % % em  - computed 
+PASS Four args - em em em em - computed 
+PASS Four args - em em em % - computed 
+PASS Four args - em em % em - computed 
+PASS Four args - em em % % - computed 
+PASS Four args - em % em em - computed 
+PASS Four args - em % em % - computed 
+PASS Four args - em % % em - computed 
+PASS Four args - em % % % - computed 
+PASS Four args - % em em em - computed 
+PASS Four args - % em em % - computed 
+PASS Four args - % em % em - computed 
+PASS Four args - % em % % - computed 
+PASS Four args - % % em em - computed 
+PASS Four args - % % em % - computed 
+PASS Four args - % % % em - computed 
+PASS One arg - ex - computed 
+PASS Two args - ex ex - computed 
+PASS Two args - ex % - computed 
+PASS Two args - % ex - computed 
+PASS Three args - ex ex ex - computed 
+PASS Three args - ex ex % - computed 
+PASS Three args - ex % ex - computed 
+PASS Three args - ex % %  - computed 
+PASS Three args - % ex ex - computed 
+PASS Three args - % ex %  - computed 
+PASS Three args - % % ex  - computed 
+PASS Four args - ex ex ex ex - computed 
+PASS Four args - ex ex ex % - computed 
+PASS Four args - ex ex % ex - computed 
+PASS Four args - ex ex % % - computed 
+PASS Four args - ex % ex ex - computed 
+PASS Four args - ex % ex % - computed 
+PASS Four args - ex % % ex - computed 
+PASS Four args - ex % % % - computed 
+PASS Four args - % ex ex ex - computed 
+PASS Four args - % ex ex % - computed 
+PASS Four args - % ex % ex - computed 
+PASS Four args - % ex % % - computed 
+PASS Four args - % % ex ex - computed 
+PASS Four args - % % ex % - computed 
+PASS Four args - % % % ex - computed 
+PASS One arg - ch - computed 
+PASS Two args - ch ch - computed 
+PASS Two args - ch % - computed 
+PASS Two args - % ch - computed 
+PASS Three args - ch ch ch - computed 
+PASS Three args - ch ch % - computed 
+PASS Three args - ch % ch - computed 
+PASS Three args - ch % %  - computed 
+PASS Three args - % ch ch - computed 
+PASS Three args - % ch %  - computed 
+PASS Three args - % % ch  - computed 
+PASS Four args - ch ch ch ch - computed 
+PASS Four args - ch ch ch % - computed 
+PASS Four args - ch ch % ch - computed 
+PASS Four args - ch ch % % - computed 
+PASS Four args - ch % ch ch - computed 
+PASS Four args - ch % ch % - computed 
+PASS Four args - ch % % ch - computed 
+PASS Four args - ch % % % - computed 
+PASS Four args - % ch ch ch - computed 
+PASS Four args - % ch ch % - computed 
+PASS Four args - % ch % ch - computed 
+PASS Four args - % ch % % - computed 
+PASS Four args - % % ch ch - computed 
+PASS Four args - % % ch % - computed 
+PASS Four args - % % % ch - computed 
+PASS One arg - rem - computed 
+PASS Two args - rem rem - computed 
+PASS Two args - rem % - computed 
+PASS Two args - % rem - computed 
+PASS Three args - rem rem rem - computed 
+PASS Three args - rem rem % - computed 
+PASS Three args - rem % rem - computed 
+PASS Three args - rem % %  - computed 
+PASS Three args - % rem rem - computed 
+PASS Three args - % rem %  - computed 
+PASS Three args - % % rem  - computed 
+PASS Four args - rem rem rem rem - computed 
+PASS Four args - rem rem rem % - computed 
+PASS Four args - rem rem % rem - computed 
+PASS Four args - rem rem % % - computed 
+PASS Four args - rem % rem rem - computed 
+PASS Four args - rem % rem % - computed 
+PASS Four args - rem % % rem - computed 
+PASS Four args - rem % % % - computed 
+PASS Four args - % rem rem rem - computed 
+PASS Four args - % rem rem % - computed 
+PASS Four args - % rem % rem - computed 
+PASS Four args - % rem % % - computed 
+PASS Four args - % % rem rem - computed 
+PASS Four args - % % rem % - computed 
+PASS Four args - % % % rem - computed 
+PASS One arg - vw - computed 
+PASS Two args - vw vw - computed 
+PASS Two args - vw % - computed 
+PASS Two args - % vw - computed 
+PASS Three args - vw vw vw - computed 
+PASS Three args - vw vw % - computed 
+PASS Three args - vw % vw - computed 
+PASS Three args - vw % %  - computed 
+PASS Three args - % vw vw - computed 
+PASS Three args - % vw %  - computed 
+PASS Three args - % % vw  - computed 
+PASS Four args - vw vw vw vw - computed 
+PASS Four args - vw vw vw % - computed 
+PASS Four args - vw vw % vw - computed 
+PASS Four args - vw vw % % - computed 
+PASS Four args - vw % vw vw - computed 
+PASS Four args - vw % vw % - computed 
+PASS Four args - vw % % vw - computed 
+PASS Four args - vw % % % - computed 
+PASS Four args - % vw vw vw - computed 
+PASS Four args - % vw vw % - computed 
+PASS Four args - % vw % vw - computed 
+PASS Four args - % vw % % - computed 
+PASS Four args - % % vw vw - computed 
+PASS Four args - % % vw % - computed 
+PASS Four args - % % % vw - computed 
+PASS One arg - vh - computed 
+PASS Two args - vh vh - computed 
+PASS Two args - vh % - computed 
+PASS Two args - % vh - computed 
+PASS Three args - vh vh vh - computed 
+PASS Three args - vh vh % - computed 
+PASS Three args - vh % vh - computed 
+PASS Three args - vh % %  - computed 
+PASS Three args - % vh vh - computed 
+PASS Three args - % vh %  - computed 
+PASS Three args - % % vh  - computed 
+PASS Four args - vh vh vh vh - computed 
+PASS Four args - vh vh vh % - computed 
+PASS Four args - vh vh % vh - computed 
+PASS Four args - vh vh % % - computed 
+PASS Four args - vh % vh vh - computed 
+PASS Four args - vh % vh % - computed 
+PASS Four args - vh % % vh - computed 
+PASS Four args - vh % % % - computed 
+PASS Four args - % vh vh vh - computed 
+PASS Four args - % vh vh % - computed 
+PASS Four args - % vh % vh - computed 
+PASS Four args - % vh % % - computed 
+PASS Four args - % % vh vh - computed 
+PASS Four args - % % vh % - computed 
+PASS Four args - % % % vh - computed 
+PASS One arg - vmin - computed 
+PASS Two args - vmin vmin - computed 
+PASS Two args - vmin % - computed 
+PASS Two args - % vmin - computed 
+PASS Three args - vmin vmin vmin - computed 
+PASS Three args - vmin vmin % - computed 
+PASS Three args - vmin % vmin - computed 
+PASS Three args - vmin % %  - computed 
+PASS Three args - % vmin vmin - computed 
+PASS Three args - % vmin %  - computed 
+PASS Three args - % % vmin  - computed 
+PASS Four args - vmin vmin vmin vmin - computed 
+PASS Four args - vmin vmin vmin % - computed 
+PASS Four args - vmin vmin % vmin - computed 
+PASS Four args - vmin vmin % % - computed 
+PASS Four args - vmin % vmin vmin - computed 
+PASS Four args - vmin % vmin % - computed 
+PASS Four args - vmin % % vmin - computed 
+PASS Four args - vmin % % % - computed 
+PASS Four args - % vmin vmin vmin - computed 
+PASS Four args - % vmin vmin % - computed 
+PASS Four args - % vmin % vmin - computed 
+PASS Four args - % vmin % % - computed 
+PASS Four args - % % vmin vmin - computed 
+PASS Four args - % % vmin % - computed 
+PASS Four args - % % % vmin - computed 
+PASS One arg - vmax - computed 
+PASS Two args - vmax vmax - computed 
+PASS Two args - vmax % - computed 
+PASS Two args - % vmax - computed 
+PASS Three args - vmax vmax vmax - computed 
+PASS Three args - vmax vmax % - computed 
+PASS Three args - vmax % vmax - computed 
+PASS Three args - vmax % %  - computed 
+PASS Three args - % vmax vmax - computed 
+PASS Three args - % vmax %  - computed 
+PASS Three args - % % vmax  - computed 
+PASS Four args - vmax vmax vmax vmax - computed 
+PASS Four args - vmax vmax vmax % - computed 
+PASS Four args - vmax vmax % vmax - computed 
+PASS Four args - vmax vmax % % - computed 
+PASS Four args - vmax % vmax vmax - computed 
+PASS Four args - vmax % vmax % - computed 
+PASS Four args - vmax % % vmax - computed 
+PASS Four args - vmax % % % - computed 
+PASS Four args - % vmax vmax vmax - computed 
+PASS Four args - % vmax vmax % - computed 
+PASS Four args - % vmax % vmax - computed 
+PASS Four args - % vmax % % - computed 
+PASS Four args - % % vmax vmax - computed 
+PASS Four args - % % vmax % - computed 
+PASS Four args - % % % vmax - computed 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/lists/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/lists/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/lists/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/lists/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-hr-element-0/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/images/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/images/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/images/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/replaced-elements/images/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webmessaging/messageerror-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webmessaging/messageerror-expected.txt
deleted file mode 100644
index e36474c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webmessaging/messageerror-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL The default value of onmessageerror is null assert_equals: body expected (object) null but got (undefined) undefined
-FAIL The onmessageerror content attribute must be compiled into the onmessageerror property assert_equals: The onmessageerror property must be a function expected "function" but got "undefined"
-FAIL The onmessageerror content attribute must execute when an event is dispatched on the window assert_true: Dispatching the event must run the code expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html
new file mode 100644
index 0000000..f1e3bb5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html
@@ -0,0 +1,9 @@
+<script>
+'use strict';
+
+Promise.resolve().then(() => navigator.usb.getDevices()).then(devices => {
+  window.parent.postMessage('#OK', '*');
+}, error => {
+  window.parent.postMessage('#' + error.name, '*');
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js
new file mode 100644
index 0000000..243242ee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js
@@ -0,0 +1,14 @@
+function assert_usb_available_in_iframe(test, origin, expected) {
+  let frame = document.createElement('iframe');
+  frame.src = origin + '/webusb/resources/check-availability.html';
+
+  window.addEventListener('message', test.step_func(evt => {
+    if (evt.source == frame.contentWindow) {
+      assert_equals(evt.data, expected);
+      document.body.removeChild(frame);
+      test.done();
+    }
+  }));
+
+  document.body.appendChild(frame);
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html
new file mode 100644
index 0000000..302e7f4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+'use strict';
+
+async_test(t => {
+  let frame = document.createElement('iframe');
+  frame.src = 'https://{{domains[www]}}:{{ports[https][0]}}/webusb/resources/check-availability.html';
+  frame.allow = 'usb';
+
+  window.addEventListener('message', t.step_func(evt => {
+    if (evt.source == frame.contentWindow) {
+      assert_equals(evt.data, '#OK');
+      document.body.removeChild(frame);
+      t.done();
+    }
+  }));
+
+  document.body.appendChild(frame);
+}, 'Feature policy "usb" can be enabled in cross-origin iframes using "allowed" attribute.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..288a3ac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=resources/featurepolicytest.js></script>
+<script>
+'use strict';
+
+promise_test(
+    () => navigator.usb.getDevices(),
+    'Feature-Policy header {"usb": ["*"]} allows the top-level document.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, '', '#OK');
+}, 'Feature-Policy header {"usb": ["*"]} allows same-origin iframes.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#OK');
+}, 'Feature-Policy header {"usb": ["*"]} allows cross-origin iframes.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..f10a282c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: {"usb": ["*"]}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html
new file mode 100644
index 0000000..1579815
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=resources/featurepolicytest.js></script>
+<script>
+'use strict';
+
+promise_test(
+    () => navigator.usb.getDevices(),
+    'Default "usb" feature policy ["self"] allows the top-level document.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, '', '#OK');
+}, 'Default "usb" feature policy ["self"] allows same-origin iframes.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#SecurityError');
+}, 'Default "usb" feature policy ["self"] disallows cross-origin iframes.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..b1e555c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=resources/featurepolicytest.js></script>
+<script>
+'use strict';
+
+promise_test(() => {
+  return navigator.usb.getDevices().then(() => {
+    assert_unreached('expected promise to reject with SecurityError');
+  }, error => {
+    assert_equals(error.name, 'SecurityError');
+  });
+}, 'Feature-Policy header {"usb": []} disallows the top-level document.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, '', '#SecurityError');
+}, 'Feature-Policy header {"usb": []} disallows same-origin iframes.');
+
+async_test(t => {
+  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#SecurityError');
+}, 'Feature-Policy header {"usb": []} disallows cross-origin iframes.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..24332c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: {"usb": []}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/multiple-workers/001.html b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/multiple-workers/001.html
index 82ddcc3..65e7917a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/multiple-workers/001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/multiple-workers/001.html
@@ -38,4 +38,3 @@
 <!--
 */
 //-->
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/xhr/004.html b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/xhr/004.html
index ec5893a..d0d82f2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/xhr/004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/xhr/004.html
@@ -32,5 +32,3 @@
 <!--
 */
 //-->
-
-
diff --git a/third_party/WebKit/LayoutTests/fast/alignment/OWNERS b/third_party/WebKit/LayoutTests/fast/alignment/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/alignment/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/alignment/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/autoresize/OWNERS b/third_party/WebKit/LayoutTests/fast/autoresize/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/autoresize/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/autoresize/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/block/OWNERS b/third_party/WebKit/LayoutTests/fast/block/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/block/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/block/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/block-inside-inline/OWNERS b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/block-inside-inline/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/block-inside-inline/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/block-inside-inline/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/auto/OWNERS b/third_party/WebKit/LayoutTests/fast/block/positioning/auto/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/auto/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/auto/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/OWNERS b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/OWNERS b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/borders/OWNERS b/third_party/WebKit/LayoutTests/fast/borders/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/borders/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/box-sizing/OWNERS b/third_party/WebKit/LayoutTests/fast/box-sizing/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/box-sizing/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/box-sizing/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/clip/OWNERS b/third_party/WebKit/LayoutTests/fast/clip/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/clip/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/clip/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/OWNERS b/third_party/WebKit/LayoutTests/fast/css-grid-layout/OWNERS
index 261aa8c..54598e7f 100644
--- a/third_party/WebKit/LayoutTests/fast/css-grid-layout/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Grid
diff --git a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/OWNERS b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/css-intrinsic-dimensions/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css/containment/OWNERS b/third_party/WebKit/LayoutTests/fast/css/containment/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/css/containment/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/css/containment/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css/content/OWNERS b/third_party/WebKit/LayoutTests/fast/css/content/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/css/content/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/css/content/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css/counters/OWNERS b/third_party/WebKit/LayoutTests/fast/css/counters/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/css/counters/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/css/counters/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/OWNERS
new file mode 100644
index 0000000..7c1ec12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/OWNERS
@@ -0,0 +1,2 @@
+# TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-align-last/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-align-last/OWNERS
deleted file mode 100644
index 261aa8c..0000000
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-align-last/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# TEAM: layout-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/OWNERS
deleted file mode 100644
index 261aa8c..0000000
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# TEAM: layout-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-indent/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-indent/OWNERS
deleted file mode 100644
index 261aa8c..0000000
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-indent/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# TEAM: layout-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-justify/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-justify/OWNERS
deleted file mode 100644
index 261aa8c..0000000
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-justify/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# TEAM: layout-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-word-break/OWNERS b/third_party/WebKit/LayoutTests/fast/css3-text/css3-word-break/OWNERS
deleted file mode 100644
index 261aa8c..0000000
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-word-break/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-# TEAM: layout-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Document/CaretRangeFromPoint/OWNERS b/third_party/WebKit/LayoutTests/fast/dom/Document/CaretRangeFromPoint/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Document/CaretRangeFromPoint/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/dom/Document/CaretRangeFromPoint/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index bef6892..3167519 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -109,6 +109,7 @@
 PASS oldChildWindow.onloadstart is newChildWindow.onloadstart
 PASS oldChildWindow.onlostpointercapture is newChildWindow.onlostpointercapture
 PASS oldChildWindow.onmessage is newChildWindow.onmessage
+PASS oldChildWindow.onmessageerror is newChildWindow.onmessageerror
 PASS oldChildWindow.onmousedown is newChildWindow.onmousedown
 PASS oldChildWindow.onmouseenter is newChildWindow.onmouseenter
 PASS oldChildWindow.onmouseleave is newChildWindow.onmouseleave
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index 45196ef..59a2c86 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -81,6 +81,7 @@
 PASS childWindow.onloadstart is null
 PASS childWindow.onlostpointercapture is null
 PASS childWindow.onmessage is null
+PASS childWindow.onmessageerror is null
 PASS childWindow.onmousedown is null
 PASS childWindow.onmouseenter is null
 PASS childWindow.onmouseleave is null
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index 05dda2b..184076e 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -81,6 +81,7 @@
 PASS childWindow.onloadstart is null
 PASS childWindow.onlostpointercapture is null
 PASS childWindow.onmessage is null
+PASS childWindow.onmessageerror is null
 PASS childWindow.onmousedown is null
 PASS childWindow.onmouseenter is null
 PASS childWindow.onmouseleave is null
diff --git a/third_party/WebKit/LayoutTests/fast/dom/elementsFromPoint/OWNERS b/third_party/WebKit/LayoutTests/fast/dom/elementsFromPoint/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/elementsFromPoint/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/dom/elementsFromPoint/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
index d276101..4f63e4c 100644
--- a/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
+++ b/third_party/WebKit/LayoutTests/fast/events/pointerevents/mouse-pointer-event-properties.html
@@ -212,7 +212,7 @@
 
   debug("--- move pen out of target ---");
   eventSender.mouseMoveTo(x - 5, y - 5, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);
-
+  eventSender.mouseLeave(inputPointerType, penId);
   debug("");
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/OWNERS b/third_party/WebKit/LayoutTests/fast/hidpi/OWNERS
index 261aa8c..83275e8 100644
--- a/third_party/WebKit/LayoutTests/fast/hidpi/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Subpixel
diff --git a/third_party/WebKit/LayoutTests/fast/inline-block/OWNERS b/third_party/WebKit/LayoutTests/fast/inline-block/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/inline-block/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/inline-block/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/inline/OWNERS b/third_party/WebKit/LayoutTests/fast/inline/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/inline/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/inline/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/layout/OWNERS b/third_party/WebKit/LayoutTests/fast/layout/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/layout/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/layout/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/lists/OWNERS b/third_party/WebKit/LayoutTests/fast/lists/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/lists/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/lists/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/OWNERS b/third_party/WebKit/LayoutTests/fast/multicol/OWNERS
index 261aa8c..2edc70a 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/multicol/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>MultiCol
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/balancing/OWNERS b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/balancing/OWNERS
index 261aa8c..2edc70a 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/balancing/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/balancing/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>MultiCol
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/balancing/OWNERS b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/balancing/OWNERS
index 261aa8c..2edc70a 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/balancing/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/balancing/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>MultiCol
diff --git a/third_party/WebKit/LayoutTests/fast/overflow/OWNERS b/third_party/WebKit/LayoutTests/fast/overflow/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/overflow/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/overflow/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/pagination/OWNERS b/third_party/WebKit/LayoutTests/fast/pagination/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/pagination/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/pagination/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/OWNERS b/third_party/WebKit/LayoutTests/fast/replaced/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/replaced/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/replaced/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/OWNERS b/third_party/WebKit/LayoutTests/fast/scroll-behavior/OWNERS
index 261aa8c..b6c7099b 100644
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/OWNERS
@@ -1 +1,2 @@
-# TEAM: layout-dev@chromium.org
+# TEAM: input-dev@chromium.org
+# COMPONENT: Blink>Scroll
diff --git a/third_party/WebKit/LayoutTests/fast/scrolling/OWNERS b/third_party/WebKit/LayoutTests/fast/scrolling/OWNERS
index 261aa8c..b6c7099b 100644
--- a/third_party/WebKit/LayoutTests/fast/scrolling/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/scrolling/OWNERS
@@ -1 +1,2 @@
-# TEAM: layout-dev@chromium.org
+# TEAM: input-dev@chromium.org
+# COMPONENT: Blink>Scroll
diff --git a/third_party/WebKit/LayoutTests/fast/sub-pixel/OWNERS b/third_party/WebKit/LayoutTests/fast/sub-pixel/OWNERS
index 261aa8c..83275e8 100644
--- a/third_party/WebKit/LayoutTests/fast/sub-pixel/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/sub-pixel/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Subpixel
diff --git a/third_party/WebKit/LayoutTests/fast/text-autosizing/OWNERS b/third_party/WebKit/LayoutTests/fast/text-autosizing/OWNERS
index 261aa8c..f5afdf9 100644
--- a/third_party/WebKit/LayoutTests/fast/text-autosizing/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/text-autosizing/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>TextAutosize
diff --git a/third_party/WebKit/LayoutTests/fast/text/OWNERS b/third_party/WebKit/LayoutTests/fast/text/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/fast/text/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/text/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/OWNERS b/third_party/WebKit/LayoutTests/fast/writing-mode/OWNERS
index 261aa8c..5ee69c13 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/OWNERS
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>WritingMode
diff --git a/third_party/WebKit/LayoutTests/fonts/OWNERS b/third_party/WebKit/LayoutTests/fonts/OWNERS
index 261aa8c..75630178 100644
--- a/third_party/WebKit/LayoutTests/fonts/OWNERS
+++ b/third_party/WebKit/LayoutTests/fonts/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Fonts
diff --git a/third_party/WebKit/LayoutTests/fullscreen/OWNERS b/third_party/WebKit/LayoutTests/fullscreen/OWNERS
index 261aa8c..090a88d4 100644
--- a/third_party/WebKit/LayoutTests/fullscreen/OWNERS
+++ b/third_party/WebKit/LayoutTests/fullscreen/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Fullscreen
diff --git a/third_party/WebKit/LayoutTests/http/tests/cache/resources/random-cached-image.php b/third_party/WebKit/LayoutTests/http/tests/cache/resources/random-cached-image.php
new file mode 100644
index 0000000..89d3d56
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/cache/resources/random-cached-image.php
@@ -0,0 +1,42 @@
+<?php
+# The script name is "random-cached-image" because this is expected to return
+# different images on every (re)load to test caching, which is similar to
+# other random-cached* scripts.
+# However, this actually returns an image from a small number of predefined
+# images in sequence,
+# because it is hard to generate random (PNG/JPEG/etc.) images from scratch.
+
+require_once '../../resources/portabilityLayer.php';
+
+if (!sys_get_temp_dir()) {
+    echo "FAIL: No temp dir was returned.\n";
+    exit();
+}
+
+$id = $_GET['id'];
+if (filter_var($id, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>"/^[a-z0-9\-]+$/"))) === false) {
+    echo "FAIL: invalid id.\n";
+    exit();
+}
+
+$countFilename = sys_get_temp_dir() . "/random-cached-image." . $id . ".tmp";
+$count = 0;
+if (file_exists($countFilename)) {
+    $count = file_get_contents($countFilename);
+}
+$count += 1;
+file_put_contents($countFilename, $count);
+
+# Images with different dimensions.
+$imageFilenames = array(
+  '../../resources/square20.png',
+  '../../resources/square100.png',
+  '../../resources/square200.png'
+);
+
+header("Content-type: image/png");
+header("Cache-control: max-age=60000");
+header("ETag: 98765");
+
+readfile($imageFilenames[$count % count($imageFilenames)]);
+?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/fullscreen/OWNERS b/third_party/WebKit/LayoutTests/http/tests/fullscreen/OWNERS
index 261aa8c..40194ba 100644
--- a/third_party/WebKit/LayoutTests/http/tests/fullscreen/OWNERS
+++ b/third_party/WebKit/LayoutTests/http/tests/fullscreen/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Fullscreen
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/force-reload-image-document.html b/third_party/WebKit/LayoutTests/http/tests/images/force-reload-image-document.html
new file mode 100644
index 0000000..9bdfa18
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/images/force-reload-image-document.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+var t = async_test("ForceReload should get a new image for an image document");
+
+function triggerReload() {
+  // This depends on how image documents are implemented by Blink.
+  var iframe = document.getElementById('iframe');
+  var img = iframe.contentDocument.body.getElementsByTagName('img')[0];
+  var originalWidth = img.width;
+  var originalHeight = img.height;
+
+  img.onerror = t.unreached_func();
+  img.onload = t.step_func_done(function() {
+    assert_not_equals(originalWidth, img.width, "Should be reloaded: width");
+    assert_not_equals(originalHeight, img.height, "Should be reloaded: height");
+  });
+
+  if (window.internals) {
+    internals.forceImageReload(img);
+  }
+}
+</script>
+
+<!-- We call triggerReload() strictly after document load event,
+because reloading is not enforced until document load event is finished. -->
+<body onload="setTimeout(t.step_func(triggerReload), 0)">
+<iframe id="iframe" src="../cache/resources/random-cached-image.php?id=force-reload-image-document"></iframe>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/force-reload.html b/third_party/WebKit/LayoutTests/http/tests/images/force-reload.html
new file mode 100644
index 0000000..e33b2d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/images/force-reload.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+var t = async_test("ForceReload should get a new image for an <img> element");
+function triggerReload() {
+  var img = document.getElementById('img');
+  var originalWidth = img.width;
+  var originalHeight = img.height;
+
+  img.onerror = t.unreached_func();
+  img.onload = t.step_func_done(function() {
+    assert_not_equals(originalWidth, img.width, "Should be reloaded: width");
+    assert_not_equals(originalHeight, img.height, "Should be reloaded: height");
+  });
+
+  if (window.internals) {
+    internals.forceImageReload(img);
+  }
+}
+</script>
+
+<!-- We call triggerReload() strictly after document load event,
+because reloading is not enforced until document load event is finished. -->
+<body onload="setTimeout(t.step_func(triggerReload), 0)">
+<img id="img" src="../cache/resources/random-cached-image.php?id=force-reload">
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index e84567a0..f5c809d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -42,10 +42,12 @@
 interface BroadcastChannel : EventTarget
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface BudgetService
     method constructor
     method getBudget
@@ -616,11 +618,13 @@
     method initMessageEvent
 interface MessagePort : EventTarget
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface NavigationPreloadManager
     method constructor
     method disable
diff --git a/third_party/WebKit/LayoutTests/ietestcenter/css3/grid/OWNERS b/third_party/WebKit/LayoutTests/ietestcenter/css3/grid/OWNERS
index 261aa8c..54598e7f 100644
--- a/third_party/WebKit/LayoutTests/ietestcenter/css3/grid/OWNERS
+++ b/third_party/WebKit/LayoutTests/ietestcenter/css3/grid/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Grid
diff --git a/third_party/WebKit/LayoutTests/ietestcenter/css3/multicolumn/OWNERS b/third_party/WebKit/LayoutTests/ietestcenter/css3/multicolumn/OWNERS
index 261aa8c..2edc70a 100644
--- a/third_party/WebKit/LayoutTests/ietestcenter/css3/multicolumn/OWNERS
+++ b/third_party/WebKit/LayoutTests/ietestcenter/css3/multicolumn/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>MultiCol
diff --git a/third_party/WebKit/LayoutTests/ietestcenter/css3/text/OWNERS b/third_party/WebKit/LayoutTests/ietestcenter/css3/text/OWNERS
index 261aa8c..7c1ec12 100644
--- a/third_party/WebKit/LayoutTests/ietestcenter/css3/text/OWNERS
+++ b/third_party/WebKit/LayoutTests/ietestcenter/css3/text/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index bef6892..3167519 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -109,6 +109,7 @@
 PASS oldChildWindow.onloadstart is newChildWindow.onloadstart
 PASS oldChildWindow.onlostpointercapture is newChildWindow.onlostpointercapture
 PASS oldChildWindow.onmessage is newChildWindow.onmessage
+PASS oldChildWindow.onmessageerror is newChildWindow.onmessageerror
 PASS oldChildWindow.onmousedown is newChildWindow.onmousedown
 PASS oldChildWindow.onmouseenter is newChildWindow.onmouseenter
 PASS oldChildWindow.onmouseleave is newChildWindow.onmouseleave
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 5971ca6..9080bda0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -6,10 +6,12 @@
 interface BroadcastChannel : EventTarget
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface ByteLengthQueuingStrategy
     method constructor
     method size
@@ -390,11 +392,13 @@
     method initMessageEvent
 interface MessagePort : EventTarget
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface NavigationPreloadManager
     method constructor
     method disable
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index b741254..116c7198 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -15,10 +15,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface ByteLengthQueuingStrategy
 [Worker]     method constructor
 [Worker]     method size
@@ -416,11 +418,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -756,6 +760,7 @@
 [Worker]     attribute console
 [Worker]     attribute internals
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method gc
 [Worker]     method postMessage
@@ -764,6 +769,7 @@
 [Worker]     method webkitResolveLocalFileSystemSyncURL
 [Worker]     method webkitResolveLocalFileSystemURL
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
index 3921550..1db0a68 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -331,10 +331,12 @@
     attribute @@toStringTag
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface ByteLengthQueuingStrategy
     method constructor
     method size
@@ -1555,6 +1557,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -1581,6 +1584,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -1993,6 +1997,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -2015,6 +2020,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -3494,11 +3500,13 @@
 interface MessagePort : EventTarget
     attribute @@toStringTag
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface MimeType
     attribute @@toStringTag
     getter description
@@ -7702,6 +7710,7 @@
     getter onloadstart
     getter onlostpointercapture
     getter onmessage
+    getter onmessageerror
     getter onmousedown
     getter onmouseenter
     getter onmouseleave
@@ -7879,6 +7888,7 @@
     setter onloadstart
     setter onlostpointercapture
     setter onmessage
+    setter onmessageerror
     setter onmousedown
     setter onmouseenter
     setter onmouseleave
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index e06c0a1..3566f5da 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -15,10 +15,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface ByteLengthQueuingStrategy
 [Worker]     method constructor
 [Worker]     method size
@@ -411,11 +413,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index 473be16..3d70cd1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -260,10 +260,12 @@
     attribute @@toStringTag
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface ByteLengthQueuingStrategy
     method constructor
     method size
@@ -1484,6 +1486,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -1510,6 +1513,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -1922,6 +1926,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -1944,6 +1949,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -3423,11 +3429,13 @@
 interface MessagePort : EventTarget
     attribute @@toStringTag
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface MimeType
     attribute @@toStringTag
     getter description
@@ -7631,6 +7639,7 @@
     getter onloadstart
     getter onlostpointercapture
     getter onmessage
+    getter onmessageerror
     getter onmousedown
     getter onmouseenter
     getter onmouseleave
@@ -7808,6 +7817,7 @@
     setter onloadstart
     setter onlostpointercapture
     setter onmessage
+    setter onmessageerror
     setter onmousedown
     setter onmouseenter
     setter onmouseleave
diff --git a/third_party/WebKit/LayoutTests/scrollbars/OWNERS b/third_party/WebKit/LayoutTests/scrollbars/OWNERS
index 261aa8c..c1db7d5 100644
--- a/third_party/WebKit/LayoutTests/scrollbars/OWNERS
+++ b/third_party/WebKit/LayoutTests/scrollbars/OWNERS
@@ -1 +1,2 @@
 # TEAM: layout-dev@chromium.org
+# COMPONENT: Blink>Layout>Scrollbars
diff --git a/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html b/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html
new file mode 100644
index 0000000..1df6e3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/shapedetection/detector-same-object.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/mojo-helpers.js"></script>
+<script src="resources/mock-barcodedetection.js"></script>
+<script src="resources/mock-facedetection.js"></script>
+<script src="resources/mock-textdetection.js"></script>
+<script>
+
+var createTestForImageData = function(createDetector, mockReady,
+                                      detectionResultTest) {
+  async_test(function(t) {
+
+    var img = new Image();
+    img.onload = function() {
+
+      var canvas = document.createElement("canvas");;
+      canvas.getContext("2d").drawImage(img, 0, 0);
+
+      var theMock = null;
+      mockReady()
+        .then(mock => {
+          theMock = mock;
+          var detector = createDetector();
+          return detector;
+        })
+        .catch(error => {
+          assert_unreached("Error creating Mock Detector: " + error);
+        })
+        .then(detector => {
+          return detector.detect(canvas.getContext("2d").getImageData(
+              0, 0, canvas.width, canvas.height));
+        })
+        .then(detectionResult => {
+          detectionResultTest(detectionResult);
+          t.done();
+        })
+        .catch(error => {
+          assert_unreached("Error during detect(canvas): " + error);
+        });
+    }
+
+    img.src = "../media/content/greenbox.png";
+  });
+};
+
+function CheckDetectedFaceSameObjects(detectedFaces) {
+  assert_greater_than(detectedFaces.length, 0, "Number of faces");
+  assert_equals(detectedFaces[0].boundingBox, detectedFaces[0].boundingBox);
+  assert_equals(detectedFaces[0].landmarks, detectedFaces[0].landmarks);
+}
+
+function CheckDetectedBarcodesSameObjects(detectedBarcodes) {
+  assert_greater_than(detectedBarcodes.length, 0, "Number of barcodes");
+  assert_equals(detectedBarcodes[0].rawValue, detectedBarcodes[0].rawValue);
+  assert_equals(detectedBarcodes[0].boundingBox, detectedBarcodes[0].boundingBox);
+  assert_equals(detectedBarcodes[0].cornerPoints, detectedBarcodes[0].cornerPoints);
+}
+
+function CheckDetectedTextBlocksSameObjects(detectedTextBlocks) {
+  assert_greater_than(detectedTextBlocks.length, 0, "Number of textBlocks");
+  assert_equals(detectedTextBlocks[0].rawValue, detectedTextBlocks[0].rawValue);
+  assert_equals(detectedTextBlocks[0].boundingBox, detectedTextBlocks[0].boundingBox);
+}
+
+// These tests verify that detect()ed Detected{Barcode,Face,Text}'s individual
+// fields are [SameObject].
+generate_tests(createTestForImageData, [
+  [
+    "Face - detect(ImageData), [SameObject]",
+    () => { return new FaceDetector(); },
+    () => { return mockFaceDetectionProviderReady; },
+    CheckDetectedFaceSameObjects
+  ],
+  [
+    "Barcode - detect(ImageData), [SameObject]",
+    () => { return new BarcodeDetector(); },
+    () => { return mockBarcodeDetectionReady; },
+    CheckDetectedBarcodesSameObjects
+  ],
+  [
+    "Text - detect(ImageData), [SameObject]",
+    () => { return new TextDetector(); },
+    () => { return mockTextDetectionReady; },
+    CheckDetectedTextBlocksSameObjects
+  ]
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index ebc8b44..8cfc298f 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -42,10 +42,12 @@
 interface BroadcastChannel : EventTarget
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface BudgetService
     method constructor
     method getBudget
@@ -615,11 +617,13 @@
     method initMessageEvent
 interface MessagePort : EventTarget
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface NetworkInformation : EventTarget
     getter downlinkMax
     getter onchange
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 6ce3baf..3e38a2c 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -39,10 +39,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface BudgetService
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -638,11 +640,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NetworkInformation : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter downlinkMax
@@ -2318,6 +2322,7 @@
 [Worker]     attribute console
 [Worker]     attribute internals
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method gc
 [Worker]     method postMessage
@@ -2326,6 +2331,7 @@
 [Worker]     method webkitResolveLocalFileSystemSyncURL
 [Worker]     method webkitResolveLocalFileSystemURL
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index 16b2aca..46fe9ac5f 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -474,10 +474,12 @@
     attribute @@toStringTag
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface BudgetService
     attribute @@toStringTag
     method constructor
@@ -2148,6 +2150,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -2174,6 +2177,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -2591,6 +2595,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -2613,6 +2618,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -4191,11 +4197,13 @@
 interface MessagePort : EventTarget
     attribute @@toStringTag
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface MimeType
     attribute @@toStringTag
     getter description
@@ -8923,6 +8931,7 @@
     getter onloadstart
     getter onlostpointercapture
     getter onmessage
+    getter onmessageerror
     getter onmousedown
     getter onmouseenter
     getter onmouseleave
@@ -9103,6 +9112,7 @@
     setter onloadstart
     setter onlostpointercapture
     setter onmessage
+    setter onmessageerror
     setter onmousedown
     setter onmouseenter
     setter onmouseleave
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt
index 64f2970bb..d1cc1d2 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -39,10 +39,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface BudgetService
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -633,11 +635,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NetworkInformation : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter downlinkMax
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 75e6cc6..2c735ba 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -6,10 +6,12 @@
 interface BroadcastChannel : EventTarget
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface ByteLengthQueuingStrategy
     method constructor
     method size
@@ -390,11 +392,13 @@
     method initMessageEvent
 interface MessagePort : EventTarget
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface NavigationPreloadManager
     method constructor
     method disable
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
index bb07f71..147cba0 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -360,6 +360,7 @@
     property onhashchange
     property onlanguagechange
     property onmessage
+    property onmessageerror
     property onoffline
     property ononline
     property onpagehide
@@ -505,6 +506,7 @@
     property onhashchange
     property onlanguagechange
     property onmessage
+    property onmessageerror
     property onoffline
     property ononline
     property onpagehide
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 77ad9a51..d4e3329 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -15,10 +15,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface ByteLengthQueuingStrategy
 [Worker]     method constructor
 [Worker]     method size
@@ -416,11 +418,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -757,6 +761,7 @@
 [Worker]     attribute console
 [Worker]     attribute internals
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method gc
 [Worker]     method postMessage
@@ -765,6 +770,7 @@
 [Worker]     method webkitResolveLocalFileSystemSyncURL
 [Worker]     method webkitResolveLocalFileSystemURL
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index da1ef84..ca5e440 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -15,10 +15,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface ByteLengthQueuingStrategy
 [Worker]     method constructor
 [Worker]     method size
@@ -411,11 +413,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/webauth/idl.html b/third_party/WebKit/LayoutTests/webauth/idl.html
index 730d8cf..8337882 100644
--- a/third_party/WebKit/LayoutTests/webauth/idl.html
+++ b/third_party/WebKit/LayoutTests/webauth/idl.html
@@ -69,7 +69,7 @@
 dictionary ScopedCredentialDescriptor {
     required ScopedCredentialType type;
     required BufferSource   id;
-    sequence < Transport >  transports;
+    sequence <Transport>  transports;
 };
 
 enum Transport {
@@ -79,14 +79,14 @@
 };
 [SecureContext]
 interface WebAuthentication {
-    Promise < ScopedCredentialInfo > makeCredential (
+    Promise <ScopedCredentialInfo> makeCredential (
         Account                                 accountInformation,
         sequence < ScopedCredentialParameters > cryptoParameters,
         BufferSource                            attestationChallenge,
         optional ScopedCredentialOptions        options
     );
 
-    Promise < AuthenticationAssertion > getAssertion (
+    Promise <AuthenticationAssertion> getAssertion (
         BufferSource               assertionChallenge,
         optional AssertionOptions  options
     );
diff --git a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
index fda4edc5..1b046b1 100644
--- a/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/element-instance-property-listing-expected.txt
@@ -374,6 +374,7 @@
     property onhashchange
     property onlanguagechange
     property onmessage
+    property onmessageerror
     property onoffline
     property ononline
     property onpagehide
@@ -520,6 +521,7 @@
     property onhashchange
     property onlanguagechange
     property onmessage
+    property onmessageerror
     property onoffline
     property ononline
     property onpagehide
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 9d7798e..8943850 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -39,10 +39,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface BudgetService
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -638,11 +640,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -2326,6 +2330,7 @@
 [Worker]     attribute console
 [Worker]     attribute internals
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method gc
 [Worker]     method postMessage
@@ -2334,6 +2339,7 @@
 [Worker]     method webkitResolveLocalFileSystemSyncURL
 [Worker]     method webkitResolveLocalFileSystemURL
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index fa4b409..4a94c3e 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -474,10 +474,12 @@
     attribute @@toStringTag
     getter name
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     setter onmessage
+    setter onmessageerror
 interface BudgetService
     attribute @@toStringTag
     method constructor
@@ -2148,6 +2150,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -2174,6 +2177,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -2591,6 +2595,7 @@
     getter onlanguagechange
     getter onload
     getter onmessage
+    getter onmessageerror
     getter onoffline
     getter ononline
     getter onpagehide
@@ -2613,6 +2618,7 @@
     setter onlanguagechange
     setter onload
     setter onmessage
+    setter onmessageerror
     setter onoffline
     setter ononline
     setter onpagehide
@@ -4191,11 +4197,13 @@
 interface MessagePort : EventTarget
     attribute @@toStringTag
     getter onmessage
+    getter onmessageerror
     method close
     method constructor
     method postMessage
     method start
     setter onmessage
+    setter onmessageerror
 interface MimeType
     attribute @@toStringTag
     getter description
@@ -8931,6 +8939,7 @@
     getter onloadstart
     getter onlostpointercapture
     getter onmessage
+    getter onmessageerror
     getter onmousedown
     getter onmouseenter
     getter onmouseleave
@@ -9111,6 +9120,7 @@
     setter onloadstart
     setter onlostpointercapture
     setter onmessage
+    setter onmessageerror
     setter onmousedown
     setter onmouseenter
     setter onmouseleave
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index 3561759..4adac7a 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -39,10 +39,12 @@
 [Worker]     attribute @@toStringTag
 [Worker]     getter name
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface BudgetService
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
@@ -633,11 +635,13 @@
 [Worker] interface MessagePort : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onmessage
+[Worker]     getter onmessageerror
 [Worker]     method close
 [Worker]     method constructor
 [Worker]     method postMessage
 [Worker]     method start
 [Worker]     setter onmessage
+[Worker]     setter onmessageerror
 [Worker] interface NavigationPreloadManager
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
diff --git a/third_party/WebKit/Source/bindings/OWNERS b/third_party/WebKit/Source/bindings/OWNERS
index 1d0c5475..0a934f9 100644
--- a/third_party/WebKit/Source/bindings/OWNERS
+++ b/third_party/WebKit/Source/bindings/OWNERS
@@ -1,5 +1,4 @@
 bashi@chromium.org
-esprehn@chromium.org
 haraken@chromium.org
 japhet@chromium.org
 jbroman@chromium.org
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
index c938a08..7c8de2b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -54,7 +54,6 @@
 #include "core/loader/ProgressTracker.h"
 #include "core/plugins/PluginView.h"
 #include "core/probe/CoreProbes.h"
-#include "platform/FrameViewBase.h"
 #include "platform/Histogram.h"
 #include "platform/UserGestureIndicator.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
diff --git a/third_party/WebKit/Source/core/OWNERS b/third_party/WebKit/Source/core/OWNERS
index 3190ca49..c783d7c55 100644
--- a/third_party/WebKit/Source/core/OWNERS
+++ b/third_party/WebKit/Source/core/OWNERS
@@ -21,7 +21,6 @@
 dstockwell@chromium.org
 eae@chromium.org
 enne@chromium.org
-esprehn@chromium.org
 fmalita@chromium.org
 # foolip reviews <video>, <track>, WebVTT and Fullscreen.
 foolip@chromium.org
diff --git a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
index 80f313b..81e6a82 100644
--- a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp
@@ -47,12 +47,13 @@
 }
 
 static bool SubimageKnownToBeOpaque(CSSValue* value,
-                                    const LayoutObject& layout_object) {
+                                    const Document& document,
+                                    const ComputedStyle& style) {
   if (value->IsImageValue())
-    return ToCSSImageValue(value)->KnownToBeOpaque(layout_object);
+    return ToCSSImageValue(value)->KnownToBeOpaque(document, style);
 
   if (value->IsImageGeneratorValue())
-    return ToCSSImageGeneratorValue(value)->KnownToBeOpaque(layout_object);
+    return ToCSSImageGeneratorValue(value)->KnownToBeOpaque(document, style);
 
   NOTREACHED();
 
@@ -188,10 +189,10 @@
          SubimageIsPending(to_value_.Get());
 }
 
-bool CSSCrossfadeValue::KnownToBeOpaque(
-    const LayoutObject& layout_object) const {
-  return SubimageKnownToBeOpaque(from_value_.Get(), layout_object) &&
-         SubimageKnownToBeOpaque(to_value_.Get(), layout_object);
+bool CSSCrossfadeValue::KnownToBeOpaque(const Document& document,
+                                        const ComputedStyle& style) const {
+  return SubimageKnownToBeOpaque(from_value_.Get(), document, style) &&
+         SubimageKnownToBeOpaque(to_value_.Get(), document, style);
 }
 
 void CSSCrossfadeValue::LoadSubimages(const Document& document) {
diff --git a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
index b160161..f91cb6f 100644
--- a/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
+++ b/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h
@@ -58,7 +58,7 @@
   IntSize FixedSize(const Document&, const FloatSize&);
 
   bool IsPending() const;
-  bool KnownToBeOpaque(const LayoutObject&) const;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
 
   void LoadSubimages(const Document&);
 
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
index b6ba8a5..6970d956 100644
--- a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
@@ -284,9 +284,15 @@
 }
 
 static Color ResolveStopColor(const CSSValue& stop_color,
-                              const LayoutObject& object) {
-  return object.GetDocument().GetTextLinkColors().ColorFromCSSValue(
-      stop_color, object.ResolveColor(CSSPropertyColor));
+                              const Document& document,
+                              const ComputedStyle& style) {
+  return document.GetTextLinkColors().ColorFromCSSValue(
+      stop_color, style.VisitedDependentColor(CSSPropertyColor));
+}
+
+static Color ResolveStopColor(const CSSValue& stop_color,
+                              const LayoutObject& obj) {
+  return ResolveStopColor(stop_color, obj.GetDocument(), obj.StyleRef());
 }
 
 void CSSGradientValue::AddDeprecatedStops(GradientDesc& desc,
@@ -788,9 +794,11 @@
   return result;
 }
 
-bool CSSGradientValue::KnownToBeOpaque(const LayoutObject& object) const {
+bool CSSGradientValue::KnownToBeOpaque(const Document& document,
+                                       const ComputedStyle& style) const {
   for (auto& stop : stops_) {
-    if (!stop.IsHint() && ResolveStopColor(*stop.color_, object).HasAlpha())
+    if (!stop.IsHint() &&
+        ResolveStopColor(*stop.color_, document, style).HasAlpha())
       return false;
   }
   return true;
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.h b/third_party/WebKit/Source/core/css/CSSGradientValue.h
index f902098..b3c26a80 100644
--- a/third_party/WebKit/Source/core/css/CSSGradientValue.h
+++ b/third_party/WebKit/Source/core/css/CSSGradientValue.h
@@ -104,7 +104,7 @@
   IntSize FixedSize(const Document&) const { return IntSize(); }
 
   bool IsPending() const { return false; }
-  bool KnownToBeOpaque(const LayoutObject&) const;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
 
   void LoadSubimages(const Document&) {}
 
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
index f39db4a..afdbf93a 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
@@ -189,19 +189,19 @@
   return false;
 }
 
-bool CSSImageGeneratorValue::KnownToBeOpaque(
-    const LayoutObject& layout_object) const {
+bool CSSImageGeneratorValue::KnownToBeOpaque(const Document& document,
+                                             const ComputedStyle& style) const {
   switch (GetClassType()) {
     case kCrossfadeClass:
-      return ToCSSCrossfadeValue(this)->KnownToBeOpaque(layout_object);
+      return ToCSSCrossfadeValue(this)->KnownToBeOpaque(document, style);
     case kLinearGradientClass:
-      return ToCSSLinearGradientValue(this)->KnownToBeOpaque(layout_object);
+      return ToCSSLinearGradientValue(this)->KnownToBeOpaque(document, style);
     case kPaintClass:
-      return ToCSSPaintValue(this)->KnownToBeOpaque(layout_object);
+      return ToCSSPaintValue(this)->KnownToBeOpaque(document, style);
     case kRadialGradientClass:
-      return ToCSSRadialGradientValue(this)->KnownToBeOpaque(layout_object);
+      return ToCSSRadialGradientValue(this)->KnownToBeOpaque(document, style);
     case kConicGradientClass:
-      return ToCSSConicGradientValue(this)->KnownToBeOpaque(layout_object);
+      return ToCSSConicGradientValue(this)->KnownToBeOpaque(document, style);
     default:
       NOTREACHED();
   }
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
index 6d79a69..0a2daa61 100644
--- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
+++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
@@ -39,6 +39,7 @@
 class Image;
 class LayoutObject;
 class FloatSize;
+class ComputedStyle;
 
 struct SizeAndCount {
   DISALLOW_NEW();
@@ -63,7 +64,7 @@
   IntSize FixedSize(const Document&, const FloatSize& default_object_size);
 
   bool IsPending() const;
-  bool KnownToBeOpaque(const LayoutObject&) const;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
 
   void LoadSubimages(const Document&);
 
diff --git a/third_party/WebKit/Source/core/css/CSSImageValue.cpp b/third_party/WebKit/Source/core/css/CSSImageValue.cpp
index 663173a7..fc34201f 100644
--- a/third_party/WebKit/Source/core/css/CSSImageValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSImageValue.cpp
@@ -116,8 +116,10 @@
   return SerializeURI(relative_url_);
 }
 
-bool CSSImageValue::KnownToBeOpaque(const LayoutObject& layout_object) const {
-  return cached_image_ ? cached_image_->KnownToBeOpaque(layout_object) : false;
+bool CSSImageValue::KnownToBeOpaque(const Document& document,
+                                    const ComputedStyle& style) const {
+  return cached_image_ ? cached_image_->KnownToBeOpaque(document, style)
+                       : false;
 }
 
 DEFINE_TRACE_AFTER_DISPATCH(CSSImageValue) {
diff --git a/third_party/WebKit/Source/core/css/CSSImageValue.h b/third_party/WebKit/Source/core/css/CSSImageValue.h
index ccca36ea..d088d685 100644
--- a/third_party/WebKit/Source/core/css/CSSImageValue.h
+++ b/third_party/WebKit/Source/core/css/CSSImageValue.h
@@ -32,7 +32,7 @@
 class Document;
 class KURL;
 class StyleImage;
-class LayoutObject;
+class ComputedStyle;
 
 class CORE_EXPORT CSSImageValue : public CSSValue {
  public:
@@ -77,7 +77,7 @@
 
   bool Equals(const CSSImageValue&) const;
 
-  bool KnownToBeOpaque(const LayoutObject&) const;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
 
   CSSImageValue* ValueWithURLMadeAbsolute() const {
     return Create(KURL(kParsedURLString, absolute_url_), cached_image_.Get());
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
index ca14302..3474876 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -100,7 +100,8 @@
   }
 }
 
-bool CSSPaintValue::KnownToBeOpaque(const LayoutObject& layout_object) const {
+bool CSSPaintValue::KnownToBeOpaque(const Document&,
+                                    const ComputedStyle&) const {
   return generator_ && !generator_->HasAlpha();
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.h b/third_party/WebKit/Source/core/css/CSSPaintValue.h
index 26fc5cd..b693cb7 100644
--- a/third_party/WebKit/Source/core/css/CSSPaintValue.h
+++ b/third_party/WebKit/Source/core/css/CSSPaintValue.h
@@ -36,7 +36,7 @@
   IntSize FixedSize(const Document&) { return IntSize(); }
 
   bool IsPending() const { return true; }
-  bool KnownToBeOpaque(const LayoutObject&) const;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const;
 
   void LoadSubimages(const Document&) {}
 
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 0276381..0f79aedd8 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -699,6 +699,7 @@
   bool CanCreateHistoryEntry() const;
 
   TextLinkColors& GetTextLinkColors() { return text_link_colors_; }
+  const TextLinkColors& GetTextLinkColors() const { return text_link_colors_; }
   VisitedLinkState& GetVisitedLinkState() const { return *visited_link_state_; }
 
   MouseEventWithHitTestResults PerformMouseEventHitTest(const HitTestRequest&,
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.h b/third_party/WebKit/Source/core/dom/MessagePort.h
index a18f354..7f2d1bc8 100644
--- a/third_party/WebKit/Source/core/dom/MessagePort.h
+++ b/third_party/WebKit/Source/core/dom/MessagePort.h
@@ -114,6 +114,14 @@
     return GetAttributeEventListener(EventTypeNames::message);
   }
 
+  void setOnmessageerror(EventListener* listener) {
+    SetAttributeEventListener(EventTypeNames::messageerror, listener);
+    start();
+  }
+  EventListener* onmessageerror() {
+    return GetAttributeEventListener(EventTypeNames::messageerror);
+  }
+
   // A port starts out its life entangled, and remains entangled until it is
   // closed or is cloned.
   bool IsEntangled() const { return !closed_ && !IsNeutered(); }
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.idl b/third_party/WebKit/Source/core/dom/MessagePort.idl
index 7b0b537c..d031b7b 100644
--- a/third_party/WebKit/Source/core/dom/MessagePort.idl
+++ b/third_party/WebKit/Source/core/dom/MessagePort.idl
@@ -38,4 +38,5 @@
 
     // event handlers
     attribute EventHandler onmessage;
+    attribute EventHandler onmessageerror;
 };
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 3ca2f29e..198e1967 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -569,37 +569,6 @@
     return true;
   }
 
-  // 5th Clause:
-  // TODO(hiroshige): Reorder the clauses to match the spec.
-  // - "If the element does not have a src attribute,
-  //    and the element has been flagged as "parser-inserted",
-  //    and either the parser that created the script is an XML parser
-  //      or it's an HTML parser whose script nesting level is not greater than
-  //      one,
-  //    and the Document of the HTML parser or XML parser that created
-  //      the script element has a style sheet that is blocking scripts"
-  // The last part "... has a style sheet that is blocking scripts"
-  // is implemented in Document::isScriptExecutionReady().
-  // Part of the condition check is done in
-  // HTMLParserScriptRunner::processScriptElementInternal().
-  // TODO(hiroshige): Clean up the split condition check.
-  // We check that the type is "classic" here, because according to the spec
-  // a "module" script doesn't reach the 5th Clause because the 4th Clause
-  // catches all "module" scripts.
-  if (GetScriptType() == ScriptType::kClassic &&
-      !element_->HasSourceAttribute() && parser_inserted_ &&
-      !element_document.IsScriptExecutionReady()) {
-    // The former part of this clause is
-    // implemented by the caller-side of prepareScript():
-    // - HTMLParserScriptRunner::requestParsingBlockingScript()
-    // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
-    will_be_parser_executed_ = true;
-    // "Set the element's "ready to be parser-executed" flag."
-    ready_to_be_parser_executed_ = true;
-
-    return true;
-  }
-
   // 3rd Clause:
   // - "If the script's type is "classic",
   //    and the element has a src attribute,
@@ -608,7 +577,6 @@
   // - "If the script's type is "module",
   //    and the element does not have an async attribute,
   //    and the element does not have the "non-blocking" flag set"
-  // TODO(hiroshige): Check the script's type and implement "module" case.
   if ((GetScriptType() == ScriptType::kClassic &&
        element_->HasSourceAttribute() && !element_->AsyncAttributeValue() &&
        !non_blocking_) ||
@@ -658,6 +626,37 @@
     return true;
   }
 
+  // The following clauses are executed only if the script's type is "classic"
+  // and the element doesn't have a src attribute.
+  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
+  DCHECK(!is_external_script_);
+
+  // 5th Clause:
+  // - "If the element does not have a src attribute,
+  //    and the element has been flagged as "parser-inserted",
+  //    and either the parser that created the script is an XML parser
+  //      or it's an HTML parser whose script nesting level is not greater than
+  //      one,
+  //    and the Document of the HTML parser or XML parser that created
+  //      the script element has a style sheet that is blocking scripts"
+  // The last part "... has a style sheet that is blocking scripts"
+  // is implemented in Document::isScriptExecutionReady().
+  // Part of the condition check is done in
+  // HTMLParserScriptRunner::processScriptElementInternal().
+  // TODO(hiroshige): Clean up the split condition check.
+  if (!element_->HasSourceAttribute() && parser_inserted_ &&
+      !element_document.IsScriptExecutionReady()) {
+    // The former part of this clause is
+    // implemented by the caller-side of prepareScript():
+    // - HTMLParserScriptRunner::requestParsingBlockingScript()
+    // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
+    will_be_parser_executed_ = true;
+    // "Set the element's "ready to be parser-executed" flag."
+    ready_to_be_parser_executed_ = true;
+
+    return true;
+  }
+
   // 6th Clause:
   // - "Otherwise"
   // "Immediately execute the script block,
@@ -666,11 +665,6 @@
   // HTMLParserScriptRunner::processScriptElementInternal().
   // TODO(hiroshige): Merge the duplicated code.
 
-  // This clause is executed only if the script's type is "classic"
-  // and the element doesn't have a src attribute.
-  DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
-  DCHECK(!is_external_script_);
-
   // Reset line numbering for nested writes.
   TextPosition position = element_document.IsInDocumentWrite()
                               ? TextPosition()
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index b83875b..f6a31f6 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -720,7 +720,6 @@
   SetSelection(SelectionInDOMTree::Builder()
                    .SetBaseAndExtent(range)
                    .SetAffinity(affinity)
-                   .SetIsHandleVisible(IsHandleVisible())
                    .SetIsDirectional(directional ==
                                      SelectionDirectionalMode::kDirectional)
                    .Build(),
@@ -976,7 +975,7 @@
   // selection is.
   Node* start = GetDocument().FocusedElement();
   if (!start)
-    start = ComputeVisibleSelectionInDOMTreeDeprecated().Start().AnchorNode();
+    start = ComputeVisibleSelectionInDOMTree().Start().AnchorNode();
   if (!start)
     return 0;
 
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index d927d3b..76d0f6d8 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -296,7 +296,7 @@
          "after it.";
 }
 
-TEST_F(FrameSelectionTest, SetSelectedRangePreservesHandle) {
+TEST_F(FrameSelectionTest, SetSelectedRangeHidesHandle) {
   Text* text = AppendTextNode("Hello, World!");
   GetDocument().View()->UpdateAllLifecyclePhases();
   Selection().SetSelection(
@@ -310,9 +310,7 @@
       VP_DEFAULT_AFFINITY, SelectionDirectionalMode::kNonDirectional, 0);
 
   EXPECT_FALSE(Selection().IsHandleVisible())
-      << "If handles weren't present before"
-         "setSelectedRange they shouldn't be present"
-         "after it.";
+      << "After SetSelectedRange handles shouldn't be present.";
 
   Selection().SetSelection(
       SelectionInDOMTree::Builder()
@@ -324,9 +322,8 @@
       EphemeralRange(Position(text, 0), Position(text, 12)),
       VP_DEFAULT_AFFINITY, SelectionDirectionalMode::kNonDirectional, 0);
 
-  EXPECT_TRUE(Selection().IsHandleVisible())
-      << "If handles were present before"
-         "selectSetSelectedRange they should be present after it.";
+  EXPECT_FALSE(Selection().IsHandleVisible())
+      << "After SetSelectedRange handles shouldn't be present.";
 }
 
 // Regression test for crbug.com/702756
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
index e6f33b17..1c82ee9 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
@@ -34,6 +34,7 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
 #include "core/html/TextControlElement.h"
+#include "platform/Histogram.h"
 #include "platform/text/TextCheckerClient.h"
 
 namespace blink {
@@ -125,6 +126,7 @@
     : frame_(&frame),
       last_request_sequence_(0),
       last_processed_sequence_(0),
+      last_request_time_(0.0),
       timer_to_process_queued_request_(
           TaskRunnerHelper::Get(TaskType::kUnspecedTimer, &frame),
           this,
@@ -154,6 +156,17 @@
   if (!request)
     return;
 
+  DEFINE_STATIC_LOCAL(CustomCountHistogram,
+                      spell_checker_request_interval_histogram,
+                      ("WebCore.SpellChecker.RequestInterval", 0, 10000, 50));
+  const double current_request_time = MonotonicallyIncreasingTime();
+  if (request_num == 0 && last_request_time_ > 0) {
+    const double interval_ms =
+        (current_request_time - last_request_time_) * 1000.0;
+    spell_checker_request_interval_histogram.Count(interval_ms);
+  }
+  last_request_time_ = current_request_time;
+
   DCHECK_EQ(request->Data().Sequence(), kUnrequestedTextCheckingSequence);
   int sequence = ++last_request_sequence_;
   if (sequence == kUnrequestedTextCheckingSequence)
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
index 77e332bd..fbe2926 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.h
@@ -123,6 +123,7 @@
 
   int last_request_sequence_;
   int last_processed_sequence_;
+  double last_request_time_;
 
   TaskRunnerTimer<SpellCheckRequester> timer_to_process_queued_request_;
 
diff --git a/third_party/WebKit/Source/core/events/EventTypeNames.json5 b/third_party/WebKit/Source/core/events/EventTypeNames.json5
index 3728b26..f9a2d98c 100644
--- a/third_party/WebKit/Source/core/events/EventTypeNames.json5
+++ b/third_party/WebKit/Source/core/events/EventTypeNames.json5
@@ -148,6 +148,7 @@
     "lostpointercapture",
     "mark",
     "message",
+    "messageerror",
     "midimessage",
     "mousedown",
     "mouseenter",
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
index 2bbb865..0e96f0fb 100644
--- a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
+++ b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
@@ -17,20 +17,20 @@
 
 const char* PointerTypeNameForWebPointPointerType(
     WebPointerProperties::PointerType type) {
+  // TODO(mustaq): Fix when the spec starts supporting hovering erasers.
   switch (type) {
     case WebPointerProperties::PointerType::kUnknown:
       return "";
     case WebPointerProperties::PointerType::kTouch:
       return "touch";
     case WebPointerProperties::PointerType::kPen:
-    case WebPointerProperties::PointerType::kEraser:
-      // TODO(mustaq): Fix when the spec starts supporting hovering erasers.
       return "pen";
     case WebPointerProperties::PointerType::kMouse:
       return "mouse";
+    default:
+      NOTREACHED();
+      return "";
   }
-  NOTREACHED();
-  return "";
 }
 
 const AtomicString& PointerEventNameForMouseEventName(
@@ -188,21 +188,22 @@
     PointerEventInit& pointer_event_init,
     const WebPointerProperties& pointer_properties,
     unsigned buttons) {
-  const WebPointerProperties::PointerType pointer_type =
+  WebPointerProperties::PointerType pointer_type =
       pointer_properties.pointer_type;
-  const IncomingId incoming_id(pointer_type, pointer_properties.id);
-  int pointer_id = AddIdAndActiveButtons(incoming_id, buttons != 0);
-
   // Tweak the |buttons| to reflect pen eraser mode only if the pen is in
   // active buttons state w/o even considering the eraser button.
   // TODO(mustaq): Fix when the spec starts supporting hovering erasers.
-  if (pointer_type == WebPointerProperties::PointerType::kEraser &&
-      buttons != 0) {
-    buttons |= static_cast<unsigned>(WebPointerProperties::Buttons::kEraser);
-    buttons &= ~static_cast<unsigned>(WebPointerProperties::Buttons::kLeft);
+  if (pointer_type == WebPointerProperties::PointerType::kEraser) {
+    if (buttons != 0) {
+      buttons |= static_cast<unsigned>(WebPointerProperties::Buttons::kEraser);
+      buttons &= ~static_cast<unsigned>(WebPointerProperties::Buttons::kLeft);
+    }
+    pointer_type = WebPointerProperties::PointerType::kPen;
   }
   pointer_event_init.setButtons(buttons);
 
+  const IncomingId incoming_id(pointer_type, pointer_properties.id);
+  int pointer_id = AddIdAndActiveButtons(incoming_id, buttons != 0);
   pointer_event_init.setPointerId(pointer_id);
   pointer_event_init.setPointerType(
       PointerTypeNameForWebPointPointerType(pointer_type));
@@ -515,6 +516,8 @@
   return true;
 }
 
+// This function does not work with pointer type of eraser, because we save
+// them as pen type in the pointer id map.
 Vector<int> PointerEventFactory::GetPointerIdsOfType(
     WebPointerProperties::PointerType pointer_type) const {
   Vector<int> mapped_ids;
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp b/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp
index 8d705c7..2f110f1 100644
--- a/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp
+++ b/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp
@@ -22,13 +22,13 @@
     case WebPointerProperties::PointerType::kTouch:
       return "touch";
     case WebPointerProperties::PointerType::kPen:
-    case WebPointerProperties::PointerType::kEraser:
       return "pen";
     case WebPointerProperties::PointerType::kMouse:
       return "mouse";
+    default:
+      NOTREACHED();
+      return "";
   }
-  NOTREACHED();
-  return "";
 }
 }
 
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h b/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h
index 2b5eac7..d9f1800 100644
--- a/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h
+++ b/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h
@@ -39,6 +39,7 @@
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(hashchange);
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(languagechange);
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(message);
+DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(messageerror);
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(offline);
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(online);
 DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(pagehide);
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp
index 92fc41d..2ff34de 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -419,8 +419,6 @@
 
   if (has_scrollbar) {
     h_bar_ = CreateScrollbar(kHorizontalScrollbar);
-    scrollable_area_->GetLayoutBox()->GetDocument().View()->AddScrollbar(
-        h_bar_);
     h_bar_is_attached_ = 1;
     scrollable_area_->DidAddScrollbar(*h_bar_, kHorizontalScrollbar);
     h_bar_->StyleChanged();
@@ -438,8 +436,6 @@
 
   if (has_scrollbar) {
     v_bar_ = CreateScrollbar(kVerticalScrollbar);
-    scrollable_area_->GetLayoutBox()->GetDocument().View()->AddScrollbar(
-        v_bar_);
     v_bar_is_attached_ = 1;
     scrollable_area_->DidAddScrollbar(*v_bar_, kVerticalScrollbar);
     v_bar_->StyleChanged();
@@ -477,8 +473,6 @@
     return;
 
   scrollable_area_->WillRemoveScrollbar(*scrollbar, orientation);
-  scrollable_area_->GetLayoutBox()->GetDocument().View()->RemoveScrollbar(
-      scrollbar);
   scrollbar->DisconnectFromScrollableArea();
   scrollbar = nullptr;
 }
@@ -3651,7 +3645,7 @@
                                        const IntPoint& point) const {
   IntPoint new_point = point;
   new_point = FrameToContents(point);
-  new_point.MoveBy(child.FrameRect().Location());
+  new_point.MoveBy(-child.FrameRect().Location());
   return new_point;
 }
 
@@ -3884,13 +3878,11 @@
 
 void FrameView::RemoveScrollbar(Scrollbar* scrollbar) {
   DCHECK(scrollbars_.Contains(scrollbar));
-  scrollbar->SetParent(nullptr);
   scrollbars_.erase(scrollbar);
 }
 
 void FrameView::AddScrollbar(Scrollbar* scrollbar) {
   DCHECK(!scrollbars_.Contains(scrollbar));
-  scrollbar->SetParent(this);
   scrollbars_.insert(scrollbar);
 }
 
@@ -4743,6 +4735,46 @@
   return local_point;
 }
 
+IntRect FrameView::ConvertFromRootFrame(
+    const IntRect& rect_in_root_frame) const {
+  if (parent_) {
+    IntRect parent_rect = parent_->ConvertFromRootFrame(rect_in_root_frame);
+    return ConvertFromContainingFrameViewBase(parent_rect);
+  }
+  return rect_in_root_frame;
+}
+
+IntPoint FrameView::ConvertFromRootFrame(
+    const IntPoint& point_in_root_frame) const {
+  if (parent_) {
+    IntPoint parent_point = parent_->ConvertFromRootFrame(point_in_root_frame);
+    return ConvertFromContainingFrameViewBase(parent_point);
+  }
+  return point_in_root_frame;
+}
+
+FloatPoint FrameView::ConvertFromRootFrame(
+    const FloatPoint& point_in_root_frame) const {
+  // FrameViews / windows are required to be IntPoint aligned, but we may
+  // need to convert FloatPoint values within them (eg. for event
+  // co-ordinates).
+  IntPoint floored_point = FlooredIntPoint(point_in_root_frame);
+  FloatPoint parent_point = ConvertFromRootFrame(floored_point);
+  FloatSize window_fraction = point_in_root_frame - floored_point;
+  // Use linear interpolation handle any fractional value (eg. for iframes
+  // subject to a transform beyond just a simple translation).
+  // FIXME: Add FloatPoint variants of all co-ordinate space conversion APIs.
+  if (!window_fraction.IsEmpty()) {
+    const int kFactor = 1000;
+    IntPoint parent_line_end = ConvertFromRootFrame(
+        floored_point + RoundedIntSize(window_fraction.ScaledBy(kFactor)));
+    FloatSize parent_fraction =
+        (parent_line_end - parent_point).ScaledBy(1.0f / kFactor);
+    parent_point.Move(parent_fraction);
+  }
+  return parent_point;
+}
+
 IntPoint FrameView::ConvertFromContainingFrameViewBaseToScrollbar(
     const Scrollbar& scrollbar,
     const IntPoint& parent_point) const {
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index bf4e3dcf..826d0875 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -40,7 +40,6 @@
 #include "core/paint/PaintInvalidationCapableScrollableArea.h"
 #include "core/paint/PaintPhase.h"
 #include "core/paint/ScrollbarManager.h"
-#include "platform/FrameViewBase.h"
 #include "platform/PlatformFrameView.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/animation/CompositorAnimationHost.h"
@@ -104,7 +103,6 @@
 class CORE_EXPORT FrameView final
     : public GarbageCollectedFinalized<FrameView>,
       public PlatformFrameView,
-      public FrameViewBase,
       public FrameOrPlugin,
       public PaintInvalidationCapableScrollableArea {
   USING_GARBAGE_COLLECTED_MIXIN(FrameView);
@@ -128,7 +126,7 @@
   int Width() const { return frame_rect_.Width(); }
   int Height() const { return frame_rect_.Height(); }
   IntSize Size() const { return frame_rect_.Size(); }
-  IntPoint Location() const override { return frame_rect_.Location(); }
+  IntPoint Location() const { return frame_rect_.Location(); }
   void Resize(int width, int height) {
     SetFrameRect(IntRect(frame_rect_.X(), frame_rect_.Y(), width, height));
   }
@@ -481,9 +479,6 @@
   // and repaints to the host window in the window's coordinate space.
   PlatformChromeClient* GetChromeClient() const;
 
-  typedef HeapHashSet<Member<FrameOrPlugin>> ChildrenSet;
-  typedef HeapHashSet<Member<Scrollbar>> ScrollbarsSet;
-
   // Functions for child manipulation and inspection.
   bool IsSelfVisible() const {
     return self_visible_;
@@ -500,10 +495,12 @@
   FrameView* Parent() const override { return parent_; }
   void RemoveChild(FrameOrPlugin*);
   void AddChild(FrameOrPlugin*);
+  using ChildrenSet = HeapHashSet<Member<FrameOrPlugin>>;
   const ChildrenSet& Children() const { return children_; }
+  // Custom scrollbars in PaintLayerScrollableArea need to be called with
+  // StyleChanged whenever window focus is changed.
   void RemoveScrollbar(Scrollbar*);
   void AddScrollbar(Scrollbar*);
-  const ScrollbarsSet* Scrollbars() const { return &scrollbars_; }
 
   // If the scroll view does not use a native widget, then it will have
   // cross-platform Scrollbars. These functions can be used to obtain those
@@ -650,6 +647,9 @@
 
   IntRect ConvertToRootFrame(const IntRect&) const;
   IntPoint ConvertToRootFrame(const IntPoint&) const;
+  IntRect ConvertFromRootFrame(const IntRect&) const;
+  IntPoint ConvertFromRootFrame(const IntPoint&) const override;
+  FloatPoint ConvertFromRootFrame(const FloatPoint&) const;
   IntPoint ConvertSelfToChild(const FrameOrPlugin&, const IntPoint&) const;
 
   // Handles painting of the contents of the view as well as the scrollbars.
@@ -1145,7 +1145,7 @@
   bool vertical_scrollbar_lock_;
 
   ChildrenSet children_;
-  ScrollbarsSet scrollbars_;
+  HeapHashSet<Member<Scrollbar>> scrollbars_;
 
   ScrollOffset pending_scroll_delta_;
   ScrollOffset scroll_offset_;
@@ -1268,11 +1268,6 @@
                   platform_frame_view->IsFrameView(),
                   platform_frame_view.IsFrameView());
 DEFINE_TYPE_CASTS(FrameView,
-                  FrameViewBase,
-                  frameViewBase,
-                  frameViewBase->IsFrameView(),
-                  frameViewBase.IsFrameView());
-DEFINE_TYPE_CASTS(FrameView,
                   FrameOrPlugin,
                   frame_or_plugin,
                   frame_or_plugin->IsFrameView(),
diff --git a/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl b/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl
index 6374803..0b09a583 100644
--- a/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl
+++ b/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl
@@ -41,6 +41,7 @@
     attribute EventHandler onhashchange;
     attribute EventHandler onlanguagechange;
     attribute EventHandler onmessage;
+    attribute EventHandler onmessageerror;
     attribute EventHandler onoffline;
     attribute EventHandler ononline;
     attribute EventHandler onpagehide;
diff --git a/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5 b/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5
index 4fccbc9..99c9455 100644
--- a/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5
+++ b/third_party/WebKit/Source/core/html/HTMLAttributeNames.json5
@@ -232,6 +232,7 @@
     "onloadstart",
     "onlostpointercapture",
     "onmessage",
+    "onmessageerror",
     "onmousedown",
     "onmouseenter",
     "onmouseleave",
diff --git a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp
index 265cd0b..b02a4d67 100644
--- a/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLBodyElement.cpp
@@ -176,6 +176,11 @@
         EventTypeNames::message,
         CreateAttributeEventListener(GetDocument().GetFrame(), name, value,
                                      EventParameterName()));
+  } else if (name == onmessageerrorAttr) {
+    GetDocument().SetWindowAttributeEventListener(
+        EventTypeNames::messageerror,
+        CreateAttributeEventListener(GetDocument().GetFrame(), name, value,
+                                     EventParameterName()));
   } else if (name == onresizeAttr) {
     GetDocument().SetWindowAttributeEventListener(
         EventTypeNames::resize,
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
index 4cdbe2a0e..6af98e2 100644
--- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -41,7 +41,6 @@
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "core/layout/api/LayoutEmbeddedItem.h"
 #include "core/plugins/PluginView.h"
-#include "platform/FrameViewBase.h"
 #include "platform/network/mime/MIMETypeRegistry.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
index 074d979..73554bd 100644
--- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -46,7 +46,6 @@
 #include "core/page/Page.h"
 #include "core/page/scrolling/ScrollingCoordinator.h"
 #include "core/plugins/PluginView.h"
-#include "platform/FrameViewBase.h"
 #include "platform/Histogram.h"
 #include "platform/bindings/V8PerIsolateData.h"
 #include "platform/loader/fetch/ResourceRequest.h"
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index 8602639..e1fea63 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -183,8 +183,9 @@
       colors.push_back(existing_color.Blend(stop_color));
     }
   }
-  found_opaque_color =
-      found_opaque_color || gradient->KnownToBeOpaque(layout_object);
+  found_opaque_color = found_opaque_color ||
+                       gradient->KnownToBeOpaque(layout_object.GetDocument(),
+                                                 layout_object.StyleRef());
 }
 
 // Gets the colors from an image style, if one exists and it is a gradient.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 5ac9de0d..13d0b9d0 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -882,7 +882,7 @@
         if (const StyleImage* image = cur->GetImage()) {
           if ((cur->RepeatX() == kRepeatFill || cur->RepeatX() == kRoundFill) &&
               (cur->RepeatY() == kRepeatFill || cur->RepeatY() == kRoundFill) &&
-              image->KnownToBeOpaque(*this)) {
+              image->KnownToBeOpaque(GetDocument(), StyleRef())) {
             layer_known_opaque = true;
           }
         }
@@ -1883,9 +1883,8 @@
   LayoutRect clip_rect = BorderBoxRect();
   clip_rect.SetLocation(location + clip_rect.Location() +
                         LayoutSize(BorderLeft(), BorderTop()));
-  clip_rect.SetSize(
-      clip_rect.Size() -
-      LayoutSize(BorderLeft() + BorderRight(), BorderTop() + BorderBottom()));
+  clip_rect.SetSize(clip_rect.Size() -
+                    LayoutSize(BorderWidth(), BorderHeight()));
 
   if (HasOverflowClip())
     ExcludeScrollbars(clip_rect, overlay_scrollbar_clip_behavior);
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp b/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
index 594eab01..e956249 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbar.cpp
@@ -99,12 +99,9 @@
              : 0;
 }
 
-void LayoutScrollbar::SetParent(FrameViewBase* parent) {
-  Scrollbar::SetParent(parent);
-  if (!parent) {
-    // Destroy all of the scrollbar's LayoutBoxes.
-    UpdateScrollbarParts(true);
-  }
+void LayoutScrollbar::DisconnectFromScrollableArea() {
+  UpdateScrollbarParts(true);
+  Scrollbar::DisconnectFromScrollableArea();
 }
 
 void LayoutScrollbar::SetEnabled(bool e) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutScrollbar.h b/third_party/WebKit/Source/core/layout/LayoutScrollbar.h
index ca62b589..05f8dec 100644
--- a/third_party/WebKit/Source/core/layout/LayoutScrollbar.h
+++ b/third_party/WebKit/Source/core/layout/LayoutScrollbar.h
@@ -77,8 +77,8 @@
  private:
   friend class Scrollbar;
 
-  void SetParent(FrameViewBase*) override;
   void SetEnabled(bool) override;
+  void DisconnectFromScrollableArea() override;
 
   void SetHoveredPart(ScrollbarPart) override;
   void SetPressedPart(ScrollbarPart) override;
diff --git a/third_party/WebKit/Source/core/layout/OWNERS b/third_party/WebKit/Source/core/layout/OWNERS
index 1f58560..b1a1a0e 100644
--- a/third_party/WebKit/Source/core/layout/OWNERS
+++ b/third_party/WebKit/Source/core/layout/OWNERS
@@ -1,7 +1,6 @@
 cbiesinger@chromium.org
 chrishtr@chromium.org
 eae@chromium.org
-esprehn@chromium.org
 fmalita@chromium.org
 fs@opera.com
 mstensho@opera.com
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.cpp b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
index d7a2fff..ec637fc 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.cpp
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.cpp
@@ -36,7 +36,6 @@
 #include "core/html/forms/DateTimeChooser.h"
 #include "core/loader/DocumentLoader.h"
 #include "platform/FileChooser.h"
-#include "platform/FrameViewBase.h"
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebApplicationCacheHost.h"
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.cpp b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
index 5421719..b0fc819 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.cpp
@@ -425,12 +425,21 @@
   if (!failed_load_url_.IsEmpty() && image_source_url == failed_load_url_)
     return;
 
+  if (loading_image_document_ && update_behavior == kUpdateForcedReload) {
+    // Prepares for reloading ImageDocument.
+    // We turn the ImageLoader into non-ImageDocument here, and proceed to
+    // reloading just like an ordinary <img> element below.
+    loading_image_document_ = false;
+    image_resource_for_image_document_ = nullptr;
+    ClearImage();
+  }
+
   // Prevent the creation of a ResourceLoader (and therefore a network request)
   // for ImageDocument loads. In this case, the image contents have already been
   // requested as a main resource and ImageDocumentParser will take care of
   // funneling the main resource bytes into image_, so just create an
   // ImageResource to be populated later.
-  if (loading_image_document_ && update_behavior != kUpdateForcedReload) {
+  if (loading_image_document_) {
     ImageResource* image_resource = ImageResource::Create(
         ResourceRequest(ImageSourceToKURL(element_->ImageSourceURL())));
     image_resource->SetStatus(ResourceStatus::kPending);
@@ -510,6 +519,16 @@
   DCHECK(failed_load_url_.IsEmpty());
   DCHECK_EQ(resource, image_.Get());
 
+  // |has_pending_load_event_| is always false and |image_complete_| is
+  // always true for entire ImageDocument loading for historical reason.
+  // DoUpdateFromElement() is not called and SetImageForImageDocument()
+  // is called instead for ImageDocument loading.
+  // TODO(hiroshige): Turn the CHECK()s to DCHECK()s before going to beta.
+  if (loading_image_document_)
+    CHECK(image_complete_);
+  else
+    CHECK(!image_complete_);
+
   image_complete_ = true;
 
   // Update ImageAnimationPolicy for image_.
@@ -522,8 +541,12 @@
     ToSVGImage(image_->GetImage())
         ->UpdateUseCounters(GetElement()->GetDocument());
 
-  if (!has_pending_load_event_)
+  if (loading_image_document_) {
+    CHECK(!has_pending_load_event_);
     return;
+  }
+
+  CHECK(has_pending_load_event_);
 
   if (resource->ErrorOccurred()) {
     LoadEventSender().CancelEvent(this);
@@ -623,10 +646,10 @@
 }
 
 void ImageLoader::DispatchPendingLoadEvent() {
-  if (!has_pending_load_event_)
-    return;
+  CHECK(has_pending_load_event_);
   if (!image_)
     return;
+  CHECK(image_complete_);
   has_pending_load_event_ = false;
   if (GetElement()->GetDocument().GetFrame())
     DispatchLoadEvent();
@@ -638,8 +661,7 @@
 }
 
 void ImageLoader::DispatchPendingErrorEvent() {
-  if (!has_pending_error_event_)
-    return;
+  CHECK(has_pending_error_event_);
   has_pending_error_event_ = false;
 
   if (GetElement()->GetDocument().GetFrame())
diff --git a/third_party/WebKit/Source/core/loader/ImageLoader.h b/third_party/WebKit/Source/core/loader/ImageLoader.h
index eb5c656..8e4f753 100644
--- a/third_party/WebKit/Source/core/loader/ImageLoader.h
+++ b/third_party/WebKit/Source/core/loader/ImageLoader.h
@@ -86,9 +86,6 @@
   bool ImageComplete() const { return image_complete_ && !pending_task_; }
 
   ImageResourceContent* GetImage() const { return image_.Get(); }
-  ImageResource* ImageResourceForImageDocument() const {
-    return image_resource_for_image_document_;
-  }
 
   // Cancels pending load events, and doesn't dispatch new ones.
   // Note: ClearImage/SetImage.*() are not a simple setter.
@@ -97,8 +94,21 @@
   void ClearImage();
   void SetImageForTest(ImageResourceContent*);
 
+  // Image document loading:
+  // When |loading_image_document_| is true:
+  //   Loading via ImageDocument.
+  //   |image_resource_for_image_document_| points to a ImageResource that is
+  //   not associated with a ResourceLoader.
+  //   The corresponding ImageDocument is responsible for supplying the response
+  //   and data to |image_resource_for_image_document_| and thus |image_|.
+  // Otherwise:
+  //   Normal loading via ResourceFetcher/ResourceLoader.
+  //   |image_resource_for_image_document_| is null.
   bool IsLoadingImageDocument() { return loading_image_document_; }
   void SetLoadingImageDocument() { loading_image_document_ = true; }
+  ImageResource* ImageResourceForImageDocument() const {
+    return image_resource_for_image_document_;
+  }
 
   bool HasPendingActivity() const {
     return has_pending_load_event_ || has_pending_error_event_ || pending_task_;
diff --git a/third_party/WebKit/Source/core/paint/BoxDecorationData.cpp b/third_party/WebKit/Source/core/paint/BoxDecorationData.cpp
index ad16460..92b3573 100644
--- a/third_party/WebKit/Source/core/paint/BoxDecorationData.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxDecorationData.cpp
@@ -64,7 +64,8 @@
       // underneath.
       const FillLayer& fill_layer = layout_box.Style()->BackgroundLayers();
       if ((background_color.Alpha() || fill_layer.Next()) &&
-          !fill_layer.ImageOccludesNextLayers(layout_box))
+          !fill_layer.ImageOccludesNextLayers(layout_box.GetDocument(),
+                                              box_style))
         return kBackgroundBleedClipLayer;
     }
     return kBackgroundBleedNone;
diff --git a/third_party/WebKit/Source/core/paint/BoxPainter.cpp b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
index 06016f14..9937ba0 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
@@ -236,7 +236,8 @@
     // TODO(trchen): A fill layer cannot paint if the calculated tile size is
     // empty.  This occlusion check can be wrong.
     if (current_layer->ClipOccludesNextLayers() &&
-        current_layer->ImageOccludesNextLayers(layout_box_)) {
+        current_layer->ImageOccludesNextLayers(layout_box_.GetDocument(),
+                                               layout_box_.StyleRef())) {
       if (current_layer->Clip() == kBorderFillBox)
         is_non_associative = false;
       break;
@@ -346,7 +347,9 @@
 struct FillLayerInfo {
   STACK_ALLOCATED();
 
-  FillLayerInfo(const LayoutBoxModelObject& obj,
+  FillLayerInfo(const Document& doc,
+                const ComputedStyle& style,
+                bool has_overflow_clip,
                 Color bg_color,
                 const FillLayer& layer,
                 BackgroundBleedAvoidance bleed_avoidance,
@@ -357,7 +360,7 @@
         include_right_edge(box ? box->IncludeLogicalRightEdge() : true),
         is_bottom_layer(!layer.Next()),
         is_border_fill(layer.Clip() == kBorderFillBox),
-        is_clipped_with_local_scrolling(obj.HasOverflowClip() &&
+        is_clipped_with_local_scrolling(has_overflow_clip &&
                                         layer.Attachment() ==
                                             kLocalBackgroundAttachment) {
     // When printing backgrounds is disabled or using economy mode,
@@ -368,8 +371,7 @@
     // we've already loaded the background images anyway. (To avoid loading the
     // background images we'd have to do this check when applying styles rather
     // than while layout.)
-    if (BoxPainter::ShouldForceWhiteBackgroundForPrintEconomy(
-            obj.StyleRef(), obj.GetDocument())) {
+    if (BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(doc, style)) {
       // Note that we can't reuse this variable below because the bgColor might
       // be changed.
       bool should_paint_background_color = is_bottom_layer && color.Alpha();
@@ -379,8 +381,8 @@
       }
     }
 
-    const bool has_rounded_border = obj.Style()->HasBorderRadius() &&
-                                    (include_left_edge || include_right_edge);
+    const bool has_rounded_border =
+        style.HasBorderRadius() && (include_left_edge || include_right_edge);
     // BorderFillBox radius clipping is taken care of by
     // BackgroundBleedClip{Only,Layer}
     is_rounded_fill =
@@ -390,7 +392,7 @@
     should_paint_image = image && image->CanRender();
     should_paint_color =
         is_bottom_layer && color.Alpha() &&
-        (!should_paint_image || !layer.ImageOccludesNextLayers(obj));
+        (!should_paint_image || !layer.ImageOccludesNextLayers(doc, style));
   }
 
   // FillLayerInfo is a temporary, stack-allocated container which cannot
@@ -578,7 +580,9 @@
   if (rect.IsEmpty())
     return;
 
-  const FillLayerInfo info(obj, color, bg_layer, bleed_avoidance, box);
+  const FillLayerInfo info(obj.GetDocument(), obj.StyleRef(),
+                           obj.HasOverflowClip(), color, bg_layer,
+                           bleed_avoidance, box);
   Optional<BackgroundImageGeometry> geometry;
 
   // Fast path for drawing simple color backgrounds.
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
index b5da714..1946cdf 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.cpp
@@ -194,8 +194,8 @@
 }
 
 bool BoxPainterBase::ShouldForceWhiteBackgroundForPrintEconomy(
-    const ComputedStyle& style,
-    const Document& document) {
+    const Document& document,
+    const ComputedStyle& style) {
   return document.Printing() &&
          style.PrintColorAdjust() == EPrintColorAdjust::kEconomy &&
          (!document.GetSettings() ||
diff --git a/third_party/WebKit/Source/core/paint/BoxPainterBase.h b/third_party/WebKit/Source/core/paint/BoxPainterBase.h
index 4947fee7..0f50053 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainterBase.h
+++ b/third_party/WebKit/Source/core/paint/BoxPainterBase.h
@@ -51,8 +51,8 @@
       bool include_logical_left_edge = true,
       bool include_logical_right_edge = true);
 
-  static bool ShouldForceWhiteBackgroundForPrintEconomy(const ComputedStyle&,
-                                                        const Document&);
+  static bool ShouldForceWhiteBackgroundForPrintEconomy(const Document&,
+                                                        const ComputedStyle&);
 
   LayoutRect BoundsForDrawingRecorder(const PaintInfo&,
                                       const LayoutPoint& adjusted_paint_offset);
diff --git a/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp b/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
index 03174ee..03a58e1 100644
--- a/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ListMarkerPainter.cpp
@@ -94,8 +94,8 @@
   Color color(layout_list_marker_.ResolveColor(CSSPropertyColor));
 
   if (BoxPainter::ShouldForceWhiteBackgroundForPrintEconomy(
-          layout_list_marker_.StyleRef(),
-          layout_list_marker_.ListItem()->GetDocument()))
+          layout_list_marker_.ListItem()->GetDocument(),
+          layout_list_marker_.StyleRef()))
     color = TextPainter::TextColorForWhiteBackground(color);
 
   // Apply the color to the list marker text.
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index fef30af..6fb4d005 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -358,6 +358,15 @@
   return point;
 }
 
+IntPoint PaintLayerScrollableArea::ConvertFromRootFrame(
+    const IntPoint& point_in_root_frame) const {
+  LayoutView* view = Box().View();
+  if (!view)
+    return point_in_root_frame;
+
+  return view->GetFrameView()->ConvertFromRootFrame(point_in_root_frame);
+}
+
 int PaintLayerScrollableArea::ScrollSize(
     ScrollbarOrientation orientation) const {
   IntSize scroll_dimensions =
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
index c9683ae..c396827 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -269,6 +269,7 @@
   IntPoint ConvertFromContainingFrameViewBaseToScrollbar(
       const Scrollbar&,
       const IntPoint&) const override;
+  IntPoint ConvertFromRootFrame(const IntPoint&) const override;
   int ScrollSize(ScrollbarOrientation) const override;
   IntSize ScrollOffsetInt() const override;
   ScrollOffset GetScrollOffset() const override;
diff --git a/third_party/WebKit/Source/core/paint/TextPainterBase.cpp b/third_party/WebKit/Source/core/paint/TextPainterBase.cpp
index 903cde1..d4255b1 100644
--- a/third_party/WebKit/Source/core/paint/TextPainterBase.cpp
+++ b/third_party/WebKit/Source/core/paint/TextPainterBase.cpp
@@ -125,7 +125,7 @@
     DCHECK(document.Printing() == is_printing ||
            RuntimeEnabledFeatures::printBrowserEnabled());
     bool force_background_to_white =
-        BoxPainter::ShouldForceWhiteBackgroundForPrintEconomy(style, document);
+        BoxPainter::ShouldForceWhiteBackgroundForPrintEconomy(document, style);
     if (force_background_to_white) {
       text_style.fill_color =
           TextColorForWhiteBackground(text_style.fill_color);
diff --git a/third_party/WebKit/Source/core/paint/ViewPainter.cpp b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
index 748a4fe..74c089ce 100644
--- a/third_party/WebKit/Source/core/paint/ViewPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
@@ -106,7 +106,7 @@
   // Special handling for print economy mode.
   bool force_background_to_white =
       BoxPainter::ShouldForceWhiteBackgroundForPrintEconomy(
-          layout_view_.StyleRef(), document);
+          document, layout_view_.StyleRef());
   if (force_background_to_white) {
     // If for any reason the view background is not transparent, paint white
     // instead, otherwise keep transparent as is.
diff --git a/third_party/WebKit/Source/core/style/FillLayer.cpp b/third_party/WebKit/Source/core/style/FillLayer.cpp
index 47d104f..5aff336 100644
--- a/third_party/WebKit/Source/core/style/FillLayer.cpp
+++ b/third_party/WebKit/Source/core/style/FillLayer.cpp
@@ -369,14 +369,13 @@
   return true;
 }
 
-bool FillLayer::ImageIsOpaque(const LayoutObject& layout_object) const {
+bool FillLayer::ImageIsOpaque(const Document& document,
+                              const ComputedStyle& style) const {
   // Returns true if we have an image that will cover the content below it when
   // m_composite == CompositeSourceOver && m_blendMode == WebBlendModeNormal.
   // Otherwise false.
-  return image_->KnownToBeOpaque(layout_object) &&
-         !image_
-              ->ImageSize(layout_object.GetDocument(),
-                          layout_object.Style()->EffectiveZoom(), LayoutSize())
+  return image_->KnownToBeOpaque(document, style) &&
+         !image_->ImageSize(document, style.EffectiveZoom(), LayoutSize())
               .IsEmpty();
 }
 
@@ -390,8 +389,8 @@
          (repeat_y_ == kRepeatFill || repeat_y_ == kRoundFill);
 }
 
-bool FillLayer::ImageOccludesNextLayers(
-    const LayoutObject& layout_object) const {
+bool FillLayer::ImageOccludesNextLayers(const Document& document,
+                                        const ComputedStyle& style) const {
   // We can't cover without an image, regardless of other parameters
   if (!image_ || !image_->CanRender())
     return false;
@@ -402,7 +401,7 @@
       return ImageTilesLayer();
     case kCompositeSourceOver:
       return (blend_mode_ == kWebBlendModeNormal) && ImageTilesLayer() &&
-             ImageIsOpaque(layout_object);
+             ImageIsOpaque(document, style);
     default: {}
   }
 
diff --git a/third_party/WebKit/Source/core/style/FillLayer.h b/third_party/WebKit/Source/core/style/FillLayer.h
index 9118a5c..7f37fe57 100644
--- a/third_party/WebKit/Source/core/style/FillLayer.h
+++ b/third_party/WebKit/Source/core/style/FillLayer.h
@@ -225,7 +225,7 @@
     return next_ ? next_->HasFixedImage() : false;
   }
 
-  bool ImageOccludesNextLayers(const LayoutObject&) const;
+  bool ImageOccludesNextLayers(const Document&, const ComputedStyle&) const;
   bool HasRepeatXY() const;
   bool ClipOccludesNextLayers() const;
 
@@ -290,7 +290,7 @@
 
   FillLayer() {}
 
-  bool ImageIsOpaque(const LayoutObject&) const;
+  bool ImageIsOpaque(const Document&, const ComputedStyle&) const;
   bool ImageTilesLayer() const;
 
   FillLayer* next_;
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp b/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
index cd91a07..8cb0985 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImage.cpp
@@ -128,8 +128,8 @@
                                       obj.StyleRef().EffectiveZoom(), url_);
 }
 
-bool StyleFetchedImage::KnownToBeOpaque(
-    const LayoutObject& layout_object) const {
+bool StyleFetchedImage::KnownToBeOpaque(const Document&,
+                                        const ComputedStyle&) const {
   return image_->GetImage()->CurrentFrameKnownToBeOpaque(
       Image::kPreCacheMetadata);
 }
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImage.h b/third_party/WebKit/Source/core/style/StyleFetchedImage.h
index 80d95da..9a297ec 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImage.h
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImage.h
@@ -63,7 +63,7 @@
   String DebugName() const override { return "StyleFetchedImage"; }
   PassRefPtr<Image> GetImage(const LayoutObject&,
                              const IntSize&) const override;
-  bool KnownToBeOpaque(const LayoutObject&) const override;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
   ImageResourceContent* CachedImage() const override;
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
index d5866e7..aeaaec3 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.cpp
@@ -126,8 +126,8 @@
                                       obj.StyleRef().EffectiveZoom(), url_);
 }
 
-bool StyleFetchedImageSet::KnownToBeOpaque(
-    const LayoutObject& layout_object) const {
+bool StyleFetchedImageSet::KnownToBeOpaque(const Document&,
+                                           const ComputedStyle&) const {
   return best_fit_image_->GetImage()->CurrentFrameKnownToBeOpaque(
       Image::kPreCacheMetadata);
 }
diff --git a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
index 2c91fdb..65d9995 100644
--- a/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
+++ b/third_party/WebKit/Source/core/style/StyleFetchedImageSet.h
@@ -71,7 +71,7 @@
   PassRefPtr<Image> GetImage(const LayoutObject&,
                              const IntSize&) const override;
   float ImageScaleFactor() const override { return image_scale_factor_; }
-  bool KnownToBeOpaque(const LayoutObject&) const override;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
   ImageResourceContent* CachedImage() const override;
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
index 576159c..bd22e34 100644
--- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
+++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
@@ -73,9 +73,9 @@
   return image_generator_value_->GetImage(layout_object, size);
 }
 
-bool StyleGeneratedImage::KnownToBeOpaque(
-    const LayoutObject& layout_object) const {
-  return image_generator_value_->KnownToBeOpaque(layout_object);
+bool StyleGeneratedImage::KnownToBeOpaque(const Document& document,
+                                          const ComputedStyle& style) const {
+  return image_generator_value_->KnownToBeOpaque(document, style);
 }
 
 DEFINE_TRACE(StyleGeneratedImage) {
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.h b/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
index 0e7ae9bc..7d9b2799 100644
--- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
+++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.h
@@ -53,7 +53,7 @@
   void RemoveClient(LayoutObject*) override;
   PassRefPtr<Image> GetImage(const LayoutObject&,
                              const IntSize&) const override;
-  bool KnownToBeOpaque(const LayoutObject&) const override;
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
 
   DECLARE_VIRTUAL_TRACE();
 
diff --git a/third_party/WebKit/Source/core/style/StyleImage.h b/third_party/WebKit/Source/core/style/StyleImage.h
index 1bb8149..6f6aadbd 100644
--- a/third_party/WebKit/Source/core/style/StyleImage.h
+++ b/third_party/WebKit/Source/core/style/StyleImage.h
@@ -37,6 +37,7 @@
 class LayoutSize;
 class SVGImage;
 class Document;
+class ComputedStyle;
 
 typedef void* WrappedImagePtr;
 
@@ -71,7 +72,7 @@
                                      const IntSize& container_size) const = 0;
   virtual WrappedImagePtr Data() const = 0;
   virtual float ImageScaleFactor() const { return 1; }
-  virtual bool KnownToBeOpaque(const LayoutObject&) const = 0;
+  virtual bool KnownToBeOpaque(const Document&, const ComputedStyle&) const = 0;
   virtual ImageResourceContent* CachedImage() const { return 0; }
 
   ALWAYS_INLINE bool IsImageResource() const { return is_image_resource_; }
diff --git a/third_party/WebKit/Source/core/style/StyleInvalidImage.h b/third_party/WebKit/Source/core/style/StyleInvalidImage.h
index 9b731df9..cca09c95 100644
--- a/third_party/WebKit/Source/core/style/StyleInvalidImage.h
+++ b/third_party/WebKit/Source/core/style/StyleInvalidImage.h
@@ -37,7 +37,9 @@
                              const IntSize&) const override {
     return nullptr;
   }
-  bool KnownToBeOpaque(const LayoutObject&) const override { return false; }
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override {
+    return false;
+  }
 
   DEFINE_INLINE_VIRTUAL_TRACE() { StyleImage::Trace(visitor); }
 
diff --git a/third_party/WebKit/Source/core/style/StylePendingImage.h b/third_party/WebKit/Source/core/style/StylePendingImage.h
index 8c87543..69f96e1 100644
--- a/third_party/WebKit/Source/core/style/StylePendingImage.h
+++ b/third_party/WebKit/Source/core/style/StylePendingImage.h
@@ -84,7 +84,9 @@
     NOTREACHED();
     return nullptr;
   }
-  bool KnownToBeOpaque(const LayoutObject&) const override { return false; }
+  bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override {
+    return false;
+  }
 
   DEFINE_INLINE_VIRTUAL_TRACE() {
     visitor->Trace(value_);
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 1874632..3c0a47f 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2781,6 +2781,16 @@
   return element->ImageSourceURL();
 }
 
+void Internals::forceImageReload(Element* element,
+                                 ExceptionState& exception_state) {
+  if (!element || !isHTMLImageElement(*element)) {
+    exception_state.ThrowDOMException(
+        kInvalidAccessError, "The element should be HTMLImageElement.");
+  }
+
+  toHTMLImageElement(*element).ForceReload();
+}
+
 String Internals::selectMenuListText(HTMLSelectElement* select) {
   DCHECK(select);
   LayoutObject* layout_object = select->GetLayoutObject();
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 11fbca5f..56b40ce 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -421,6 +421,7 @@
   void forceReload(bool bypass_cache);
 
   String getImageSourceURL(Element*);
+  void forceImageReload(Element*, ExceptionState&);
 
   String selectMenuListText(HTMLSelectElement*);
   bool isSelectPopupVisible(Node*);
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index 7a6146e..71620d29 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -270,6 +270,7 @@
     void forceReload(boolean endToEnd);
 
     DOMString getImageSourceURL(Element element);
+    [RaisesException] void forceImageReload(Element element);
 
     DOMString selectMenuListText(HTMLSelectElement select);
     boolean isSelectPopupVisible(Node node);
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
index ed7fa9b..9728280 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.h
@@ -67,6 +67,7 @@
   static bool CanTransferArrayBuffersAndImageBitmaps() { return true; }
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(messageerror);
 
   DECLARE_VIRTUAL_TRACE();
 
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.idl b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.idl
index a66c738..6a192533 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.idl
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.idl
@@ -39,4 +39,5 @@
     void close();
 
     attribute EventHandler onmessage;
+    attribute EventHandler onmessageerror;
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
index 09f0ab9e..871728a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -515,6 +515,11 @@
       if (!this._continueToLocationDecorations)
         this._showContinueToLocations();
     }
+    if (this._continueToLocationDecorations) {
+      this.textEditor.element.classList.toggle(
+          'source-frame-async-step-in-hovered',
+          !!event.target.enclosingNodeOrSelfWithClass('source-frame-async-step-in'));
+    }
   }
 
   /**
@@ -915,6 +920,7 @@
       for (var decoration of this._continueToLocationDecorations.keys())
         this.textEditor.removeHighlight(decoration);
       this._continueToLocationDecorations = null;
+      this.textEditor.element.classList.remove('source-frame-async-step-in-hovered');
     });
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
index bc278a3c..aac305c 100644
--- a/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
+++ b/third_party/WebKit/Source/devtools/front_end/text_editor/cmdevtools.css
@@ -79,7 +79,7 @@
     width: 10px;
 }
 
-.CodeMirror .source-frame-async-step-in:hover {
+.source-frame-async-step-in-hovered .source-frame-async-step-in {
     background-color: hsl(100, 79%, 77%);
 }
 
diff --git a/third_party/WebKit/Source/modules/OWNERS b/third_party/WebKit/Source/modules/OWNERS
index 710055d..adb5ada6 100644
--- a/third_party/WebKit/Source/modules/OWNERS
+++ b/third_party/WebKit/Source/modules/OWNERS
@@ -1,4 +1,3 @@
-esprehn@chromium.org
 haraken@chromium.org
 mkwst@chromium.org
 mlamouri@chromium.org
diff --git a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.h b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.h
index 7b81f95..e27351b 100644
--- a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.h
+++ b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.h
@@ -37,6 +37,7 @@
   void postMessage(const ScriptValue&, ExceptionState&);
   void close();
   DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(messageerror);
 
   // EventTarget:
   const AtomicString& InterfaceName() const override;
diff --git a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.idl b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.idl
index c9b2912..e321edd 100644
--- a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.idl
+++ b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.idl
@@ -21,4 +21,5 @@
 
     // event handlers
     attribute EventHandler onmessage;
+    attribute EventHandler onmessageerror;
 };
diff --git a/third_party/WebKit/Source/modules/imagecapture/README.md b/third_party/WebKit/Source/modules/imagecapture/README.md
index b0b52e2..b85f7ae 100644
--- a/third_party/WebKit/Source/modules/imagecapture/README.md
+++ b/third_party/WebKit/Source/modules/imagecapture/README.md
@@ -43,7 +43,7 @@
 while connecting the Red Eye Reduction, if available, is not.
 
 | Object                   |type                 | retrieved by...                         |
-| :--                      |:--                  | --:                                     |
+|:------------------------ |:------------------- | ---------------------------------------:|
 |[`PhotoCapabilities`]     |non-live capabilities|`theImageCapturer.getPhotoCapabilities()`|
 |[`MediaTrackCapabilities`]|live capabilities    |`theTrack.getCapabilities()`             |
 |                          |                     |                                         |
diff --git a/third_party/WebKit/Source/modules/shapedetection/DetectedBarcode.idl b/third_party/WebKit/Source/modules/shapedetection/DetectedBarcode.idl
index 8472bbf..1b4f77d 100644
--- a/third_party/WebKit/Source/modules/shapedetection/DetectedBarcode.idl
+++ b/third_party/WebKit/Source/modules/shapedetection/DetectedBarcode.idl
@@ -13,5 +13,5 @@
     [SameObject] readonly attribute DOMRect boundingBox;
     // 4 corner points in clockwise direction starting with top-left. Due to
     // possible perspective distortions, this is not necessarily a rectangle.
-    [SameObject] readonly attribute FrozenArray<Point2D> cornerPoints;
+    [SameObject, SaveSameObject] readonly attribute FrozenArray<Point2D> cornerPoints;
 };
diff --git a/third_party/WebKit/Source/modules/shapedetection/DetectedFace.h b/third_party/WebKit/Source/modules/shapedetection/DetectedFace.h
index 5c14f1d6..969f4327 100644
--- a/third_party/WebKit/Source/modules/shapedetection/DetectedFace.h
+++ b/third_party/WebKit/Source/modules/shapedetection/DetectedFace.h
@@ -31,8 +31,8 @@
   explicit DetectedFace(DOMRect*);
   DetectedFace(DOMRect*, const HeapVector<Landmark>&);
 
-  Member<DOMRect> bounding_box_;
-  HeapVector<Landmark> landmarks_;
+  const Member<DOMRect> bounding_box_;
+  const HeapVector<Landmark> landmarks_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/shapedetection/DetectedFace.idl b/third_party/WebKit/Source/modules/shapedetection/DetectedFace.idl
index bccaab0..ef6150b4 100644
--- a/third_party/WebKit/Source/modules/shapedetection/DetectedFace.idl
+++ b/third_party/WebKit/Source/modules/shapedetection/DetectedFace.idl
@@ -9,7 +9,6 @@
     RuntimeEnabled=ShapeDetection,
 ] interface DetectedFace {
     // TODO(xianglu): Implement any other fields. https://crbug.com/646083
-    readonly attribute DOMRect boundingBox;
-
-    [SameObject] readonly attribute FrozenArray<Landmark> landmarks;
+    [SameObject] readonly attribute DOMRect boundingBox;
+    [SameObject, SaveSameObject] readonly attribute FrozenArray<Landmark> landmarks;
 };
diff --git a/third_party/WebKit/Source/modules/shapedetection/DetectedText.idl b/third_party/WebKit/Source/modules/shapedetection/DetectedText.idl
index 99d8306..57075627 100644
--- a/third_party/WebKit/Source/modules/shapedetection/DetectedText.idl
+++ b/third_party/WebKit/Source/modules/shapedetection/DetectedText.idl
@@ -8,6 +8,6 @@
     Constructor,
     RuntimeEnabled=ShapeDetection,
 ] interface DetectedText {
-    [SameObject] readonly attribute DOMRect boundingBox;
     [SameObject] readonly attribute DOMString rawValue;
+    [SameObject] readonly attribute DOMRect boundingBox;
 };
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
index 31fbc5f1..5122c99 100644
--- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
+++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -220,6 +220,14 @@
     return promise;
   }
 
+  // When we are requesting to start presentation with a user action or the
+  // display has activated, record the user action.
+  if (first_present &&
+      (UserGestureIndicator::ProcessingUserGesture() || in_display_activate_)) {
+    Platform::Current()->RecordAction(
+        UserMetricsAction("VR.WebVR.requestPresent"));
+  }
+
   // A valid number of layers must be provided in order to present.
   if (layers.size() == 0 || layers.size() > capabilities_->maxLayers()) {
     ForceExitPresent();
@@ -671,7 +679,13 @@
       // Can't get into this presentation mode, so nothing to do here.
     }
     is_presenting_ = false;
+
     OnPresentChange();
+
+    // Record user action for stop presenting.  Note that this could be
+    // user-triggered or not.
+    Platform::Current()->RecordAction(
+        UserMetricsAction("VR.WebVR.StopPresenting"));
   }
 
   rendering_context_ = nullptr;
diff --git a/third_party/WebKit/Source/modules/webauth/BUILD.gn b/third_party/WebKit/Source/modules/webauth/BUILD.gn
index fa4e1d75..eaa78b4 100644
--- a/third_party/WebKit/Source/modules/webauth/BUILD.gn
+++ b/third_party/WebKit/Source/modules/webauth/BUILD.gn
@@ -16,6 +16,7 @@
   ]
 
   deps = [
+    "//components/webauth:authenticator_blink",
     "//device/usb/public/interfaces:interfaces_blink",
   ]
 }
diff --git a/third_party/WebKit/Source/modules/webauth/DEPS b/third_party/WebKit/Source/modules/webauth/DEPS
index 1e6ebea1..9bcda18 100644
--- a/third_party/WebKit/Source/modules/webauth/DEPS
+++ b/third_party/WebKit/Source/modules/webauth/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/webauth",
   "+device/usb/public/interfaces",
   "+mojo/public/cpp/bindings",
 ]
diff --git a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
index 1274dcf..06cba2c 100644
--- a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
+++ b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
@@ -4,13 +4,133 @@
 
 #include "modules/webauth/WebAuthentication.h"
 
+#include <stdint.h>
+
 #include "bindings/core/v8/ScriptPromise.h"
+#include "bindings/core/v8/ScriptPromiseResolver.h"
+#include "core/dom/DOMException.h"
+#include "core/dom/Document.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/frame/LocalFrame.h"
+#include "modules/webauth/RelyingPartyAccount.h"
+#include "modules/webauth/ScopedCredential.h"
+#include "modules/webauth/ScopedCredentialOptions.h"
+#include "modules/webauth/ScopedCredentialParameters.h"
+#include "public/platform/InterfaceProvider.h"
+
+namespace {
+const char kNoAuthenticatorError[] = "Authenticator unavailable.";
+}  // anonymous namespace
+
+namespace mojo {
+
+using webauth::mojom::blink::RelyingPartyAccount;
+using webauth::mojom::blink::RelyingPartyAccountPtr;
+using webauth::mojom::blink::ScopedCredentialOptions;
+using webauth::mojom::blink::ScopedCredentialOptionsPtr;
+using webauth::mojom::blink::ScopedCredentialParameters;
+using webauth::mojom::blink::ScopedCredentialParametersPtr;
+using webauth::mojom::blink::ScopedCredentialDescriptor;
+using webauth::mojom::blink::ScopedCredentialType;
+using webauth::mojom::blink::Transport;
+
+// TODO(kpaulhamus): Make this a TypeConverter
+Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) {
+  DCHECK(buffer.isNull());
+  Vector<uint8_t> vector;
+  if (buffer.isArrayBuffer()) {
+    vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
+                  buffer.getAsArrayBuffer()->ByteLength());
+  } else {
+    vector.Append(static_cast<uint8_t*>(
+                      buffer.getAsArrayBufferView().View()->BaseAddress()),
+                  buffer.getAsArrayBufferView().View()->byteLength());
+  }
+  return vector;
+}
+
+// TODO(kpaulhamus): Make this a TypeConverter
+ScopedCredentialType ConvertScopedCredentialType(const String& cred_type) {
+  if (cred_type == "ScopedCred")
+    return ScopedCredentialType::SCOPEDCRED;
+  NOTREACHED();
+  return ScopedCredentialType::SCOPEDCRED;
+}
+
+// TODO(kpaulhamus): Make this a TypeConverter
+Transport ConvertTransport(const String& transport) {
+  if (transport == "usb")
+    return Transport::USB;
+  if (transport == "nfc")
+    return Transport::NFC;
+  if (transport == "ble")
+    return Transport::BLE;
+  NOTREACHED();
+  return Transport::USB;
+}
+
+RelyingPartyAccountPtr ConvertRelyingPartyAccount(
+    const blink::RelyingPartyAccount& account_information,
+    blink::ScriptPromiseResolver* resolver) {
+  auto mojo_account = RelyingPartyAccount::New();
+
+  mojo_account->relying_party_display_name =
+      account_information.rpDisplayName();
+  mojo_account->display_name = account_information.displayName();
+  mojo_account->id = account_information.id();
+  mojo_account->name = account_information.name();
+  mojo_account->image_url = account_information.imageURL();
+  return mojo_account;
+}
+
+// TODO(kpaulhamus): Make this a TypeConverter
+ScopedCredentialOptionsPtr ConvertScopedCredentialOptions(
+    const blink::ScopedCredentialOptions options,
+    blink::ScriptPromiseResolver* resolver) {
+  auto mojo_options = ScopedCredentialOptions::New();
+  mojo_options->timeout_seconds = options.timeoutSeconds();
+  mojo_options->relying_party_id = options.rpId();
+
+  // Adds the excludeList members (which are ScopedCredentialDescriptors)
+  for (const auto& descriptor : options.excludeList()) {
+    auto mojo_descriptor = ScopedCredentialDescriptor::New();
+    mojo_descriptor->type = ConvertScopedCredentialType(descriptor.type());
+    mojo_descriptor->id = ConvertBufferSource(descriptor.id());
+    for (const auto& transport : descriptor.transports())
+      mojo_descriptor->transports.push_back(ConvertTransport(transport));
+    mojo_options->exclude_list.push_back(std::move(mojo_descriptor));
+  }
+  // TODO(kpaulhamus): add AuthenticationExtensions;
+  return mojo_options;
+}
+
+// TODO(kpaulhamus): Make this a TypeConverter
+ScopedCredentialParametersPtr ConvertScopedCredentialParameter(
+    const blink::ScopedCredentialParameters parameter,
+    blink::ScriptPromiseResolver* resolver) {
+  auto mojo_parameter = ScopedCredentialParameters::New();
+  mojo_parameter->type = ConvertScopedCredentialType(parameter.type());
+  // TODO(kpaulhamus): add AlgorithmIdentifier
+  return mojo_parameter;
+}
+}  // namespace mojo
 
 namespace blink {
 
-WebAuthentication::WebAuthentication(LocalFrame& frame) {}
+WebAuthentication::WebAuthentication(LocalFrame& frame)
+    : ContextLifecycleObserver(frame.GetDocument()) {
+  frame.GetInterfaceProvider()->GetInterface(
+      mojo::MakeRequest(&authenticator_));
+  authenticator_.set_connection_error_handler(ConvertToBaseCallback(
+      WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
+                WrapWeakPersistent(this))));
+}
 
-WebAuthentication::~WebAuthentication() {}
+WebAuthentication::~WebAuthentication() {
+  // |authenticator_| may still be valid but there should be no more
+  // outstanding requests because each holds a persistent handle to this object.
+  DCHECK(authenticator_requests_.IsEmpty());
+}
 
 void WebAuthentication::Dispose() {}
 
@@ -20,8 +140,32 @@
     const HeapVector<ScopedCredentialParameters> crypto_parameters,
     const BufferSource& attestation_challenge,
     ScopedCredentialOptions& options) {
-  NOTREACHED();
-  return ScriptPromise();
+  if (!authenticator_) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kNotSupportedError));
+  }
+
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  ScriptPromise promise = resolver->Promise();
+
+  // TODO(kpaulhamus) validate parameters according to spec
+  auto account =
+      mojo::ConvertRelyingPartyAccount(account_information, resolver);
+  Vector<uint8_t> buffer = mojo::ConvertBufferSource(attestation_challenge);
+  auto opts = mojo::ConvertScopedCredentialOptions(options, resolver);
+  Vector<webauth::mojom::blink::ScopedCredentialParametersPtr> parameters;
+  for (const auto& parameter : crypto_parameters) {
+    parameters.push_back(
+        mojo::ConvertScopedCredentialParameter(parameter, resolver));
+  }
+
+  authenticator_requests_.insert(resolver);
+  authenticator_->MakeCredential(
+      std::move(account), std::move(parameters), buffer, std::move(opts),
+      ConvertToBaseCallback(Bind(&WebAuthentication::OnMakeCredential,
+                                 WrapPersistent(this),
+                                 WrapPersistent(resolver))));
+  return promise;
 }
 
 ScriptPromise WebAuthentication::getAssertion(
@@ -32,4 +176,58 @@
   return ScriptPromise();
 }
 
+void WebAuthentication::ContextDestroyed(ExecutionContext*) {
+  authenticator_.reset();
+  authenticator_requests_.clear();
+}
+
+void WebAuthentication::OnAuthenticatorConnectionError() {
+  authenticator_.reset();
+  for (ScriptPromiseResolver* resolver : authenticator_requests_) {
+    resolver->Reject(
+        DOMException::Create(kNotFoundError, kNoAuthenticatorError));
+  }
+  authenticator_requests_.clear();
+}
+
+void WebAuthentication::OnMakeCredential(
+    ScriptPromiseResolver* resolver,
+    Vector<webauth::mojom::blink::ScopedCredentialInfoPtr> credentials) {
+  if (!MarkRequestComplete(resolver))
+    return;
+
+  HeapVector<Member<ScopedCredentialInfo>> scoped_credentials;
+  for (auto& credential : credentials) {
+    if (credential->client_data.IsEmpty() ||
+        credential->attestation.IsEmpty()) {
+      resolver->Reject(
+          DOMException::Create(kNotFoundError, "No credentials returned."));
+    }
+    DOMArrayBuffer* client_data_buffer = DOMArrayBuffer::Create(
+        static_cast<void*>(&credential->client_data.front()),
+        credential->client_data.size());
+
+    DOMArrayBuffer* attestation_buffer = DOMArrayBuffer::Create(
+        static_cast<void*>(&credential->attestation.front()),
+        credential->attestation.size());
+
+    scoped_credentials.push_back(
+        ScopedCredentialInfo::Create(client_data_buffer, attestation_buffer));
+  }
+  resolver->Resolve();
+}
+
+bool WebAuthentication::MarkRequestComplete(ScriptPromiseResolver* resolver) {
+  auto request_entry = authenticator_requests_.find(resolver);
+  if (request_entry == authenticator_requests_.end())
+    return false;
+  authenticator_requests_.erase(request_entry);
+  return true;
+}
+
+DEFINE_TRACE(WebAuthentication) {
+  visitor->Trace(authenticator_requests_);
+  ContextLifecycleObserver::Trace(visitor);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webauth/WebAuthentication.h b/third_party/WebKit/Source/modules/webauth/WebAuthentication.h
index 7f36dc9..262bc8b8 100644
--- a/third_party/WebKit/Source/modules/webauth/WebAuthentication.h
+++ b/third_party/WebKit/Source/modules/webauth/WebAuthentication.h
@@ -7,28 +7,29 @@
 
 #include "bindings/core/v8/ArrayBufferOrArrayBufferView.h"
 #include "bindings/core/v8/ScriptPromise.h"
+#include "components/webauth/authenticator.mojom-blink.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "core/dom/DOMArrayBuffer.h"
 #include "modules/webauth/AuthenticationAssertionOptions.h"
-#include "modules/webauth/RelyingPartyAccount.h"
-#include "modules/webauth/ScopedCredentialOptions.h"
-#include "modules/webauth/ScopedCredentialParameters.h"
+#include "modules/webauth/ScopedCredentialInfo.h"
 #include "platform/bindings/ScriptWrappable.h"
 
 namespace blink {
 
-class LocalFrame;
-class ScriptState;
 class RelyingPartyAccount;
 class AuthenticationAssertionOptions;
-class ScopedCredentialParameters;
 class ScopedCredentialOptions;
+class ScopedCredentialParameters;
+class ScriptPromiseResolver;
 
 typedef ArrayBufferOrArrayBufferView BufferSource;
 
 class WebAuthentication final
     : public GarbageCollectedFinalized<WebAuthentication>,
-      public ScriptWrappable {
+      public ScriptWrappable,
+      public ContextLifecycleObserver {
   DEFINE_WRAPPERTYPEINFO();
+  USING_GARBAGE_COLLECTED_MIXIN(WebAuthentication);
 
  public:
   static WebAuthentication* Create(LocalFrame& frame) {
@@ -39,6 +40,7 @@
 
   void Dispose();
 
+  // WebAuthentication.idl
   ScriptPromise makeCredential(ScriptState*,
                                const RelyingPartyAccount&,
                                const HeapVector<ScopedCredentialParameters>,
@@ -48,12 +50,27 @@
                              const BufferSource&,
                              const AuthenticationAssertionOptions&);
 
-  DEFINE_INLINE_TRACE() {}
+  // ContextLifecycleObserver overrides.
+  void ContextDestroyed(ExecutionContext*) override;
+
+  webauth::mojom::blink::Authenticator* Authenticator() const {
+    return authenticator_.get();
+  }
+
+  void OnMakeCredential(ScriptPromiseResolver*,
+                        Vector<webauth::mojom::blink::ScopedCredentialInfoPtr>);
+  bool MarkRequestComplete(ScriptPromiseResolver*);
+
+  void OnAuthenticatorConnectionError();
+
+  DECLARE_VIRTUAL_TRACE();
 
  private:
   explicit WebAuthentication(LocalFrame&);
-};
 
+  webauth::mojom::blink::AuthenticatorPtr authenticator_;
+  HeapHashSet<Member<ScriptPromiseResolver>> authenticator_requests_;
+};
 }  // namespace blink
 
 #endif  // WebAuthentication_h
diff --git a/third_party/WebKit/Source/modules/webusb/USB.cpp b/third_party/WebKit/Source/modules/webusb/USB.cpp
index be6863a1..25480f4 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -28,6 +28,10 @@
 namespace blink {
 namespace {
 
+const char kFeaturePolicyBlocked[] =
+    "Access to the feature \"usb\" is disallowed by feature policy.";
+const char kIframeBlocked[] =
+    "Access to this method is not allowed in embedded frames.";
 const char kNoDeviceSelected[] = "No device selected.";
 
 UsbDeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) {
@@ -72,31 +76,53 @@
 }
 
 ScriptPromise USB::getDevices(ScriptState* script_state) {
-  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
-  ScriptPromise promise = resolver->Promise();
-  EnsureDeviceManagerConnection();
-  if (!device_manager_) {
-    resolver->Reject(DOMException::Create(kNotSupportedError));
-  } else {
-    device_manager_requests_.insert(resolver);
-    device_manager_->GetDevices(
-        nullptr, ConvertToBaseCallback(WTF::Bind(&USB::OnGetDevices,
-                                                 WrapPersistent(this),
-                                                 WrapPersistent(resolver))));
+  LocalFrame* frame = GetFrame();
+  if (!frame) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kNotSupportedError));
   }
-  return promise;
+
+  if (RuntimeEnabledFeatures::featurePolicyEnabled()) {
+    if (!frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb)) {
+      return ScriptPromise::RejectWithDOMException(
+          script_state,
+          DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
+    }
+  } else if (!frame->IsMainFrame()) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kSecurityError, kIframeBlocked));
+  }
+
+  EnsureDeviceManagerConnection();
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  device_manager_requests_.insert(resolver);
+  device_manager_->GetDevices(
+      nullptr,
+      ConvertToBaseCallback(WTF::Bind(&USB::OnGetDevices, WrapPersistent(this),
+                                      WrapPersistent(resolver))));
+  return resolver->Promise();
 }
 
 ScriptPromise USB::requestDevice(ScriptState* script_state,
                                  const USBDeviceRequestOptions& options) {
-  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
-  ScriptPromise promise = resolver->Promise();
+  LocalFrame* frame = GetFrame();
+  if (!frame) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kNotSupportedError));
+  }
+
+  if (RuntimeEnabledFeatures::featurePolicyEnabled()) {
+    if (!frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb)) {
+      return ScriptPromise::RejectWithDOMException(
+          script_state,
+          DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
+    }
+  } else if (!frame->IsMainFrame()) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(kSecurityError, kIframeBlocked));
+  }
 
   if (!chooser_service_) {
-    if (!GetFrame()) {
-      resolver->Reject(DOMException::Create(kNotSupportedError));
-      return promise;
-    }
     GetFrame()->GetInterfaceProvider()->GetInterface(
         mojo::MakeRequest(&chooser_service_));
     chooser_service_.set_connection_error_handler(
@@ -105,23 +131,27 @@
   }
 
   if (!UserGestureIndicator::ConsumeUserGesture()) {
-    resolver->Reject(DOMException::Create(
-        kSecurityError,
-        "Must be handling a user gesture to show a permission request."));
-  } else {
-    Vector<UsbDeviceFilterPtr> filters;
-    if (options.hasFilters()) {
-      filters.ReserveCapacity(options.filters().size());
-      for (const auto& filter : options.filters())
-        filters.push_back(ConvertDeviceFilter(filter));
-    }
-    chooser_service_requests_.insert(resolver);
-    chooser_service_->GetPermission(
-        std::move(filters), ConvertToBaseCallback(WTF::Bind(
-                                &USB::OnGetPermission, WrapPersistent(this),
-                                WrapPersistent(resolver))));
+    return ScriptPromise::RejectWithDOMException(
+        script_state,
+        DOMException::Create(
+            kSecurityError,
+            "Must be handling a user gesture to show a permission request."));
   }
-  return promise;
+
+  Vector<UsbDeviceFilterPtr> filters;
+  if (options.hasFilters()) {
+    filters.ReserveCapacity(options.filters().size());
+    for (const auto& filter : options.filters())
+      filters.push_back(ConvertDeviceFilter(filter));
+  }
+
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+  chooser_service_requests_.insert(resolver);
+  chooser_service_->GetPermission(
+      std::move(filters), ConvertToBaseCallback(WTF::Bind(
+                              &USB::OnGetPermission, WrapPersistent(this),
+                              WrapPersistent(resolver))));
+  return resolver->Promise();
 }
 
 ExecutionContext* USB::GetExecutionContext() const {
@@ -175,11 +205,10 @@
 
   EnsureDeviceManagerConnection();
 
-  if (device_manager_ && device_info) {
+  if (device_manager_ && device_info)
     resolver->Resolve(GetOrCreateDevice(std::move(device_info)));
-  } else {
+  else
     resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected));
-  }
 }
 
 void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) {
@@ -219,16 +248,28 @@
 void USB::AddedEventListener(const AtomicString& event_type,
                              RegisteredEventListener& listener) {
   EventTargetWithInlineData::AddedEventListener(event_type, listener);
-  if (event_type == EventTypeNames::connect ||
-      event_type == EventTypeNames::disconnect) {
+  if (event_type != EventTypeNames::connect &&
+      event_type != EventTypeNames::disconnect) {
+    return;
+  }
+
+  LocalFrame* frame = GetFrame();
+  if (!frame)
+    return;
+
+  if (RuntimeEnabledFeatures::featurePolicyEnabled()) {
+    if (frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb))
+      EnsureDeviceManagerConnection();
+  } else if (frame->IsMainFrame()) {
     EnsureDeviceManagerConnection();
   }
 }
 
 void USB::EnsureDeviceManagerConnection() {
-  if (device_manager_ || !GetFrame())
+  if (device_manager_)
     return;
 
+  DCHECK(GetFrame());
   GetFrame()->GetInterfaceProvider()->GetInterface(
       mojo::MakeRequest(&device_manager_));
   device_manager_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind(
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 82b6562..a98b805 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -257,7 +257,6 @@
     "FileMetadata.cpp",
     "FileMetadata.h",
     "FileSystemType.h",
-    "FrameViewBase.h",
     "Histogram.cpp",
     "Histogram.h",
     "InstanceCounters.cpp",
diff --git a/third_party/WebKit/Source/platform/DEPS b/third_party/WebKit/Source/platform/DEPS
index cd7ace6..1a5de4e2 100644
--- a/third_party/WebKit/Source/platform/DEPS
+++ b/third_party/WebKit/Source/platform/DEPS
@@ -10,6 +10,7 @@
     "+base/json",
     "+base/location.h",
     "+base/memory",
+    "+base/message_loop/message_loop.h",
     "+base/metrics/histogram.h",
     "+base/metrics/histogram_base.h",
     "+base/metrics/histogram_macros.h",
diff --git a/third_party/WebKit/Source/platform/FrameViewBase.h b/third_party/WebKit/Source/platform/FrameViewBase.h
deleted file mode 100644
index f68c377..0000000
--- a/third_party/WebKit/Source/platform/FrameViewBase.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
- * Copyright (C) 2008 Collabora Ltd.  All rights reserved.
- * Copyright (C) 2013 Google Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FrameViewBase_h
-#define FrameViewBase_h
-
-#include "platform/PlatformExport.h"
-#include "platform/geometry/FloatPoint.h"
-#include "platform/geometry/IntRect.h"
-#include "platform/heap/Handle.h"
-
-namespace blink {
-
-// The FrameViewBase class is the parent of Scrollbar.
-// TODO(joelhockey): Move core/paint/ScrollbarManager to platform/scroll
-// and use it to replace this class.
-class PLATFORM_EXPORT FrameViewBase : public GarbageCollectedMixin {
- public:
-  FrameViewBase(){};
-  virtual ~FrameViewBase(){};
-
-  virtual IntPoint Location() const = 0;
-
-  virtual bool IsFrameView() const { return false; }
-
-  virtual FrameViewBase* Parent() const = 0;
-
-  // ConvertFromRootFrame must be in FrameViewBase rather than FrameView
-  // to be visible to Scrollbar::ConvertFromRootFrame and
-  // RemoteFrameView::UpdateRemoteViewportIntersection. The related
-  // ConvertFromContainingFrameViewBase must be declared locally to be visible.
-  IntRect ConvertFromRootFrame(const IntRect& rect_in_root_frame) const {
-    if (const FrameViewBase* parent_frame_view_base = Parent()) {
-      IntRect parent_rect =
-          parent_frame_view_base->ConvertFromRootFrame(rect_in_root_frame);
-      return ConvertFromContainingFrameViewBase(parent_rect);
-    }
-    return rect_in_root_frame;
-  }
-
-  IntPoint ConvertFromRootFrame(const IntPoint& point_in_root_frame) const {
-    if (const FrameViewBase* parent_frame_view_base = Parent()) {
-      IntPoint parent_point =
-          parent_frame_view_base->ConvertFromRootFrame(point_in_root_frame);
-      return ConvertFromContainingFrameViewBase(parent_point);
-    }
-    return point_in_root_frame;
-  }
-
-  FloatPoint ConvertFromRootFrame(const FloatPoint& point_in_root_frame) const {
-    // FrameViewBase / windows are required to be IntPoint aligned, but we may
-    // need to convert FloatPoint values within them (eg. for event
-    // co-ordinates).
-    IntPoint floored_point = FlooredIntPoint(point_in_root_frame);
-    FloatPoint parent_point = ConvertFromRootFrame(floored_point);
-    FloatSize window_fraction = point_in_root_frame - floored_point;
-    // Use linear interpolation handle any fractional value (eg. for iframes
-    // subject to a transform beyond just a simple translation).
-    // FIXME: Add FloatPoint variants of all co-ordinate space conversion APIs.
-    if (!window_fraction.IsEmpty()) {
-      const int kFactor = 1000;
-      IntPoint parent_line_end = ConvertFromRootFrame(
-          floored_point + RoundedIntSize(window_fraction.ScaledBy(kFactor)));
-      FloatSize parent_fraction =
-          (parent_line_end - parent_point).ScaledBy(1.0f / kFactor);
-      parent_point.Move(parent_fraction);
-    }
-    return parent_point;
-  }
-
-  virtual IntRect ConvertFromContainingFrameViewBase(const IntRect&) const = 0;
-  virtual IntPoint ConvertFromContainingFrameViewBase(
-      const IntPoint&) const = 0;
-
-  virtual void Dispose() {}
-};
-
-}  // namespace blink
-
-#endif  // FrameViewBase_h
diff --git a/third_party/WebKit/Source/platform/OWNERS b/third_party/WebKit/Source/platform/OWNERS
index 33b1079..50537c8 100644
--- a/third_party/WebKit/Source/platform/OWNERS
+++ b/third_party/WebKit/Source/platform/OWNERS
@@ -1,7 +1,6 @@
 dglazkov@chromium.org
 drott@chromium.org
 eae@chromium.org
-esprehn@chromium.org
 fmalita@chromium.org
 haraken@chromium.org
 jbroman@chromium.org
diff --git a/third_party/WebKit/Source/platform/PlatformChromeClient.h b/third_party/WebKit/Source/platform/PlatformChromeClient.h
index f3d99db..f44b9cd6 100644
--- a/third_party/WebKit/Source/platform/PlatformChromeClient.h
+++ b/third_party/WebKit/Source/platform/PlatformChromeClient.h
@@ -33,6 +33,7 @@
 #include "platform/wtf/Noncopyable.h"
 
 namespace blink {
+
 class IntRect;
 
 class PLATFORM_EXPORT PlatformChromeClient
diff --git a/third_party/WebKit/Source/platform/TimerTest.cpp b/third_party/WebKit/Source/platform/TimerTest.cpp
index ee46d223..2b648f74 100644
--- a/third_party/WebKit/Source/platform/TimerTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerTest.cpp
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <queue>
+#include "base/message_loop/message_loop.h"
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/child/web_scheduler.h"
 #include "platform/scheduler/child/web_task_runner_impl.h"
diff --git a/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h b/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h
index 561e0ae..500c413 100644
--- a/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h
+++ b/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h
@@ -55,6 +55,8 @@
   X(NamedConstructor, Initialized)                    \
   X(PerformanceObserver, Callback)                    \
   X(PopStateEvent, State)                             \
+  X(SameObject, DetectedBarcodeCornerPoints)          \
+  X(SameObject, DetectedFaceLandmarks)                \
   X(SameObject, NotificationActions)                  \
   X(SameObject, NotificationData)                     \
   X(SameObject, NotificationVibrate)                  \
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
index 74d15ee8..f9ab84f 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
@@ -150,6 +150,7 @@
     default_feature_name_map.Set("fullscreen",
                                  WebFeaturePolicyFeature::kFullscreen);
     default_feature_name_map.Set("payment", WebFeaturePolicyFeature::kPayment);
+    default_feature_name_map.Set("usb", WebFeaturePolicyFeature::kUsb);
     if (RuntimeEnabledFeatures::featurePolicyExperimentalFeaturesEnabled()) {
       default_feature_name_map.Set("vibrate",
                                    WebFeaturePolicyFeature::kVibrate);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
index 614331c..e1d590f 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -770,6 +770,9 @@
   EXPECT_EQ(transform_node_index, transform_node.id);
 
   EXPECT_EQ(0u, scroll_client.did_scroll_count);
+  // TODO(pdr): The PaintArtifactCompositor should set the scroll clip layer id
+  // so the Layer is scrollable. This call should be removed.
+  layer->SetScrollClipLayerId(layer->id());
   layer->SetScrollOffsetFromImplSide(gfx::ScrollOffset(1, 2));
   EXPECT_EQ(1u, scroll_client.did_scroll_count);
   EXPECT_EQ(gfx::ScrollOffset(1, 2), scroll_client.last_scroll_offset);
diff --git a/third_party/WebKit/Source/platform/json/OWNERS b/third_party/WebKit/Source/platform/json/OWNERS
index 19f9406..273c6c0 100644
--- a/third_party/WebKit/Source/platform/json/OWNERS
+++ b/third_party/WebKit/Source/platform/json/OWNERS
@@ -1,4 +1,3 @@
-esprehn@chromium.org
 pfeldman@chromium.org
 iclelland@chromium.org
 
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
index fc20922a..77fbf79 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -12,6 +12,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pending_task.h"
 #include "base/threading/thread_checker.h"
 #include "base/trace_event/trace_event.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
index 60a2266..7ce94b9 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
index 0e1bec150..faab2f96 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
index 93f9601..4c21fff 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_WORKER_SCHEDULER_H_
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "platform/PlatformExport.h"
 #include "platform/scheduler/child/worker_scheduler.h"
 #include "public/platform/scheduler/child/single_thread_idle_task_runner.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
index d5311fc..e98ff07 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/callback.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/simple_test_tick_clock.h"
 #include "cc/test/ordered_simple_task_runner.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
index 0b252f7f..f4329de 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/time/tick_clock.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/task_queue_selector.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
index edef613..c71ab80 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "cc/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/lazy_now.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_base.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_base.cc
index 7236771..888ecc8 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_base.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_base.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/pending_task.h"
 #include "base/threading/platform_thread.h"
 #include "platform/scheduler/child/compositor_worker_scheduler.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
index fd28795..d2722af1 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEBTHREAD_IMPL_FOR_WORKER_SCHEDULER_H_
 
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "public/platform/WebPrivatePtr.h"
 #include "public/platform/scheduler/child/webthread_base.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
index 1a895af..adefd56 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_IMPL_H_
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "platform/scheduler/base/task_time_observer.h"
 #include "platform/scheduler/base/thread_load_tracker.h"
 #include "platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
index aa0fbfc9..0f3570db 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -8,6 +8,7 @@
 #include "base/atomicops.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/synchronization/lock.h"
 #include "base/trace_event/trace_log.h"
 #include "device/base/synchronization/shared_memory_seqlock_buffer.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index 0d2c1fb..5645568 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/callback.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/simple_test_tick_clock.h"
 #include "cc/output/begin_frame_args.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
index f9cf3f9..b5020de 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEBTHREAD_IMPL_FOR_RENDERER_SCHEDULER_H_
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEBTHREAD_IMPL_FOR_RENDERER_SCHEDULER_H_
 
+#include "base/message_loop/message_loop.h"
 #include "platform/PlatformExport.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/scheduler/child/webthread_base.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
index aa75bed..f57a222 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -9,16 +9,17 @@
 #include "base/location.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/test/simple_test_tick_clock.h"
+#include "platform/WebTaskRunner.h"
 #include "platform/scheduler/base/test_time_source.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
+#include "public/platform/WebTraceLocation.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "platform/WebTaskRunner.h"
-#include "public/platform/WebTraceLocation.h"
 
 namespace blink {
 namespace scheduler {
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
index 78f7640..d5dbe47b 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_renderer_scheduler.cc
@@ -4,6 +4,7 @@
 
 #include "public/platform/scheduler/test/fake_renderer_scheduler.h"
 
+#include "base/message_loop/message_loop.h"
 #include "public/platform/WebThread.h"
 
 namespace blink {
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 40eb97c..a84fe5c 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -200,6 +200,12 @@
     NOTREACHED();
     return scrollbar_point;
   }
+  virtual IntPoint ConvertFromRootFrame(
+      const IntPoint& point_in_root_frame) const {
+    NOTREACHED();
+    return point_in_root_frame;
+  }
+
   virtual Scrollbar* HorizontalScrollbar() const { return nullptr; }
   virtual Scrollbar* VerticalScrollbar() const { return nullptr; }
 
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
index 774f3df..4c6c488 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
@@ -63,8 +63,7 @@
                     &Scrollbar::AutoscrollTimerFired),
       elastic_overscroll_(0),
       track_needs_repaint_(true),
-      thumb_needs_repaint_(true),
-      parent_(nullptr) {
+      thumb_needs_repaint_(true) {
   theme_.RegisterScrollbar(*this);
 
   // FIXME: This is ugly and would not be necessary if we fix cross-platform
@@ -87,7 +86,6 @@
 DEFINE_TRACE(Scrollbar) {
   visitor->Trace(scrollable_area_);
   visitor->Trace(chrome_client_);
-  visitor->Trace(parent_);
 }
 
 void Scrollbar::SetFrameRect(const IntRect& frame_rect) {
@@ -575,12 +573,11 @@
 
 IntPoint Scrollbar::ConvertFromRootFrame(
     const IntPoint& point_in_root_frame) const {
-  if (const FrameViewBase* parent = Parent()) {
-    IntPoint parent_point = parent->ConvertFromRootFrame(point_in_root_frame);
-    if (scrollable_area_) {
-      return scrollable_area_->ConvertFromContainingFrameViewBaseToScrollbar(
-          *this, parent_point);
-    }
+  if (scrollable_area_) {
+    IntPoint parent_point =
+        scrollable_area_->ConvertFromRootFrame(point_in_root_frame);
+    return scrollable_area_->ConvertFromContainingFrameViewBaseToScrollbar(
+        *this, parent_point);
   }
 
   return point_in_root_frame;
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.h b/third_party/WebKit/Source/platform/scroll/Scrollbar.h
index ecb2b7bc..f11149f 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.h
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.h
@@ -26,7 +26,6 @@
 #ifndef Scrollbar_h
 #define Scrollbar_h
 
-#include "platform/FrameViewBase.h"
 #include "platform/Timer.h"
 #include "platform/graphics/paint/DisplayItem.h"
 #include "platform/heap/Handle.h"
@@ -75,9 +74,6 @@
   IntSize Size() const override { return frame_rect_.Size(); }
   IntPoint Location() const override { return frame_rect_.Location(); }
 
-  virtual void SetParent(FrameViewBase* parent) { parent_ = parent; }
-  FrameViewBase* Parent() const { return parent_; }
-
   void SetFrameRect(const IntRect&);
   IntRect FrameRect() const override { return frame_rect_; }
 
@@ -85,8 +81,7 @@
   void GetTickmarks(Vector<IntRect>&) const override;
   bool IsScrollableAreaActive() const override;
 
-  IntPoint ConvertFromRootFrame(
-      const IntPoint& point_in_root_frame) const override;
+  IntPoint ConvertFromRootFrame(const IntPoint&) const override;
 
   bool IsCustomScrollbar() const override { return false; }
   ScrollbarOrientation Orientation() const override { return orientation_; }
@@ -117,7 +112,7 @@
   // Will trigger paint invalidation if required.
   void OffsetDidChange();
 
-  void DisconnectFromScrollableArea();
+  virtual void DisconnectFromScrollableArea();
   ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
 
   int PressedPos() const { return pressed_pos_; }
@@ -252,7 +247,6 @@
   bool track_needs_repaint_;
   bool thumb_needs_repaint_;
   LayoutRect visual_rect_;
-  Member<FrameViewBase> parent_;
   IntRect frame_rect_;
 };
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
index 45075f2..b6bc8f1 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
@@ -54,8 +54,7 @@
   virtual void GetTickmarks(Vector<IntRect>&) const = 0;
   virtual bool IsScrollableAreaActive() const = 0;
 
-  virtual IntPoint ConvertFromRootFrame(
-      const IntPoint& point_in_root_frame) const = 0;
+  virtual IntPoint ConvertFromRootFrame(const IntPoint&) const = 0;
 
   virtual bool IsCustomScrollbar() const = 0;
   virtual ScrollbarOrientation Orientation() const = 0;
diff --git a/third_party/WebKit/Source/platform/wtf/OWNERS b/third_party/WebKit/Source/platform/wtf/OWNERS
index 45bef0a..a9fd1294 100644
--- a/third_party/WebKit/Source/platform/wtf/OWNERS
+++ b/third_party/WebKit/Source/platform/wtf/OWNERS
@@ -1,5 +1,4 @@
 erik.corry@gmail.com
-esprehn@chromium.org
 haraken@chromium.org
 jochen@chromium.org
 mikhail.pozdnyakov@intel.com
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index d600f48..d5a93ed 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -136,6 +136,8 @@
     "WebExport.h",
     "WebFormControlElement.cpp",
     "WebFormElement.cpp",
+    "WebFormElementObserverImpl.cpp",
+    "WebFormElementObserverImpl.h",
     "WebFrame.cpp",
     "WebFrameClient.cpp",
     "WebFrameContentDumper.cpp",
diff --git a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
index f5151fa2..44b0de5c 100644
--- a/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ContextMenuClientImpl.cpp
@@ -60,7 +60,6 @@
 #include "core/page/ContextMenuController.h"
 #include "core/page/Page.h"
 #include "platform/ContextMenu.h"
-#include "platform/FrameViewBase.h"
 #include "platform/exported/WrappedResourceResponse.h"
 #include "platform/text/TextBreakIterator.h"
 #include "platform/weborigin/KURL.h"
@@ -402,6 +401,19 @@
     data.input_field_type = WebContextMenuData::kInputFieldTypeNone;
   }
 
+  WebRect focus_webrect;
+  WebRect anchor_webrect;
+  web_view_->SelectionBounds(focus_webrect, anchor_webrect);
+
+  int left = std::min(focus_webrect.x, anchor_webrect.x);
+  int top = std::min(focus_webrect.y, anchor_webrect.y);
+  int right = std::max(focus_webrect.x + focus_webrect.width,
+                       anchor_webrect.x + anchor_webrect.width);
+  int bottom = std::max(focus_webrect.y + focus_webrect.height,
+                        anchor_webrect.y + anchor_webrect.height);
+
+  data.selection_rect = WebRect(left, top, right - left, bottom - top);
+
   if (from_touch && !ShouldShowContextMenuFromTouch(data))
     return false;
 
diff --git a/third_party/WebKit/Source/web/OWNERS b/third_party/WebKit/Source/web/OWNERS
index b2c551c..bfa525a 100644
--- a/third_party/WebKit/Source/web/OWNERS
+++ b/third_party/WebKit/Source/web/OWNERS
@@ -3,7 +3,6 @@
 dcheng@chromium.org
 dglazkov@chromium.org
 dgozman@chromium.org
-esprehn@chromium.org
 haraken@chromium.org
 japhet@chromium.org
 jochen@chromium.org
diff --git a/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp b/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
new file mode 100644
index 0000000..37a1270
--- /dev/null
+++ b/third_party/WebKit/Source/web/WebFormElementObserverImpl.cpp
@@ -0,0 +1,150 @@
+// 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 "web/WebFormElementObserverImpl.h"
+
+#include "core/css/CSSComputedStyleDeclaration.h"
+#include "core/dom/MutationCallback.h"
+#include "core/dom/MutationObserver.h"
+#include "core/dom/MutationObserverInit.h"
+#include "core/dom/MutationRecord.h"
+#include "core/dom/StaticNodeList.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFormElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "public/web/WebFormElement.h"
+#include "public/web/WebInputElement.h"
+#include "public/web/modules/password_manager/WebFormElementObserverCallback.h"
+
+namespace blink {
+
+class WebFormElementObserverImpl::ObserverCallback : public MutationCallback {
+ public:
+  ObserverCallback(HTMLElement&,
+                   std::unique_ptr<WebFormElementObserverCallback>);
+  DECLARE_VIRTUAL_TRACE();
+
+  ExecutionContext* GetExecutionContext() const override;
+
+  void Disconnect();
+
+ private:
+  void Call(const HeapVector<Member<MutationRecord>>& records,
+            MutationObserver*) override;
+
+  Member<HTMLElement> element_;
+  Member<MutationObserver> mutation_observer_;
+  std::unique_ptr<WebFormElementObserverCallback> callback_;
+};
+
+WebFormElementObserverImpl::ObserverCallback::ObserverCallback(
+    HTMLElement& element,
+    std::unique_ptr<WebFormElementObserverCallback> callback)
+    : element_(&element), callback_(std::move(callback)) {
+  DCHECK(element.ownerDocument());
+  mutation_observer_ = MutationObserver::Create(this);
+
+  {
+    Vector<String> filter;
+    filter.ReserveCapacity(3);
+    filter.push_back(String("action"));
+    filter.push_back(String("class"));
+    filter.push_back(String("style"));
+    MutationObserverInit init;
+    init.setAttributes(true);
+    init.setAttributeFilter(filter);
+    mutation_observer_->observe(element_, init, ASSERT_NO_EXCEPTION);
+  }
+  {
+    MutationObserverInit init;
+    init.setChildList(true);
+    mutation_observer_->observe(element_->parentElement(), init,
+                                ASSERT_NO_EXCEPTION);
+  }
+}
+
+ExecutionContext*
+WebFormElementObserverImpl::ObserverCallback::GetExecutionContext() const {
+  return element_->ownerDocument();
+}
+
+void WebFormElementObserverImpl::ObserverCallback::Disconnect() {
+  mutation_observer_->disconnect();
+  callback_.reset();
+}
+
+void WebFormElementObserverImpl::ObserverCallback::Call(
+    const HeapVector<Member<MutationRecord>>& records,
+    MutationObserver*) {
+  for (const auto& record : records) {
+    if (record->type() == "childList") {
+      for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
+        if (record->removedNodes()->item(i) != element_)
+          continue;
+        callback_->ElementWasHiddenOrRemoved();
+        Disconnect();
+        return;
+      }
+    } else {
+      HTMLElement& element = *ToHTMLElement(record->target());
+      if (record->attributeName() == "action") {
+        // If the action was modified, we just assume that the form as
+        // submitted.
+        callback_->ElementWasHiddenOrRemoved();
+        Disconnect();
+        return;
+      }
+      // Otherwise, either "style" or "class" was modified. Check the
+      // computed style.
+      CSSComputedStyleDeclaration* style =
+          CSSComputedStyleDeclaration::Create(&element);
+      if (style->GetPropertyValue(CSSPropertyDisplay) == "none") {
+        callback_->ElementWasHiddenOrRemoved();
+        Disconnect();
+        return;
+      }
+    }
+  }
+}
+
+DEFINE_TRACE(WebFormElementObserverImpl::ObserverCallback) {
+  visitor->Trace(element_);
+  visitor->Trace(mutation_observer_);
+  MutationCallback::Trace(visitor);
+}
+
+WebFormElementObserver* WebFormElementObserver::Create(
+    WebFormElement& element,
+    std::unique_ptr<WebFormElementObserverCallback> callback) {
+  return new WebFormElementObserverImpl(*element.Unwrap<HTMLFormElement>(),
+                                        std::move(callback));
+}
+
+WebFormElementObserver* WebFormElementObserver::Create(
+    WebInputElement& element,
+    std::unique_ptr<WebFormElementObserverCallback> callback) {
+  return new WebFormElementObserverImpl(*element.Unwrap<HTMLInputElement>(),
+                                        std::move(callback));
+}
+
+WebFormElementObserverImpl::WebFormElementObserverImpl(
+    HTMLElement& element,
+    std::unique_ptr<WebFormElementObserverCallback> callback)
+    : self_keep_alive_(this) {
+  mutation_callback_ = new ObserverCallback(element, std::move(callback));
+}
+
+WebFormElementObserverImpl::~WebFormElementObserverImpl() {}
+
+void WebFormElementObserverImpl::Disconnect() {
+  mutation_callback_->Disconnect();
+  mutation_callback_ = nullptr;
+  self_keep_alive_.Clear();
+}
+
+DEFINE_TRACE(WebFormElementObserverImpl) {
+  visitor->Trace(mutation_callback_);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/web/WebFormElementObserverImpl.h b/third_party/WebKit/Source/web/WebFormElementObserverImpl.h
new file mode 100644
index 0000000..e6a734b
--- /dev/null
+++ b/third_party/WebKit/Source/web/WebFormElementObserverImpl.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebFormElementObserverImpl_h
+#define WebFormElementObserverImpl_h
+
+#include "platform/heap/HeapAllocator.h"
+#include "platform/heap/Member.h"
+#include "platform/heap/SelfKeepAlive.h"
+#include "platform/wtf/Compiler.h"
+#include "public/web/modules/password_manager/WebFormElementObserver.h"
+#include "web/WebExport.h"
+
+namespace blink {
+
+class HTMLElement;
+class WebFormElementObserverCallback;
+
+class WEB_EXPORT WebFormElementObserverImpl final
+    : public GarbageCollectedFinalized<WebFormElementObserverImpl>,
+      NON_EXPORTED_BASE(public WebFormElementObserver) {
+  WTF_MAKE_NONCOPYABLE(WebFormElementObserverImpl);
+
+ public:
+  WebFormElementObserverImpl(HTMLElement&,
+                             std::unique_ptr<WebFormElementObserverCallback>);
+  ~WebFormElementObserverImpl() override;
+
+  // WebFormElementObserver implementation.
+  void Disconnect() override;
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  class ObserverCallback;
+
+  Member<ObserverCallback> mutation_callback_;
+
+  // WebFormElementObserverImpl must remain alive until Disconnect() is called.
+  SelfKeepAlive<WebFormElementObserverImpl> self_keep_alive_;
+};
+
+}  // namespace blink
+
+#endif  // WebFormElementObserverImpl_h
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index 35ef848..cddba83c 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -1218,16 +1218,31 @@
   MoveRangeSelection(base_in_viewport, extent_in_viewport);
 }
 
-void WebLocalFrameImpl::SelectRange(const WebRange& web_range) {
+void WebLocalFrameImpl::SelectRange(
+    const WebRange& web_range,
+    HandleVisibilityBehavior handle_visibility_behavior) {
   TRACE_EVENT0("blink", "WebLocalFrameImpl::selectRange");
 
   // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
   // needs to be audited.  see http://crbug.com/590369 for more details.
   GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
 
-  GetFrame()->Selection().SetSelectedRange(
-      web_range.CreateEphemeralRange(GetFrame()), VP_DEFAULT_AFFINITY,
-      SelectionDirectionalMode::kNonDirectional, kNotUserTriggered);
+  const EphemeralRange& range = web_range.CreateEphemeralRange(GetFrame());
+  if (range.IsNull())
+    return;
+
+  FrameSelection& selection = GetFrame()->Selection();
+  const bool show_handles =
+      handle_visibility_behavior == kShowSelectionHandle ||
+      (handle_visibility_behavior == kPreserveHandleVisibility &&
+       selection.IsHandleVisible());
+  selection.SetSelection(SelectionInDOMTree::Builder()
+                             .SetBaseAndExtent(range)
+                             .SetAffinity(VP_DEFAULT_AFFINITY)
+                             .SetIsHandleVisible(show_handles)
+                             .SetIsDirectional(false)
+                             .Build(),
+                         kNotUserTriggered);
 }
 
 WebString WebLocalFrameImpl::RangeAsText(const WebRange& web_range) {
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index 9e94c5cc8..70f0c3b5 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -193,7 +193,8 @@
   WebString SelectionAsMarkup() const override;
   bool SelectWordAroundCaret() override;
   void SelectRange(const WebPoint& base, const WebPoint& extent) override;
-  void SelectRange(const WebRange&) override;
+  void SelectRange(const WebRange&,
+                   HandleVisibilityBehavior = kHideSelectionHandle) override;
   WebString RangeAsText(const WebRange&) override;
   void MoveRangeSelectionExtent(const WebPoint&) override;
   void MoveRangeSelection(
diff --git a/third_party/WebKit/Source/web/WebNode.cpp b/third_party/WebKit/Source/web/WebNode.cpp
index 390399c..12105550 100644
--- a/third_party/WebKit/Source/web/WebNode.cpp
+++ b/third_party/WebKit/Source/web/WebNode.cpp
@@ -47,7 +47,6 @@
 #include "core/layout/LayoutPart.h"
 #include "modules/accessibility/AXObject.h"
 #include "modules/accessibility/AXObjectCacheImpl.h"
-#include "platform/FrameViewBase.h"
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/WebString.h"
 #include "public/web/WebAXObject.h"
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index b5779391..3c25672 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -5386,6 +5386,70 @@
               selection_string == "Some offscreen test text for testing");
 }
 
+TEST_P(ParameterizedWebFrameTest, SelectRangeDefaultHandleVisibility) {
+  RegisterMockedHttpURLLoad("select_range_basic.html");
+
+  FrameTestHelpers::WebViewHelper web_view_helper;
+  InitializeTextSelectionWebView(base_url_ + "select_range_basic.html",
+                                 &web_view_helper);
+
+  WebLocalFrameImpl* frame = web_view_helper.WebView()->MainFrameImpl();
+  frame->SelectRange(WebRange(0, 5));
+  EXPECT_FALSE(frame->SelectionRange().IsNull());
+
+  EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
+      << "By default selection handles should not be visible";
+}
+
+TEST_P(ParameterizedWebFrameTest, SelectRangeHideHandle) {
+  RegisterMockedHttpURLLoad("select_range_basic.html");
+
+  FrameTestHelpers::WebViewHelper web_view_helper;
+  InitializeTextSelectionWebView(base_url_ + "select_range_basic.html",
+                                 &web_view_helper);
+
+  WebLocalFrameImpl* frame = web_view_helper.WebView()->MainFrameImpl();
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle);
+
+  EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
+      << "Selection handle should not be visible with kHideSelectionHandle";
+}
+
+TEST_P(ParameterizedWebFrameTest, SelectRangeShowHandle) {
+  RegisterMockedHttpURLLoad("select_range_basic.html");
+
+  FrameTestHelpers::WebViewHelper web_view_helper;
+  InitializeTextSelectionWebView(base_url_ + "select_range_basic.html",
+                                 &web_view_helper);
+
+  WebLocalFrameImpl* frame = web_view_helper.WebView()->MainFrameImpl();
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle);
+
+  EXPECT_TRUE(frame->GetFrame()->Selection().IsHandleVisible())
+      << "Selection handle should be visible with kShowSelectionHandle";
+}
+
+TEST_P(ParameterizedWebFrameTest, SelectRangePreserveHandleVisibility) {
+  RegisterMockedHttpURLLoad("select_range_basic.html");
+
+  FrameTestHelpers::WebViewHelper web_view_helper;
+  InitializeTextSelectionWebView(base_url_ + "select_range_basic.html",
+                                 &web_view_helper);
+
+  WebLocalFrameImpl* frame = web_view_helper.WebView()->MainFrameImpl();
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kHideSelectionHandle);
+  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility);
+
+  EXPECT_FALSE(frame->GetFrame()->Selection().IsHandleVisible())
+      << "kPreserveHandleVisibility should keep handles invisible";
+
+  frame->SelectRange(WebRange(0, 5), WebLocalFrame::kShowSelectionHandle);
+  frame->SelectRange(WebRange(0, 6), WebLocalFrame::kPreserveHandleVisibility);
+
+  EXPECT_TRUE(frame->GetFrame()->Selection().IsHandleVisible())
+      << "kPreserveHandleVisibility should keep handles visible";
+}
+
 TEST_P(ParameterizedWebFrameTest, SelectRangeInIframe) {
   WebFrame* frame;
   WebRect start_web_rect;
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
index 5639c14..74547b9 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py
@@ -97,17 +97,16 @@
     def run(self, args):
         """Run the tests and return a RunDetails object with the results."""
         start_time = time.time()
-        self._printer.write_update("Collecting tests ...")
+        self._printer.write_update('Collecting tests ...')
         running_all_tests = False
 
-        self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...')
-
         try:
-            _log.info('run-webkit-tests - calling ensure_manifest')
+            self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...')
             WPTManifest.ensure_manifest(self._port.host)
         finally:
-            _log.info('run-webkit-tests - completed ensure_manfiest')
+            self._printer.write_update('Completed generating manifest.')
 
+        self._printer.write_update('Collecting tests ...')
         try:
             paths, all_test_names, running_all_tests = self._collect_tests(args)
         except IOError:
@@ -196,12 +195,12 @@
 
         # Some crash logs can take a long time to be written out so look
         # for new logs after the test run finishes.
-        self._printer.write_update("looking for new crash logs")
+        self._printer.write_update('Looking for new crash logs ...')
         self._look_for_new_crash_logs(initial_results, start_time)
         for retry_attempt_results in all_retry_results:
             self._look_for_new_crash_logs(retry_attempt_results, start_time)
 
-        _log.debug("summarizing results")
+        self._printer.write_update('Summarizing results ...')
         summarized_full_results = test_run_results.summarize_results(
             self._port, self._expectations, initial_results, all_retry_results,
             enabled_pixel_tests_in_retry)
@@ -450,7 +449,7 @@
 
     def _clobber_old_results(self):
         dir_above_results_path = self._filesystem.dirname(self._results_directory)
-        self._printer.write_update("Clobbering old results in %s" % dir_above_results_path)
+        self._printer.write_update('Clobbering old results in %s.' % dir_above_results_path)
         if not self._filesystem.exists(dir_above_results_path):
             return
         file_list = self._filesystem.listdir(dir_above_results_path)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
index ea47086..d5d9bbc 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
@@ -201,7 +201,8 @@
             matching_value_keys = set()
         return merged_dict
 
-    def get_expectations(self, results):
+    def get_expectations(self, results, test_name=''):
+
         """Returns a set of test expectations to use based on results.
 
         Returns a set of one or more test expectations based on the expected
@@ -217,11 +218,21 @@
                         'bug': 'crbug.com/11111'
                     }
                 }
+            test_name: The test name string (optional).
 
         Returns:
             A set of one or more test expectation strings with the first letter
             capitalized. Example: set(['Failure', 'Timeout']).
         """
+        # If the result is MISSING, this implies that the test was not
+        # rebaselined and has an actual result but no baseline. We can't
+        # add a Missing expectation (this is not allowed), but no other
+        # expectation is correct.
+        # We also want to skip any new manual tests that are not automated;
+        # see crbug.com/708241 for context.
+        if (results['actual'] == 'MISSING' or
+                '-manual.' in test_name and results['actual'] == 'TIMEOUT'):
+            return {'Skip'}
         expectations = set()
         failure_types = ('TEXT', 'IMAGE+TEXT', 'IMAGE', 'AUDIO')
         other_types = ('TIMEOUT', 'CRASH', 'PASS')
@@ -269,12 +280,8 @@
         if specifier_part:
             line_parts.append(specifier_part)
         line_parts.append(test_name)
+        line_parts.append('[ %s ]' % ' '.join(self.get_expectations(results, test_name)))
 
-        # Skip new manual tests; see crbug.com/708241 for context.
-        if '-manual.' in test_name and results['actual'] in ('MISSING', 'TIMEOUT'):
-            line_parts.append('[ Skip ]')
-        else:
-            line_parts.append('[ %s ]' % ' '.join(self.get_expectations(results)))
         return ' '.join(line_parts)
 
     def specifier_part(self, port_names, test_name):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
index 9b09e6f..4dd0d76 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
@@ -185,6 +185,12 @@
         self.assertEqual(
             updater.get_expectations({'expected': 'Pass', 'actual': 'IMAGE+TEXT IMAGE IMAGE'}),
             {'Failure'})
+        self.assertEqual(
+            updater.get_expectations({'expected': 'Pass', 'actual': 'MISSING'}),
+            {'Skip'})
+        self.assertEqual(
+            updater.get_expectations({'expected': 'Pass', 'actual': 'TIMEOUT'}, test_name='foo/bar-manual.html'),
+            {'Skip'})
 
     def test_create_line_list_old_tests(self):
         # In this example, there are two failures that are not in w3c tests.
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index c7c70638..2eb5a18 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -609,6 +609,8 @@
     "web/mac/WebScrollbarTheme.h",
     "web/mac/WebSubstringUtil.h",
     "web/mac/WebSubstringUtil.h",
+    "web/modules/password_manager/WebFormElementObserver.h",
+    "web/modules/password_manager/WebFormElementObserverCallback.h",
     "web/modules/serviceworker/WebServiceWorkerContextClient.h",
     "web/modules/serviceworker/WebServiceWorkerContextProxy.h",
     "web/win/WebFontRendering.h",
@@ -736,8 +738,6 @@
     "//url/mojo:url_mojom_origin",
   ]
 
-  component_output_prefix = "blink_mojo_bindings"
-
   # The chromium variant must be linked with content and use the same export
   # settings in component build because of the WebBluetoothDeviceId typemap
   # inside content.
@@ -770,8 +770,6 @@
     "//url/mojo:url_mojom_gurl",
   ]
 
-  component_output_prefix = "blink_android_mojo_bindings"
-
   # See comment above.
   export_class_attribute = "CONTENT_EXPORT"
   export_define = "CONTENT_IMPLEMENTATION=1"
@@ -797,8 +795,6 @@
     "//cc/ipc:interfaces",
   ]
 
-  component_output_prefix = "blink_offscreen_canvas_mojo_bindings"
-
   # See comment above
   export_class_attribute = "CONTENT_EXPORT"
   export_define = "CONTENT_IMPLEMENTATION=1"
diff --git a/third_party/WebKit/public/OWNERS b/third_party/WebKit/public/OWNERS
index 79efaa1..772c2e9c 100644
--- a/third_party/WebKit/public/OWNERS
+++ b/third_party/WebKit/public/OWNERS
@@ -3,7 +3,6 @@
 dcheng@chromium.org
 dglazkov@chromium.org
 dstockwell@chromium.org
-esprehn@chromium.org
 foolip@chromium.org
 haraken@chromium.org
 japhet@chromium.org
diff --git a/third_party/WebKit/public/platform/WebFeaturePolicy.h b/third_party/WebKit/public/platform/WebFeaturePolicy.h
index 95ac512..b73e971 100644
--- a/third_party/WebKit/public/platform/WebFeaturePolicy.h
+++ b/third_party/WebKit/public/platform/WebFeaturePolicy.h
@@ -6,57 +6,13 @@
 #define WebFeaturePolicy_h
 
 #include "WebCommon.h"
+#include "WebFeaturePolicyFeature.h"
 #include "WebSecurityOrigin.h"
 #include "WebString.h"
 #include "WebVector.h"
 
 namespace blink {
 
-// These values map to the features which can be controlled by Feature Policy.
-//
-// Features are defined in
-// https://wicg.github.io/feature-policy/#defined-features. Many of these are
-// still under development in blink behind the featurePolicyExperimentalFeatures
-// flag, see getWebFeaturePolicyFeature().
-enum class WebFeaturePolicyFeature {
-  kNotFound = 0,
-  // Controls access to video input devices.
-  kCamera,
-  // Controls whether navigator.requestMediaKeySystemAccess is allowed.
-  kEme,
-  // Controls whether Element.requestFullscreen is allowed.
-  kFullscreen,
-  // Controls access to Geolocation interface.
-  kGeolocation,
-  // Controls access to audio input devices.
-  kMicrophone,
-  // Controls access to requestMIDIAccess method.
-  kMidiFeature,
-  // Controls access to PaymentRequest interface.
-  kPayment,
-  // Controls access to audio output devices.
-  kSpeaker,
-  // Controls access to navigator.vibrate method.
-  kVibrate,
-  // Controls access to document.cookie attribute.
-  kDocumentCookie,
-  // Contols access to document.domain attribute.
-  kDocumentDomain,
-  // Controls access to document.write and document.writeln methods.
-  kDocumentWrite,
-  // Controls access to Notification interface.
-  kNotifications,
-  // Controls access to PushManager interface.
-  kPush,
-  // Controls whether synchronous script elements will run.
-  kSyncScript,
-  // Controls use of synchronous XMLHTTPRequest API.
-  kSyncXHR,
-  // Controls access to RTCPeerConnection interface.
-  kWebRTC,
-  LAST_FEATURE = kWebRTC
-};
-
 struct BLINK_PLATFORM_EXPORT WebParsedFeaturePolicyDeclaration {
   WebParsedFeaturePolicyDeclaration() : matches_all_origins(false) {}
   WebFeaturePolicyFeature feature;
diff --git a/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h b/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h
new file mode 100644
index 0000000..d400770c
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h
@@ -0,0 +1,59 @@
+// 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 WebFeaturePolicyFeature_h
+#define WebFeaturePolicyFeature_h
+
+namespace blink {
+
+// These values map to the features which can be controlled by Feature Policy.
+//
+// Features are defined in
+// https://wicg.github.io/feature-policy/#defined-features. Many of these are
+// still under development in blink behind the featurePolicyExperimentalFeatures
+// flag, see getWebFeaturePolicyFeature().
+enum class WebFeaturePolicyFeature {
+  kNotFound = 0,
+  // Controls access to video input devices.
+  kCamera,
+  // Controls whether navigator.requestMediaKeySystemAccess is allowed.
+  kEme,
+  // Controls whether Element.requestFullscreen is allowed.
+  kFullscreen,
+  // Controls access to Geolocation interface.
+  kGeolocation,
+  // Controls access to audio input devices.
+  kMicrophone,
+  // Controls access to requestMIDIAccess method.
+  kMidiFeature,
+  // Controls access to PaymentRequest interface.
+  kPayment,
+  // Controls access to audio output devices.
+  kSpeaker,
+  // Controls access to navigator.vibrate method.
+  kVibrate,
+  // Controls access to document.cookie attribute.
+  kDocumentCookie,
+  // Contols access to document.domain attribute.
+  kDocumentDomain,
+  // Controls access to document.write and document.writeln methods.
+  kDocumentWrite,
+  // Controls access to Notification interface.
+  kNotifications,
+  // Controls access to PushManager interface.
+  kPush,
+  // Controls whether synchronous script elements will run.
+  kSyncScript,
+  // Controls use of synchronous XMLHTTPRequest API.
+  kSyncXHR,
+  // Controls access to RTCPeerConnection interface.
+  kWebRTC,
+  // Controls access to the WebUSB API.
+  kUsb,
+  LAST_FEATURE = kUsb
+};
+
+}  // namespace blink
+
+#endif  // WebFeaturePolicyFeature_h
diff --git a/third_party/WebKit/public/platform/scheduler/child/webthread_base.h b/third_party/WebKit/public/platform/scheduler/child/webthread_base.h
index 76774e7..642fd8d 100644
--- a/third_party/WebKit/public/platform/scheduler/child/webthread_base.h
+++ b/third_party/WebKit/public/platform/scheduler/child/webthread_base.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <memory>
 
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "public/platform/WebCommon.h"
 #include "public/platform/WebThread.h"
diff --git a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
index c828f19..5ad57854 100644
--- a/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
+++ b/third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_TEST_FAKE_RENDERER_SCHEDULER_H_
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "public/platform/scheduler/renderer/renderer_scheduler.h"
 
 namespace blink {
diff --git a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
index 839747f0..57389f2 100644
--- a/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
+++ b/third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_WEBKIT_PUBLIC_PLATFORM_SCHEDULER_TEST_MOCK_RENDERER_SCHEDULER_H_
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "cc/output/begin_frame_args.h"
 #include "public/platform/WebThread.h"
 #include "public/platform/scheduler/renderer/renderer_scheduler.h"
diff --git a/third_party/WebKit/public/web/WebContextMenuData.h b/third_party/WebKit/public/web/WebContextMenuData.h
index e237751..d13c1997 100644
--- a/third_party/WebKit/public/web/WebContextMenuData.h
+++ b/third_party/WebKit/public/web/WebContextMenuData.h
@@ -39,6 +39,7 @@
 #include "../platform/WebVector.h"
 #include "WebHistoryItem.h"
 #include "WebMenuItemInfo.h"
+#include "public/platform/WebRect.h"
 
 #define WEBCONTEXT_MEDIATYPEFILE_DEFINED
 
@@ -189,6 +190,9 @@
   // Custom context menu items provided by the WebCore internals.
   WebVector<WebMenuItemInfo> custom_items;
 
+  // Selection in viewport coordinates.
+  WebRect selection_rect;
+
   WebContextMenuData()
       : media_type(kMediaTypeNone),
         has_image_contents(false),
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index 875b58ea..57adf3b 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -339,7 +339,17 @@
   // DEPRECATED: Use moveRangeSelection.
   virtual void SelectRange(const WebPoint& base, const WebPoint& extent) = 0;
 
-  virtual void SelectRange(const WebRange&) = 0;
+  enum HandleVisibilityBehavior {
+    // Hide handle(s) in the new selection.
+    kHideSelectionHandle,
+    // Show handle(s) in the new selection.
+    kShowSelectionHandle,
+    // Keep the current handle visibility.
+    kPreserveHandleVisibility,
+  };
+  virtual void SelectRange(const WebRange&,
+                           HandleVisibilityBehavior = kHideSelectionHandle) = 0;
+
   virtual WebString RangeAsText(const WebRange&) = 0;
 
   // Move the current selection to the provided viewport point/points. If the
diff --git a/third_party/WebKit/public/web/modules/password_manager/OWNERS b/third_party/WebKit/public/web/modules/password_manager/OWNERS
new file mode 100644
index 0000000..70f3bfc
--- /dev/null
+++ b/third_party/WebKit/public/web/modules/password_manager/OWNERS
@@ -0,0 +1,3 @@
+jochen@chromium.org
+
+# COMPONENT: UI>Browser>Passwords
diff --git a/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserver.h b/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserver.h
new file mode 100644
index 0000000..0bfd2de
--- /dev/null
+++ b/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserver.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebFormElementObserver_h
+#define WebFormElementObserver_h
+
+#include <memory>
+
+#include "public/platform/WebCommon.h"
+
+namespace blink {
+
+class WebFormElement;
+class WebFormElementObserverCallback;
+class WebInputElement;
+
+class BLINK_EXPORT WebFormElementObserver {
+ public:
+  // Creates a WebFormElementObserver. Delete this WebFormElementObsrver by
+  // calling WebFormElementObserver::Disconnect.
+  static WebFormElementObserver* Create(
+      WebFormElement&,
+      std::unique_ptr<WebFormElementObserverCallback>);
+  static WebFormElementObserver* Create(
+      WebInputElement&,
+      std::unique_ptr<WebFormElementObserverCallback>);
+
+  virtual void Disconnect() = 0;
+
+ protected:
+  WebFormElementObserver() = default;
+  virtual ~WebFormElementObserver() = default;
+};
+
+}  // namespace blink
+
+#endif  // WebFormElementObserver_h
diff --git a/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserverCallback.h b/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserverCallback.h
new file mode 100644
index 0000000..9b8637c4
--- /dev/null
+++ b/third_party/WebKit/public/web/modules/password_manager/WebFormElementObserverCallback.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebFormElementObserverCallback_h
+#define WebFormElementObserverCallback_h
+
+namespace blink {
+
+class WebFormElementObserverCallback {
+ public:
+  virtual ~WebFormElementObserverCallback() {}
+
+  // Invoked when the observed element was either removed from the DOM, it's
+  // action attribute changed, or it's computed style changed to display: none.
+  virtual void ElementWasHiddenOrRemoved() = 0;
+};
+
+}  // namespace blink
+
+#endif  // WebFormElementObserverCallback_h
diff --git a/third_party/android_platform/README.chromium b/third_party/android_platform/README.chromium
index c224644d..03f9651 100644
--- a/third_party/android_platform/README.chromium
+++ b/third_party/android_platform/README.chromium
@@ -42,6 +42,7 @@
     where relocations are packed.
 Added code to capture java stderr for better handling of native->java crashes.
 Fixed invalid using decl in logging header debug.h
+Only attempt to symbolize with ELF libraries.
 
 Android relocation packing tool details:
     Copy sources from AOSP bionic/tools/relocation_packer
diff --git a/third_party/android_platform/development/scripts/symbol.py b/third_party/android_platform/development/scripts/symbol.py
index 3d6ee67..469446ca 100755
--- a/third_party/android_platform/development/scripts/symbol.py
+++ b/third_party/android_platform/development/scripts/symbol.py
@@ -316,9 +316,15 @@
   Returns:
     A list of matching library filenames for library_name.
   """
+  def extant_library(filename):
+    if (os.path.exists(filename)
+        and elf_symbolizer.ContainsElfMagic(filename)):
+      return [filename]
+    return []
+
   candidates = GetCandidates(
       GetLibrarySearchPaths(), library_name,
-      lambda filename: filter(os.path.exists, [filename]))
+      extant_library)
   # For GN, candidates includes both stripped an unstripped libraries. Stripped
   # libraries are always newer. Explicitly look for .unstripped and sort them
   # ahead.
diff --git a/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc b/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc
index bd34c670..b0ebe299 100644
--- a/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc
+++ b/third_party/libaddressinput/chromium/chrome_metadata_source_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/url_request/test_url_fetcher_factory.h"
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 8450385..67a410a 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Saturday May 06 2017
+Date: Friday May 12 2017
 Branch: master
-Commit: f4653c1efc0a8d758195572de34ae05271453d93
+Commit: ac8f58f6ab73fea7948f40eaf608f832964d8a58
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni
index 085e67e..0a0291a 100644
--- a/third_party/libvpx/libvpx_srcs.gni
+++ b/third_party/libvpx/libvpx_srcs.gni
@@ -324,7 +324,9 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_dct32x32_impl_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_impl_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_sse2.h",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_inv_txfm_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/inv_txfm_sse2.h",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/transpose_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/txfm_common_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_asm_stubs.c",
   "//third_party/libvpx/source/libvpx/vpx_mem/include/vpx_mem_intrnl.h",
@@ -415,6 +417,10 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_intrin_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_pred_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct16x16_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct32x32_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct4x4_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct8x8_add_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_loopfilter_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_quantize_intrin_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_variance_sse2.c",
@@ -769,7 +775,9 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_dct32x32_impl_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_impl_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_sse2.h",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_inv_txfm_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/inv_txfm_sse2.h",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/transpose_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/txfm_common_sse2.h",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_asm_stubs.c",
   "//third_party/libvpx/source/libvpx/vpx_mem/include/vpx_mem_intrnl.h",
@@ -867,6 +875,10 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_intrin_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_pred_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct16x16_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct32x32_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct4x4_add_sse2.c",
+  "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_idct8x8_add_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_loopfilter_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_quantize_intrin_sse2.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_variance_sse2.c",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vp9_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vp9_rtcd.h
index e9c8af5..6387bc8c 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vp9_rtcd.h
@@ -86,7 +86,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
index 6d96087..ef89dd1f 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
@@ -676,20 +676,24 @@
 #define vpx_sub_pixel_variance16x16 vpx_sub_pixel_variance16x16_neon
 
 uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_c
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_neon
 
 uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_c
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_neon
 
 uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_c
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_neon
 
 uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance32x32 vpx_sub_pixel_variance32x32_neon
 
 uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_c
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
@@ -698,17 +702,20 @@
 #define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_c
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_neon
 
 uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance64x64 vpx_sub_pixel_variance64x64_neon
 
 uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_c
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_neon
 
 uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_c
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_neon
 
 uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -758,14 +765,16 @@
 #define vpx_variance16x16 vpx_variance16x16_neon
 
 unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance16x32 vpx_variance16x32_c
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x32 vpx_variance16x32_neon
 
 unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 #define vpx_variance16x8 vpx_variance16x8_neon
 
 unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance32x16 vpx_variance32x16_c
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x16 vpx_variance32x16_neon
 
 unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -794,7 +803,8 @@
 #define vpx_variance8x16 vpx_variance8x16_neon
 
 unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance8x4 vpx_variance8x4_c
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x4 vpx_variance8x4_neon
 
 unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h
index e9c8af5..6387bc8c 100644
--- a/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm64/vp9_rtcd.h
@@ -86,7 +86,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
index 6d96087..ef89dd1f 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -676,20 +676,24 @@
 #define vpx_sub_pixel_variance16x16 vpx_sub_pixel_variance16x16_neon
 
 uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_c
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_neon
 
 uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_c
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_neon
 
 uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_c
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_neon
 
 uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance32x32 vpx_sub_pixel_variance32x32_neon
 
 uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_c
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
@@ -698,17 +702,20 @@
 #define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_c
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_neon
 
 uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance64x64 vpx_sub_pixel_variance64x64_neon
 
 uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_c
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_neon
 
 uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_c
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_neon
 
 uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -758,14 +765,16 @@
 #define vpx_variance16x16 vpx_variance16x16_neon
 
 unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance16x32 vpx_variance16x32_c
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x32 vpx_variance16x32_neon
 
 unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 #define vpx_variance16x8 vpx_variance16x8_neon
 
 unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance32x16 vpx_variance32x16_c
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x16 vpx_variance32x16_neon
 
 unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -794,7 +803,8 @@
 #define vpx_variance8x16 vpx_variance8x16_neon
 
 unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance8x4 vpx_variance8x4_c
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x4 vpx_variance8x4_neon
 
 unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vp9_rtcd.h
index 90d5406..84711ac 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vp9_rtcd.h
@@ -86,7 +86,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
index f8e4136..45cc943 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -676,20 +676,24 @@
 RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance16x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_c
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance16x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_c
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance16x8)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_c
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance32x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance32x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_c
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance32x64)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
@@ -698,17 +702,20 @@
 #define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_c
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance64x32)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance64x64)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_c
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance8x16)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_c
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+RTCD_EXTERN uint32_t (*vpx_sub_pixel_variance8x4)(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 
 uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -758,14 +765,16 @@
 RTCD_EXTERN unsigned int (*vpx_variance16x16)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance16x32 vpx_variance16x32_c
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+RTCD_EXTERN unsigned int (*vpx_variance16x32)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 RTCD_EXTERN unsigned int (*vpx_variance16x8)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance32x16 vpx_variance32x16_c
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+RTCD_EXTERN unsigned int (*vpx_variance32x16)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -794,7 +803,8 @@
 RTCD_EXTERN unsigned int (*vpx_variance8x16)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance8x4 vpx_variance8x4_c
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+RTCD_EXTERN unsigned int (*vpx_variance8x4)(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 
 unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -997,10 +1007,24 @@
     if (flags & HAS_NEON) vpx_satd = vpx_satd_neon;
     vpx_sub_pixel_variance16x16 = vpx_sub_pixel_variance16x16_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance16x16 = vpx_sub_pixel_variance16x16_neon;
+    vpx_sub_pixel_variance16x32 = vpx_sub_pixel_variance16x32_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance16x32 = vpx_sub_pixel_variance16x32_neon;
+    vpx_sub_pixel_variance16x8 = vpx_sub_pixel_variance16x8_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance16x8 = vpx_sub_pixel_variance16x8_neon;
+    vpx_sub_pixel_variance32x16 = vpx_sub_pixel_variance32x16_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance32x16 = vpx_sub_pixel_variance32x16_neon;
     vpx_sub_pixel_variance32x32 = vpx_sub_pixel_variance32x32_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance32x32 = vpx_sub_pixel_variance32x32_neon;
+    vpx_sub_pixel_variance32x64 = vpx_sub_pixel_variance32x64_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance32x64 = vpx_sub_pixel_variance32x64_neon;
+    vpx_sub_pixel_variance64x32 = vpx_sub_pixel_variance64x32_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance64x32 = vpx_sub_pixel_variance64x32_neon;
     vpx_sub_pixel_variance64x64 = vpx_sub_pixel_variance64x64_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance64x64 = vpx_sub_pixel_variance64x64_neon;
+    vpx_sub_pixel_variance8x16 = vpx_sub_pixel_variance8x16_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance8x16 = vpx_sub_pixel_variance8x16_neon;
+    vpx_sub_pixel_variance8x4 = vpx_sub_pixel_variance8x4_c;
+    if (flags & HAS_NEON) vpx_sub_pixel_variance8x4 = vpx_sub_pixel_variance8x4_neon;
     vpx_sub_pixel_variance8x8 = vpx_sub_pixel_variance8x8_c;
     if (flags & HAS_NEON) vpx_sub_pixel_variance8x8 = vpx_sub_pixel_variance8x8_neon;
     vpx_subtract_block = vpx_subtract_block_c;
@@ -1023,8 +1047,12 @@
     if (flags & HAS_NEON) vpx_v_predictor_8x8 = vpx_v_predictor_8x8_neon;
     vpx_variance16x16 = vpx_variance16x16_c;
     if (flags & HAS_NEON) vpx_variance16x16 = vpx_variance16x16_neon;
+    vpx_variance16x32 = vpx_variance16x32_c;
+    if (flags & HAS_NEON) vpx_variance16x32 = vpx_variance16x32_neon;
     vpx_variance16x8 = vpx_variance16x8_c;
     if (flags & HAS_NEON) vpx_variance16x8 = vpx_variance16x8_neon;
+    vpx_variance32x16 = vpx_variance32x16_c;
+    if (flags & HAS_NEON) vpx_variance32x16 = vpx_variance32x16_neon;
     vpx_variance32x32 = vpx_variance32x32_c;
     if (flags & HAS_NEON) vpx_variance32x32 = vpx_variance32x32_neon;
     vpx_variance32x64 = vpx_variance32x64_c;
@@ -1035,6 +1063,8 @@
     if (flags & HAS_NEON) vpx_variance64x64 = vpx_variance64x64_neon;
     vpx_variance8x16 = vpx_variance8x16_c;
     if (flags & HAS_NEON) vpx_variance8x16 = vpx_variance8x16_neon;
+    vpx_variance8x4 = vpx_variance8x4_c;
+    if (flags & HAS_NEON) vpx_variance8x4 = vpx_variance8x4_neon;
     vpx_variance8x8 = vpx_variance8x8_c;
     if (flags & HAS_NEON) vpx_variance8x8 = vpx_variance8x8_neon;
     vpx_vector_var = vpx_vector_var_c;
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vp9_rtcd.h
index e9c8af5..6387bc8c 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vp9_rtcd.h
@@ -86,7 +86,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
index 6d96087..ef89dd1f 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -676,20 +676,24 @@
 #define vpx_sub_pixel_variance16x16 vpx_sub_pixel_variance16x16_neon
 
 uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_c
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_neon
 
 uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_c
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_neon
 
 uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_c
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_neon
 
 uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance32x32 vpx_sub_pixel_variance32x32_neon
 
 uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_c
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
@@ -698,17 +702,20 @@
 #define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_c
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_neon
 
 uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance64x64 vpx_sub_pixel_variance64x64_neon
 
 uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_c
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_neon
 
 uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_c
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_neon
 
 uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -758,14 +765,16 @@
 #define vpx_variance16x16 vpx_variance16x16_neon
 
 unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance16x32 vpx_variance16x32_c
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x32 vpx_variance16x32_neon
 
 unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 #define vpx_variance16x8 vpx_variance16x8_neon
 
 unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance32x16 vpx_variance32x16_c
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x16 vpx_variance32x16_neon
 
 unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -794,7 +803,8 @@
 #define vpx_variance8x16 vpx_variance8x16_neon
 
 unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance8x4 vpx_variance8x4_c
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x4 vpx_variance8x4_neon
 
 unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/linux/arm/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm/vp9_rtcd.h
index 449ba32b..333fc72 100644
--- a/third_party/libvpx/source/config/linux/arm/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm/vp9_rtcd.h
@@ -80,7 +80,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h
index e9c8af5..6387bc8c 100644
--- a/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vp9_rtcd.h
@@ -86,7 +86,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
index 6d96087..ef89dd1f 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -676,20 +676,24 @@
 #define vpx_sub_pixel_variance16x16 vpx_sub_pixel_variance16x16_neon
 
 uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_c
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_neon
 
 uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_c
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_neon
 
 uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_c
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_neon
 
 uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance32x32 vpx_sub_pixel_variance32x32_neon
 
 uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_c
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
 
 uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_c
@@ -698,17 +702,20 @@
 #define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_c
 
 uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_c
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_neon
 
 uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 #define vpx_sub_pixel_variance64x64 vpx_sub_pixel_variance64x64_neon
 
 uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_c
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_neon
 
 uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
-#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_c
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_neon
 
 uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
 uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
@@ -758,14 +765,16 @@
 #define vpx_variance16x16 vpx_variance16x16_neon
 
 unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance16x32 vpx_variance16x32_c
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x32 vpx_variance16x32_neon
 
 unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 #define vpx_variance16x8 vpx_variance16x8_neon
 
 unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance32x16 vpx_variance32x16_c
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x16 vpx_variance32x16_neon
 
 unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
@@ -794,7 +803,8 @@
 #define vpx_variance8x16 vpx_variance8x16_neon
 
 unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
-#define vpx_variance8x4 vpx_variance8x4_c
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x4 vpx_variance8x4_neon
 
 unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
 unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
diff --git a/third_party/libvpx/source/config/linux/generic/vp9_rtcd.h b/third_party/libvpx/source/config/linux/generic/vp9_rtcd.h
index 0ba5c37..92e3a02 100644
--- a/third_party/libvpx/source/config/linux/generic/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/generic/vp9_rtcd.h
@@ -80,13 +80,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -122,7 +122,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
index fa959b54..a09ed559 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
@@ -832,49 +832,49 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_c
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_256_add vpx_highbd_idct16x16_256_add_c
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_38_add vpx_highbd_idct16x16_38_add_c
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1_add vpx_highbd_idct32x32_1_add_c
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_c
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_c
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_64_add vpx_highbd_idct8x8_64_add_c
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/linux/ia32/vp9_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vp9_rtcd.h
index b12f3bd..23db87a 100644
--- a/third_party/libvpx/source/config/linux/ia32/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -141,9 +141,9 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
index 798b495..49450cda 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -1024,56 +1024,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/linux/mips64el/vp9_rtcd.h b/third_party/libvpx/source/config/linux/mips64el/vp9_rtcd.h
index 35327e2..c508c23 100644
--- a/third_party/libvpx/source/config/linux/mips64el/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mips64el/vp9_rtcd.h
@@ -80,7 +80,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/mipsel/vp9_rtcd.h b/third_party/libvpx/source/config/linux/mipsel/vp9_rtcd.h
index 35327e2..c508c23 100644
--- a/third_party/libvpx/source/config/linux/mipsel/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/mipsel/vp9_rtcd.h
@@ -80,7 +80,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/x64/vp9_rtcd.h b/third_party/libvpx/source/config/linux/x64/vp9_rtcd.h
index 5e72bb8..126071d 100644
--- a/third_party/libvpx/source/config/linux/x64/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -143,9 +143,9 @@
 void vp9_quantize_fp_32x32_ssse3(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 RTCD_EXTERN void (*vp9_quantize_fp_32x32)(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
index 6bab65e..b2403c3 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -1031,56 +1031,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_256_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_38_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1_add vpx_highbd_idct32x32_1_add_sse2
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_64_add vpx_highbd_idct8x8_64_add_sse2
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/mac/ia32/vp9_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vp9_rtcd.h
index b12f3bd..23db87a 100644
--- a/third_party/libvpx/source/config/mac/ia32/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -141,9 +141,9 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
index 798b495..49450cda 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -1024,56 +1024,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/mac/x64/vp9_rtcd.h b/third_party/libvpx/source/config/mac/x64/vp9_rtcd.h
index 5e72bb8..126071d 100644
--- a/third_party/libvpx/source/config/mac/x64/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -143,9 +143,9 @@
 void vp9_quantize_fp_32x32_ssse3(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 RTCD_EXTERN void (*vp9_quantize_fp_32x32)(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
index 6bab65e..b2403c3 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -1031,56 +1031,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_256_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_38_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1_add vpx_highbd_idct32x32_1_add_sse2
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_64_add vpx_highbd_idct8x8_64_add_sse2
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/nacl/vp9_rtcd.h b/third_party/libvpx/source/config/nacl/vp9_rtcd.h
index 0ba5c37..92e3a02 100644
--- a/third_party/libvpx/source/config/nacl/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/nacl/vp9_rtcd.h
@@ -80,13 +80,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -122,7 +122,7 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 #define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_c
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
index fa959b54..a09ed559 100644
--- a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
@@ -832,49 +832,49 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_c
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_256_add vpx_highbd_idct16x16_256_add_c
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_38_add vpx_highbd_idct16x16_38_add_c
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1_add vpx_highbd_idct32x32_1_add_c
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_c
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_c
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_64_add vpx_highbd_idct8x8_64_add_c
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index 57251a6..01c5af14 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  6
 #define VERSION_PATCH  1
-#define VERSION_EXTRA  "576-gf4653c1ef"
+#define VERSION_EXTRA  "620-gac8f58f6a"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.6.1-576-gf4653c1ef"
-#define VERSION_STRING      " v1.6.1-576-gf4653c1ef"
+#define VERSION_STRING_NOSP "v1.6.1-620-gac8f58f6a"
+#define VERSION_STRING      " v1.6.1-620-gac8f58f6a"
diff --git a/third_party/libvpx/source/config/win/ia32/vp9_rtcd.h b/third_party/libvpx/source/config/win/ia32/vp9_rtcd.h
index b12f3bd..23db87a 100644
--- a/third_party/libvpx/source/config/win/ia32/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -141,9 +141,9 @@
 void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 #define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_c
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
index 798b495..49450cda 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -1024,56 +1024,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_10_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_256_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct16x16_38_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct32x32_1_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct4x4_16_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_12_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+RTCD_EXTERN void (*vpx_highbd_idct8x8_64_add)(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/libvpx/source/config/win/x64/vp9_rtcd.h b/third_party/libvpx/source/config/win/x64/vp9_rtcd.h
index 5e72bb8..126071d 100644
--- a/third_party/libvpx/source/config/win/x64/vp9_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vp9_rtcd.h
@@ -95,13 +95,13 @@
 void vp9_highbd_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
 #define vp9_highbd_fwht4x4 vp9_highbd_fwht4x4_c
 
-void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type, int bd);
+void vp9_highbd_iht16x16_256_add_c(const tran_low_t *input, uint16_t *output, int pitch, int tx_type, int bd);
 #define vp9_highbd_iht16x16_256_add vp9_highbd_iht16x16_256_add_c
 
-void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht4x4_16_add vp9_highbd_iht4x4_16_add_c
 
-void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type, int bd);
+void vp9_highbd_iht8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int tx_type, int bd);
 #define vp9_highbd_iht8x8_64_add vp9_highbd_iht8x8_64_add_c
 
 void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows, int cols, int flimit);
@@ -143,9 +143,9 @@
 void vp9_quantize_fp_32x32_ssse3(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 RTCD_EXTERN void (*vp9_quantize_fp_32x32)(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
 
-void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
-RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, int phase_scaler);
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_ssse3(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
+RTCD_EXTERN void (*vp9_scale_and_extend_frame)(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, uint8_t filter_type, int phase_scaler);
 
 void vp9_temporal_filter_apply_c(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
 void vp9_temporal_filter_apply_sse4_1(const uint8_t *frame1, unsigned int stride, const uint8_t *frame2, unsigned int block_width, unsigned int block_height, int strength, int filter_weight, uint32_t *accumulator, uint16_t *count);
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
index 6bab65e..b2403c3 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -1031,56 +1031,56 @@
 void vpx_highbd_h_predictor_8x8_c(uint16_t *dst, ptrdiff_t y_stride, const uint16_t *above, const uint16_t *left, int bd);
 #define vpx_highbd_h_predictor_8x8 vpx_highbd_h_predictor_8x8_c
 
-void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_10_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_10_add vpx_highbd_idct16x16_10_add_sse2
 
-void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_1_add vpx_highbd_idct16x16_1_add_c
 
-void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_256_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_38_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct16x16_256_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct16x16_38_add vpx_highbd_idct16x16_256_add_sse2
 
-void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1024_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1024_add vpx_highbd_idct32x32_1024_add_c
 
-void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_135_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_135_add vpx_highbd_idct32x32_135_add_c
 
-void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_1_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_1_add vpx_highbd_idct32x32_1_add_sse2
 
-void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct32x32_34_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct32x32_34_add vpx_highbd_idct32x32_34_add_c
 
-void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_16_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_16_add vpx_highbd_idct4x4_16_add_sse2
 
-void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct4x4_1_add vpx_highbd_idct4x4_1_add_c
 
-void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_12_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_12_add vpx_highbd_idct8x8_12_add_sse2
 
-void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_1_add vpx_highbd_idct8x8_1_add_c
 
-void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
-void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
+void vpx_highbd_idct8x8_64_add_sse2(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_idct8x8_64_add vpx_highbd_idct8x8_64_add_sse2
 
-void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_16_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_16_add vpx_highbd_iwht4x4_16_add_c
 
-void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride, int bd);
+void vpx_highbd_iwht4x4_1_add_c(const tran_low_t *input, uint16_t *dest, int stride, int bd);
 #define vpx_highbd_iwht4x4_1_add vpx_highbd_iwht4x4_1_add_c
 
 void vpx_highbd_lpf_horizontal_16_c(uint16_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int bd);
diff --git a/third_party/typ/README.chromium b/third_party/typ/README.chromium
index dc38714..c8af3c19 100644
--- a/third_party/typ/README.chromium
+++ b/third_party/typ/README.chromium
@@ -1,7 +1,7 @@
 Name: typ
 URL: https://github.com/dpranke/typ.git
-Version: 0.9.11
-Revision: f6afa2bbd1765b21e815e1e6f6f36e1b9f896edf
+Version: 0.9.12
+Revision: 2b5a4fcf7c103323f9c6cd8d8127d740e78c0fe8
 Security Critical: no
 License: Apache 2.0
 License File: NOT_SHIPPED
diff --git a/third_party/typ/typ/json_results.py b/third_party/typ/typ/json_results.py
index 6d1eb81..f048d05 100644
--- a/third_party/typ/typ/json_results.py
+++ b/third_party/typ/typ/json_results.py
@@ -123,6 +123,14 @@
     return full_results['num_failures_by_type']['FAIL']
 
 
+def num_passes(full_results):
+    return full_results['num_failures_by_type']['PASS']
+
+
+def num_skips(full_results):
+    return full_results['num_failures_by_type']['SKIP']
+
+
 def failed_test_names(results):
     names = set()
     for r in results.results:
diff --git a/third_party/typ/typ/runner.py b/third_party/typ/typ/runner.py
index a2f5c3df..01e414c 100644
--- a/third_party/typ/typ/runner.py
+++ b/third_party/typ/typ/runner.py
@@ -422,9 +422,6 @@
 
     def _run_tests(self, result_set, test_set):
         h = self.host
-        if not test_set.parallel_tests and not test_set.isolated_tests:
-            self.print_('No tests to run.')
-            return 1, None
 
         all_tests = [ti.name for ti in
                      _sort_inputs(test_set.parallel_tests +
@@ -592,8 +589,9 @@
         self.printer.flush()
 
     def _summarize(self, full_results):
-        num_tests = self.stats.finished
+        num_passes = json_results.num_passes(full_results)
         num_failures = json_results.num_failures(full_results)
+        num_skips = json_results.num_skips(full_results)
 
         if self.args.quiet and num_failures == 0:
             return
@@ -603,10 +601,11 @@
                                            self.stats.started_time)
         else:
             timing_clause = ''
-        self.update('%d test%s run%s, %d failure%s.' %
-                    (num_tests,
-                     '' if num_tests == 1 else 's',
+        self.update('%d test%s passed%s, %d skipped, %d failure%s.' %
+                    (num_passes,
+                     '' if num_passes == 1 else 's',
                      timing_clause,
+                     num_skips,
                      num_failures,
                      '' if num_failures == 1 else 's'), elide=False)
         self.print_()
diff --git a/third_party/typ/typ/tests/main_test.py b/third_party/typ/typ/tests/main_test.py
index 4474efc..f17aabc 100644
--- a/third_party/typ/typ/tests/main_test.py
+++ b/third_party/typ/typ/tests/main_test.py
@@ -191,7 +191,7 @@
         self.check([], files=PASS_TEST_FILES,
                    ret=0,
                    out=('[1/1] pass_test.PassingTest.test_pass passed\n'
-                        '1 test run, 0 failures.\n'), err='')
+                        '1 test passed, 0 skipped, 0 failures.\n'), err='')
 
     def test_coverage(self):
         try:
@@ -203,7 +203,7 @@
             self.check(['-c', 'pass_test'], files=files, ret=0, err='',
                        out=d("""\
                              [1/1] pass_test.PassingTest.test_pass passed
-                             1 test run, 0 failures.
+                             1 test passed, 0 skipped, 0 failures.
 
                              Name           Stmts   Miss  Cover
                              ----------------------------------
@@ -230,7 +230,7 @@
         self.check(['-n'], files=PASS_TEST_FILES, ret=0, err='',
                    out=d("""\
                          [1/1] pass_test.PassingTest.test_pass passed
-                         1 test run, 0 failures.
+                         1 test passed, 0 skipped, 0 failures.
                          """))
 
     def test_error(self):
@@ -243,7 +243,7 @@
         _, out, _, _ = self.check([''], files=files, ret=1, err='')
         self.assertIn('[1/1] err_test.ErrTest.test_err failed unexpectedly',
                       out)
-        self.assertIn('1 test run, 1 failure', out)
+        self.assertIn('0 tests passed, 0 skipped, 1 failure', out)
 
     def test_fail(self):
         _, out, _, _ = self.check([], files=FAIL_TEST_FILES, ret=1, err='')
@@ -267,7 +267,7 @@
                                       files=files, ret=0, err='')
         self.assertIn('Retrying failed tests (attempt #1 of 3)', out)
         self.assertNotIn('Retrying failed tests (attempt #2 of 3)', out)
-        self.assertIn('1 test run, 0 failures.\n', out)
+        self.assertIn('1 test passed, 0 skipped, 0 failures.\n', out)
         results = json.loads(files['full_results.json'])
         self.assertEqual(
             results['tests'][
@@ -293,7 +293,7 @@
                                       files=files, ret=0, err='')
         self.assertIn('Retrying failed tests (attempt #1 of 3)', out)
         self.assertNotIn('Retrying failed tests (attempt #2 of 3)', out)
-        self.assertIn('1 test run, 0 failures.\n', out)
+        self.assertIn('0 tests passed, 1 skipped, 0 failures.\n', out)
         results = json.loads(files['full_results.json'])
         self.assertEqual(
             results['tests'][
@@ -377,8 +377,8 @@
 
     def test_import_failure_no_tests(self):
         files = {'foo.py': 'import unittest'}
-        self.check(['-l', 'foo'], files=files, ret=1, err='',
-                   out='No tests to run.\n')
+        self.check(['-l', 'foo'], files=files, ret=0, err='',
+                   out='\n')
 
     def test_import_failure_syntax_error(self):
         files = {'syn_test.py': d("""\
@@ -405,7 +405,7 @@
     def test_isolate(self):
         self.check(['--isolate', '*test_pass*'], files=PASS_TEST_FILES, ret=0,
                    out=('[1/1] pass_test.PassingTest.test_pass passed\n'
-                        '1 test run, 0 failures.\n'), err='')
+                        '1 test passed, 0 skipped, 0 failures.\n'), err='')
 
     def test_load_tests_failure(self):
         files = {'foo_test.py': d("""\
@@ -423,7 +423,7 @@
                                   err='')
         self.assertIn('[1/2] load_test.BaseTest.test_fail failed', out)
         self.assertIn('[2/2] load_test.BaseTest.test_pass passed', out)
-        self.assertIn('2 tests run, 1 failure.\n', out)
+        self.assertIn('1 test passed, 0 skipped, 1 failure.\n', out)
 
     def test_load_tests_multiple_workers(self):
         _, out, _, _ = self.check([], files=LOAD_TEST_FILES, ret=1, err='')
@@ -433,7 +433,7 @@
         # we care about are present.
         self.assertIn('test_pass passed', out)
         self.assertIn('test_fail failed', out)
-        self.assertIn('2 tests run, 1 failure.\n', out)
+        self.assertIn('1 test passed, 0 skipped, 1 failure.\n', out)
 
     def test_missing_builder_name(self):
         self.check(['--test-results-server', 'localhost'], ret=2,
@@ -449,7 +449,7 @@
                    files=OUTPUT_TEST_FILES, aenv={'NINJA_STATUS': 'ns: '},
                    out=d("""\
                          ns: output_test.PassTest.test_out passed
-                         1 test run, 0 failures.
+                         1 test passed, 0 skipped, 0 failures.
                          """), err='')
 
     def test_output_for_failures(self):
@@ -474,15 +474,16 @@
                          3)
 
     def test_skip(self):
-        self.check(['--skip', '*test_fail*'], files=FAIL_TEST_FILES, ret=1,
-                   out='No tests to run.\n', err='')
+        _, out, _, _ = self.check(['--skip', '*test_fail*'],
+                                  files=FAIL_TEST_FILES, ret=0)
+        self.assertIn('0 tests passed, 1 skipped, 0 failures.', out)
 
         files = {'fail_test.py': FAIL_TEST_PY,
                  'pass_test.py': PASS_TEST_PY}
         self.check(['-j', '1', '--skip', '*test_fail*'], files=files, ret=0,
                    out=('[1/2] fail_test.FailingTest.test_fail was skipped\n'
                         '[2/2] pass_test.PassingTest.test_pass passed\n'
-                        '2 tests run, 0 failures.\n'), err='')
+                        '1 test passed, 1 skipped, 0 failures.\n'), err='')
 
         # This tests that we print test_started updates for skipped tests
         # properly. It also tests how overwriting works.
@@ -503,7 +504,7 @@
              '                                     \r'
              '[2/2] pass_test.PassingTest.test_pass passed\r'
              '                                            \r'
-             '2 tests run, 0 failures.'))
+             '1 test passed, 1 skipped, 0 failures.'))
 
     def test_skips_and_failures(self):
         _, out, _, _ = self.check(['-j', '1', '-v', '-v'], files=SF_TEST_FILES,
@@ -533,16 +534,17 @@
                        '  reason\n'
                        '[9/9] sf_test.SkipSetup.test_notrun was skipped:\n'
                        '  setup failed\n'
-                       '9 tests run, 4 failures.\n'), out)
+                       '1 test passed, 4 skipped, 4 failures.\n'), out)
 
     def test_skip_and_all(self):
         # --all should override --skip
-        self.check(['-l', '--skip', '*test_pass'],
-                   files=PASS_TEST_FILES, ret=1, err='',
-                   out='No tests to run.\n')
-        self.check(['-l', '--all', '--skip', '*test_pass'],
-                   files=PASS_TEST_FILES, ret=0, err='',
-                   out='pass_test.PassingTest.test_pass\n')
+        _, out, _, _ = self.check(['--skip', '*test_pass'],
+                                  files=PASS_TEST_FILES, ret=0, err='')
+        self.assertIn('0 tests passed, 1 skipped, 0 failures.', out)
+
+        _, out, _, _ = self.check(['--all', '--skip', '*test_pass'],
+                                  files=PASS_TEST_FILES, ret=0, err='')
+        self.assertIn('1 test passed, 0 skipped, 0 failures.', out)
 
     def test_skip_decorators_and_all(self):
         _, out, _, _ = self.check(['--all', '-j', '1', '-v', '-v'],
@@ -589,7 +591,7 @@
             for i, test in enumerate(tests):
                 exp_out += ('[%d/%d] shard_test.ShardTest.test_%s passed\n' %
                             (i + 1, total_tests, test))
-            exp_out += '%d test%s run, 0 failures.\n' % (
+            exp_out += '%d test%s passed, 0 skipped, 0 failures.\n' % (
                 total_tests, "" if total_tests == 1 else "s")
             self.assertEqual(out, exp_out)
 
@@ -607,14 +609,14 @@
         self.check(['foo/bar'], files=files, ret=0, err='',
                    out=d("""\
                          [1/1] foo.bar.pass_test.PassingTest.test_pass passed
-                         1 test run, 0 failures.
+                         1 test passed, 0 skipped, 0 failures.
                          """))
 
     def test_timing(self):
         self.check(['-t'], files=PASS_TEST_FILES, ret=0, err='',
                    rout=(r'\[1/1\] pass_test.PassingTest.test_pass passed '
                          r'\d+.\d+s\n'
-                         r'1 test run in \d+.\d+s, 0 failures.'))
+                         r'1 test passed in \d+.\d+s, 0 skipped, 0 failures.'))
 
     def test_test_results_server(self):
         server = test_result_server_fake.start()
@@ -629,7 +631,7 @@
                         '--metadata', 'foo=bar'],
                        files=PASS_TEST_FILES, ret=0, err='',
                        out=('[1/1] pass_test.PassingTest.test_pass passed\n'
-                            '1 test run, 0 failures.\n'))
+                            '1 test passed, 0 skipped, 0 failures.\n'))
 
         finally:
             posts = server.stop()
@@ -654,7 +656,7 @@
                         '--metadata', 'foo=bar'],
                        files=PASS_TEST_FILES, ret=1, err='',
                        out=('[1/1] pass_test.PassingTest.test_pass passed\n'
-                            '1 test run, 0 failures.\n'
+                            '1 test passed, 0 skipped, 0 failures.\n'
                             'Uploading the JSON results raised '
                             '"HTTP Error 500: Internal Server Error"\n'))
 
@@ -669,7 +671,7 @@
                     '--metadata', 'foo=bar'],
                    files=PASS_TEST_FILES, ret=1, err='',
                    rout=(r'\[1/1\] pass_test.PassingTest.test_pass passed\n'
-                         '1 test run, 0 failures.\n'
+                         '1 test passed, 0 skipped, 0 failures.\n'
                          'Uploading the JSON results raised .*\n'))
 
     def test_verbose_2(self):
@@ -680,7 +682,7 @@
                            hello on stderr
                          [2/2] output_test.PassTest.test_out passed:
                            hello on stdout
-                         2 tests run, 0 failures.
+                         2 tests passed, 0 skipped, 0 failures.
                          """), err='')
 
     def test_verbose_3(self):
@@ -693,7 +695,7 @@
                          [1/2] output_test.PassTest.test_out queued
                          [2/2] output_test.PassTest.test_out passed:
                            hello on stdout
-                         2 tests run, 0 failures.
+                         2 tests passed, 0 skipped, 0 failures.
                          """), err='')
 
     def test_version(self):
diff --git a/third_party/typ/typ/tests/runner_test.py b/third_party/typ/typ/tests/runner_test.py
index 4ebb30b..a5013b2 100644
--- a/third_party/typ/typ/tests/runner_test.py
+++ b/third_party/typ/typ/tests/runner_test.py
@@ -147,8 +147,8 @@
             result = self.call([],
                                win_multiprocessing=WinMultiprocessing.ignore)
             ret, out, err = result
-            self.assertEqual(ret, 1)
-            self.assertEqual(out, 'No tests to run.\n')
+            self.assertEqual(ret, 0)
+            self.assertEqual(out, '0 tests passed, 0 skipped, 0 failures.\n')
             self.assertEqual(err, '')
 
     def test_real_unimportable_main(self):
@@ -205,14 +205,14 @@
 
     def test_single_job(self):
         ret, out, err = self.call(['-j', '1'], platform='win32')
-        self.assertEqual(ret, 1)
-        self.assertIn('No tests to run.', out)
+        self.assertEqual(ret, 0)
+        self.assertEqual('0 tests passed, 0 skipped, 0 failures.\n', out )
         self.assertEqual(err, '')
 
     def test_spawn(self):
         ret, out, err = self.call([])
-        self.assertEqual(ret, 1)
-        self.assertIn('No tests to run.', out)
+        self.assertEqual(ret, 0)
+        self.assertEqual('0 tests passed, 0 skipped, 0 failures.\n', out)
         self.assertEqual(err, '')
 
 
diff --git a/third_party/typ/typ/version.py b/third_party/typ/typ/version.py
index 8d5c7b50..9fc38441d 100644
--- a/third_party/typ/typ/version.py
+++ b/third_party/typ/typ/version.py
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-VERSION = '0.9.11'
+VERSION = '0.9.12'
diff --git a/tools/battor_agent/battor_agent_bin.cc b/tools/battor_agent/battor_agent_bin.cc
index 3c83d67..0d535543 100644
--- a/tools/battor_agent/battor_agent_bin.cc
+++ b/tools/battor_agent/battor_agent_bin.cc
@@ -42,6 +42,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py
index 151cb357..d0aded2 100755
--- a/tools/clang/scripts/package.py
+++ b/tools/clang/scripts/package.py
@@ -26,6 +26,8 @@
 LLVM_BUILD_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-build')
 LLVM_RELEASE_DIR = os.path.join(LLVM_BUILD_DIR, 'Release+Asserts')
 LLVM_LTO_GOLD_PLUGIN_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-lto-gold-plugin')
+BINUTILS_LIB_DIR = os.path.join(THIRD_PARTY_DIR, 'binutils', 'Linux_x64',
+                                'Release', 'lib')
 STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision')
 
 
@@ -322,6 +324,12 @@
     shutil.copytree(os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'include', 'c++'),
                     os.path.join(pdir, 'include', 'c++'))
 
+  # Copy tcmalloc from the binutils package.
+  # FIXME: We should eventually be building our own copy.
+  if sys.platform.startswith('linux'):
+    shutil.copy(os.path.join(BINUTILS_LIB_DIR, 'libtcmalloc_minimal.so.4'),
+                os.path.join(pdir, 'lib'))
+
   # Copy buildlog over.
   shutil.copy('buildlog.txt', pdir)
 
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 501bc9f..64c5207 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -34,7 +34,7 @@
   CLANG_REVISION = 'HEAD'
 
 # This is incremented when pushing a new build of Clang at the same revision.
-CLANG_SUB_REVISION=1
+CLANG_SUB_REVISION=2
 
 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
 
@@ -66,11 +66,10 @@
     os.path.join(LLVM_DIR, '..', 'llvm-build-tools'))
 STAMP_FILE = os.path.normpath(
     os.path.join(LLVM_DIR, '..', 'llvm-build', 'cr_build_revision'))
-BINUTILS_DIR = os.path.join(THIRD_PARTY_DIR, 'binutils')
-BINUTILS_BIN_DIR = os.path.join(BINUTILS_DIR, BINUTILS_DIR,
-                                'Linux_x64', 'Release', 'bin')
-BFD_PLUGINS_DIR = os.path.join(BINUTILS_DIR, 'Linux_x64', 'Release',
-                               'lib', 'bfd-plugins')
+BINUTILS_DIR = os.path.join(THIRD_PARTY_DIR, 'binutils', 'Linux_x64', 'Release')
+BINUTILS_BIN_DIR = os.path.join(BINUTILS_DIR, 'bin')
+BINUTILS_LIB_DIR = os.path.join(BINUTILS_DIR, 'lib')
+BFD_PLUGINS_DIR = os.path.join(BINUTILS_LIB_DIR, 'bfd-plugins')
 VERSION = '5.0.0'
 ANDROID_NDK_DIR = os.path.join(
     CHROMIUM_DIR, 'third_party', 'android_tools', 'ndk')
@@ -503,7 +502,7 @@
 
   binutils_incdir = ''
   if sys.platform.startswith('linux'):
-    binutils_incdir = os.path.join(BINUTILS_DIR, 'Linux_x64/Release/include')
+    binutils_incdir = os.path.join(BINUTILS_DIR, 'include')
 
   if args.bootstrap:
     print 'Building bootstrap compiler'
@@ -565,6 +564,13 @@
                 os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'lib', 'LLVMgold.so'),
                 os.path.join(BFD_PLUGINS_DIR, 'LLVMgold.so')])
 
+    # Link against binutils's copy of tcmalloc to speed up the linker by ~10%.
+    # In package.py we copy the .so into our package.
+    tcmalloc_ldflags = ['-L' + BINUTILS_LIB_DIR, '-ltcmalloc_minimal']
+    # Make sure that tblgen and the test suite can find tcmalloc.
+    os.environ['LD_LIBRARY_PATH'] = \
+        BINUTILS_LIB_DIR + os.pathsep + os.environ.get('LD_LIBRARY_PATH', '')
+
     lto_cflags = ['-flto=thin']
     lto_ldflags = ['-fuse-ld=lld']
     if args.gcc_toolchain:
@@ -577,7 +583,7 @@
         '-DCMAKE_CXX_COMPILER=' + cxx,
         '-DCMAKE_C_FLAGS=' + ' '.join(lto_cflags),
         '-DCMAKE_CXX_FLAGS=' + ' '.join(lto_cflags),
-        '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(lto_ldflags),
+        '-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(lto_ldflags + tcmalloc_ldflags),
         '-DCMAKE_SHARED_LINKER_FLAGS=' + ' '.join(lto_ldflags),
         '-DCMAKE_MODULE_LINKER_FLAGS=' + ' '.join(lto_ldflags)]
 
diff --git a/tools/gn/analyzer.cc b/tools/gn/analyzer.cc
index 6e23c345..d1f2d524 100644
--- a/tools/gn/analyzer.cc
+++ b/tools/gn/analyzer.cc
@@ -112,7 +112,7 @@
                  const std::string& key,
                  const LabelSet& labels) {
   std::vector<std::string> strings;
-  auto value = base::WrapUnique(new base::ListValue());
+  auto value = base::MakeUnique<base::ListValue>();
   for (const auto l : labels)
     strings.push_back(l.GetUserVisibleName(default_toolchain));
   std::sort(strings.begin(), strings.end());
@@ -207,7 +207,7 @@
   } else {
     WriteString(*value, "status", outputs.status);
     if (outputs.compile_includes_all) {
-      auto compile_targets = base::WrapUnique(new base::ListValue());
+      auto compile_targets = base::MakeUnique<base::ListValue>();
       compile_targets->AppendString("all");
       value->SetWithoutPathExpansion("compile_targets",
                                      std::move(compile_targets));
diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc
index 650c64a..f2fe7521 100644
--- a/tools/gn/scope.cc
+++ b/tools/gn/scope.cc
@@ -339,7 +339,7 @@
     }
 
     std::unique_ptr<Scope>& dest_scope = dest->target_defaults_[current_name];
-    dest_scope = base::WrapUnique(new Scope(settings_));
+    dest_scope = base::MakeUnique<Scope>(settings_);
     pair.second->NonRecursiveMergeTo(dest_scope.get(), options, node_for_err,
                                      "<SHOULDN'T HAPPEN>", err);
   }
@@ -430,7 +430,7 @@
 
 Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
   std::unique_ptr<Scope>& dest = target_defaults_[target_type];
-  dest = base::WrapUnique(new Scope(settings_));
+  dest = base::MakeUnique<Scope>(settings_);
   return dest.get();
 }
 
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc
index 22f4fcec..192230d 100644
--- a/tools/gn/setup.cc
+++ b/tools/gn/setup.cc
@@ -265,21 +265,6 @@
 }
 #endif
 
-// Expands all ./, ../, and symbolic links in the given path.
-bool GetRealPath(const base::FilePath& path, base::FilePath* out) {
-#if defined(OS_POSIX)
-  char buf[PATH_MAX];
-  if (!realpath(path.value().c_str(), buf)) {
-    return false;
-  }
-  *out = base::FilePath(buf);
-#else
-  // Do nothing on a non-POSIX system.
-  *out = path;
-#endif
-  return true;
-}
-
 }  // namespace
 
 const char Setup::kBuildArgFileName[] = "args.gn";
@@ -578,8 +563,8 @@
     root_path = dotfile_name_.DirName();
   }
 
-  base::FilePath root_realpath;
-  if (!GetRealPath(root_path, &root_realpath)) {
+  base::FilePath root_realpath = base::MakeAbsoluteFilePath(root_path);
+  if (root_realpath.empty()) {
     Err(Location(), "Can't get the real root path.",
         "I could not get the real path of \"" + FilePathToUTF8(root_path) +
         "\".").PrintToStdout();
@@ -610,8 +595,9 @@
         "\".").PrintToStdout();
     return false;
   }
-  base::FilePath build_dir_realpath;
-  if (!GetRealPath(build_dir_path, &build_dir_realpath)) {
+  base::FilePath build_dir_realpath =
+      base::MakeAbsoluteFilePath(build_dir_path);
+  if (build_dir_realpath.empty()) {
     Err(Location(), "Can't get the real build dir path.",
         "I could not get the real path of \"" + FilePathToUTF8(build_dir_path) +
         "\".").PrintToStdout();
diff --git a/tools/gn/xcode_object.cc b/tools/gn/xcode_object.cc
index b8c8502..8a314703 100644
--- a/tools/gn/xcode_object.cc
+++ b/tools/gn/xcode_object.cc
@@ -560,8 +560,8 @@
   }
 
   if (!group) {
-    children_.push_back(base::WrapUnique(
-        new PBXGroup(component.as_string(), component.as_string())));
+    children_.push_back(base::MakeUnique<PBXGroup>(component.as_string(),
+                                                   component.as_string()));
     group = static_cast<PBXGroup*>(children_.back().get());
   }
 
@@ -617,11 +617,11 @@
       product_type_(product_type),
       product_name_(product_name) {
   DCHECK(product_reference_);
-  build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase));
+  build_phases_.push_back(base::MakeUnique<PBXSourcesBuildPhase>());
   source_build_phase_ =
       static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
 
-  build_phases_.push_back(base::WrapUnique(new PBXFrameworksBuildPhase));
+  build_phases_.push_back(base::MakeUnique<PBXFrameworksBuildPhase>());
 }
 
 PBXNativeTarget::~PBXNativeTarget() {}
diff --git a/tools/gn/xml_element_writer.cc b/tools/gn/xml_element_writer.cc
index bb0d232..ecc4f7b 100644
--- a/tools/gn/xml_element_writer.cc
+++ b/tools/gn/xml_element_writer.cc
@@ -64,8 +64,7 @@
     const std::string& tag,
     const XmlAttributes& attributes) {
   StartContent(true);
-  return base::WrapUnique(
-      new XmlElementWriter(out_, tag, attributes, indent_ + 2));
+  return base::MakeUnique<XmlElementWriter>(out_, tag, attributes, indent_ + 2);
 }
 
 std::ostream& XmlElementWriter::StartContent(bool start_new_line) {
diff --git a/tools/gn/xml_element_writer.h b/tools/gn/xml_element_writer.h
index 01346d23..0e8fa01f 100644
--- a/tools/gn/xml_element_writer.h
+++ b/tools/gn/xml_element_writer.h
@@ -116,8 +116,8 @@
     const std::string& attribute_name,
     const Writer& attribute_value_writer) {
   StartContent(true);
-  return base::WrapUnique(new XmlElementWriter(
-      out_, tag, attribute_name, attribute_value_writer, indent_ + 2));
+  return base::MakeUnique<XmlElementWriter>(
+      out_, tag, attribute_name, attribute_value_writer, indent_ + 2);
 }
 
 std::string XmlEscape(const std::string& value);
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 1e32fb1..bcfc0e1 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -16630,6 +16630,30 @@
   </description>
 </action>
 
+<action name="VR.DOFF">
+  <owner>billorr@chromium.org</owner>
+  <description>
+    The user has successfully completed the VR DOFF flow.
+  </description>
+</action>
+
+<action name="VR.DON">
+  <owner>billorr@chromium.org</owner>
+  <description>
+    The user has successfully completed the VR DON flow.
+  </description>
+</action>
+
+<action name="VR.WebVR.StopPresenting">
+  <owner>billorr@chromium.org</owner>
+  <description>The user (or site) has stopped WebVR presentation.</description>
+</action>
+
+<action name="VR.WebVR.requestPresent">
+  <owner>billorr@chromium.org</owner>
+  <description>The user has initiated WebVR presentation.</description>
+</action>
+
 <action name="VideoPlayer.CastVideoError">
   <owner>yoshiki@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 069b3e0..817545cb 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -2220,6 +2220,7 @@
   <int value="165" label="BFSI_INVALID_REQUESTS"/>
   <int value="166" label="BFSI_INVALID_TITLE"/>
   <int value="167" label="RWH_INVALID_FRAME_TOKEN"/>
+  <int value="168" label="RWH_BAD_FRAME_SINK_REQUEST"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions" type="int">
@@ -21336,6 +21337,7 @@
   <int value="-1536293422" label="SharedArrayBuffer:enabled"/>
   <int value="-1536242739" label="security-chip"/>
   <int value="-1532014193" label="disable-encryption-migration"/>
+  <int value="-1515415104" label="top-document-isolation:disabled"/>
   <int value="-1514943439" label="ash-enable-swipe-to-close-in-overview-mode"/>
   <int value="-1514611301" label="enable-data-reduction-proxy-bypass-warnings"/>
   <int value="-1512656386" label="disable-new-audio-rendering-mixing-strategy"/>
@@ -21663,6 +21665,7 @@
   <int value="-314605926" label="protect-sync-credential-on-reauth:enabled"/>
   <int value="-311148335" label="v8-pac-mojo-out-of-process"/>
   <int value="-300018686" label="disable-cloud-import"/>
+  <int value="-299841473" label="top-document-isolation:enabled"/>
   <int value="-297716805"
       label="CrossOriginMediaPlaybackRequiresUserGesture:disabled"/>
   <int value="-290672626" label="enable-asm-wasm"/>
@@ -33543,6 +33546,7 @@
   <int value="3" label="XHR succeeded"/>
   <int value="4" label="Frame detached"/>
   <int value="5" label="By context menu"/>
+  <int value="6" label="DOM mutation after XHR"/>
 </enum>
 
 <enum name="SubresourceFilterActions" type="int">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 501b53f..c2a2f5bf 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -29627,6 +29627,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Memory.Experimental.Browser2" units="MB">
+<!-- Name completed by histogram_suffixes name="BrowserMemoryAllocator2" -->
+
+  <owner>erikchen@chromium.org</owner>
+  <summary>
+    The browser process's memory usage reported by the memory instrumentation
+    service.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Experimental.CompressedPagesPerSecond" units="pages/s">
   <owner>bashi@chromium.org</owner>
   <summary>
@@ -29670,6 +29680,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Memory.Experimental.Gpu2" units="MB">
+<!-- Name completed by histogram_suffixes name="GpuMemoryAllocator2" -->
+
+  <owner>erikchen@chromium.org</owner>
+  <summary>
+    The gpu process's memory usage reported by the memory instrumentation
+    service.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Memory.Experimental.Renderer" units="MB">
 <!-- Name completed by histogram_suffixes name="RendererMemoryAllocator" -->
 
@@ -29711,6 +29731,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Memory.Experimental.Renderer2" units="MB">
+<!-- Name completed by histogram_suffixes name="RendererMemoryAllocator2" -->
+
+  <owner>erikchen@chromium.org</owner>
+  <summary>
+    The renderer process's memory usage reported by the memory instrumentation
+    service.
+  </summary>
+</histogram>
+
 <histogram name="Memory.Experimental.SwapInPerSecond" units="swaps/s">
   <owner>bashi@chromium.org</owner>
   <summary>
@@ -39249,7 +39279,7 @@
 </histogram>
 
 <histogram name="Net.TCP_Connection_Latency_IPv4_No_Race" units="ms">
-  <owner>mmenke@chromium.org</owner>
+  <owner>mgersh@chromium.org</owner>
   <summary>
     Time from when the Connect() starts until it completes when the network
     address only contains IPv4 addresses.  Only times under 10 minutes are
@@ -39258,7 +39288,7 @@
 </histogram>
 
 <histogram name="Net.TCP_Connection_Latency_IPv4_Wins_Race" units="ms">
-  <owner>mmenke@chromium.org</owner>
+  <owner>mgersh@chromium.org</owner>
   <summary>
     Time from when the Connect() starts until it completes when the IPv4
     fallback connection won the race against IPv6.  Only times under 10 minutes
@@ -39267,7 +39297,7 @@
 </histogram>
 
 <histogram name="Net.TCP_Connection_Latency_IPv6_Raceable" units="ms">
-  <owner>mmenke@chromium.org</owner>
+  <owner>mgersh@chromium.org</owner>
   <summary>
     Time from when the Connect() starts until it completes when we race an IPv6
     connection against an IPv4 connection with a 300ms delay.  Only times under
@@ -39276,7 +39306,7 @@
 </histogram>
 
 <histogram name="Net.TCP_Connection_Latency_IPv6_Solo" units="ms">
-  <owner>mmenke@chromium.org</owner>
+  <owner>mgersh@chromium.org</owner>
   <summary>
     Time from when the Connect() starts until it completes when the network
     address only contains IPv6 addresses.  Only times under 10 minutes are
@@ -80300,6 +80330,15 @@
   </summary>
 </histogram>
 
+<histogram name="WebCore.SpellChecker.RequestInterval" units="ms">
+  <owner>xiaochengh@chromium.org</owner>
+  <summary>
+    The amount of time between consecutive spellcheck requests made by Blink,
+    with the exception that requests made simultaneously checking different
+    parts of the same editing host count as only one request.
+  </summary>
+</histogram>
+
 <histogram name="WebCore.UseCounter_TEST.CSSProperties"
     enum="MappedCSSProperties">
   <obsolete>
@@ -84057,6 +84096,12 @@
   <affected-histogram name="BlinkGC.CollectionRate"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="BrowserMemoryAllocator2" separator=".">
+  <suffix name="Resident" label="Only counting resident memory."/>
+  <suffix name="Malloc" label="Constrained to malloc allocator."/>
+  <affected-histogram name="Memory.Experimental.Browser2"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="CachedResourceType" separator=".">
   <suffix name="JavaScript"
       label="Showing cache patterns only for JavaScript resources."/>
@@ -86037,6 +86082,12 @@
   <affected-histogram name="GPU.ContextMemory.WebGL"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="GpuMemoryAllocator2" separator=".">
+  <suffix name="Resident" label="Only counting resident memory."/>
+  <suffix name="Malloc" label="Constrained to malloc allocator."/>
+  <affected-histogram name="Memory.Experimental.Gpu2"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="GWSChromeJointExperiment">
   <suffix name="Experiment1"
       label="Only page loads that are a result of a navigation from a web
@@ -90765,6 +90816,15 @@
   <affected-histogram name="Memory.Experimental.Renderer"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="RendererMemoryAllocator2" separator=".">
+  <suffix name="Resident" label="Only counting resident memory."/>
+  <suffix name="Malloc" label="Constrained to malloc allocator."/>
+  <suffix name="PartitionAlloc" label="Constrained to partition allocator."/>
+  <suffix name="BlinkGC" label="Constrained to blink GC allocator."/>
+  <suffix name="V8" label="Constrained to v8 allocator."/>
+  <affected-histogram name="Memory.Experimental.Renderer2"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="RendererMemoryTiming" separator=".">
   <suffix name="DidFinishLoad"
       label="Recorded each time DidFinishLoad is called for *any* frame
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 57f186f0..903a4a9 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -35,7 +35,6 @@
 jetstream,"bmeurer@chromium.org, mvstanton@chromium.org",
 kraken,"bmeurer@chromium.org, mvstanton@chromium.org",
 load_library_perf_tests,,
-loading.cluster_telemetry,,
 loading.desktop,"kouhei@chormium.org, ksakamoto@chromium.org",
 loading.mobile,"kouhei@chromium.org, ksakamoto@chromium.org",
 media.android.tough_video_cases,"crouleau@chromium.org, videostack-eng@google.com",Internals>Media
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py
index 5beb23b..2460783e 100644
--- a/tools/perf/benchmarks/benchmark_smoke_unittest.py
+++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -27,7 +27,6 @@
 from benchmarks import kraken
 from benchmarks import octane
 from benchmarks import rasterize_and_record_micro
-from benchmarks import repaint
 from benchmarks import speedometer
 from benchmarks import v8_browsing
 
@@ -93,7 +92,6 @@
     indexeddb_perf,  # Always fails on Win7 & Android Tests builder.
     octane,  # Often fails & take long time to timeout on cq bot.
     rasterize_and_record_micro,  # Always fails on cq bot.
-    repaint,  # Often fails & takes long time to timeout on cq bot.
     speedometer,  # Takes 101 seconds.
     jetstream,  # Take 206 seconds.
     kraken,  # Flaky on Android, crbug.com/626174.
diff --git a/tools/perf/benchmarks/loading.py b/tools/perf/benchmarks/loading.py
index ed570a5..7c9540ae 100644
--- a/tools/perf/benchmarks/loading.py
+++ b/tools/perf/benchmarks/loading.py
@@ -5,7 +5,6 @@
 from core import perf_benchmark
 import page_sets
 
-import ct_benchmarks_util
 from benchmarks import page_cycler_v2
 from telemetry import benchmark
 from telemetry.page import cache_temperature
@@ -70,38 +69,3 @@
   @classmethod
   def Name(cls):
     return 'loading.mobile'
-
-
-# Disabled because we do not plan on running CT benchmarks on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
-class LoadingClusterTelemetry(_LoadingBase):
-
-  options = {'upload_results': True}
-
-  _ALL_NET_CONFIGS = traffic_setting.NETWORK_CONFIGS.keys()
-
-  @classmethod
-  def AddBenchmarkCommandLineArgs(cls, parser):
-    super(LoadingClusterTelemetry, cls).AddBenchmarkCommandLineArgs(parser)
-    ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
-    parser.add_option(
-        '--wait-time',  action='store', type='int',
-        default=60, help='Number of seconds to wait for after navigation.')
-    parser.add_option(
-        '--traffic-setting',  choices=cls._ALL_NET_CONFIGS,
-        default=traffic_setting.REGULAR_4G,
-        help='Traffic condition (string). Default to "%%default". Can be: %s' %
-         ', '.join(cls._ALL_NET_CONFIGS))
-
-  def CreateStorySet(self, options):
-    def Wait(action_runner):
-      action_runner.Wait(options.wait_time)
-    return page_sets.CTPageSet(
-      options.urls_list, options.user_agent, options.archive_data_file,
-      traffic_setting=options.traffic_setting,
-      run_page_interaction_callback=Wait)
-
-  @classmethod
-  def Name(cls):
-    return 'loading.cluster_telemetry'
diff --git a/tools/perf/benchmarks/rasterize_and_record_micro.py b/tools/perf/benchmarks/rasterize_and_record_micro.py
index 5c4bf6c0..92a6d35 100644
--- a/tools/perf/benchmarks/rasterize_and_record_micro.py
+++ b/tools/perf/benchmarks/rasterize_and_record_micro.py
@@ -4,10 +4,8 @@
 
 from core import perf_benchmark
 
-import ct_benchmarks_util
 from measurements import rasterize_and_record_micro
 import page_sets
-from page_sets import repaint_helpers
 from telemetry import benchmark
 
 
@@ -115,26 +113,3 @@
     return 'rasterize_and_record_micro.partial_invalidation'
 
 
-# Disabled because we do not plan on running CT benchmarks on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
-class RasterizeAndRecordMicroCT(_RasterizeAndRecordMicro):
-  """Measures rasterize and record performance for Cluster Telemetry."""
-
-  @classmethod
-  def Name(cls):
-    return 'rasterize_and_record_micro_ct'
-
-  @classmethod
-  def AddBenchmarkCommandLineArgs(cls, parser):
-    _RasterizeAndRecordMicro.AddBenchmarkCommandLineArgs(parser)
-    ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
-
-  @classmethod
-  def ProcessCommandLineArgs(cls, parser, args):
-    ct_benchmarks_util.ValidateCommandLineArgs(parser, args)
-
-  def CreateStorySet(self, options):
-    return page_sets.CTPageSet(
-        options.urls_list, options.user_agent, options.archive_data_file,
-        run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
diff --git a/tools/perf/contrib/cluster_telemetry/OWNERS b/tools/perf/contrib/cluster_telemetry/OWNERS
new file mode 100644
index 0000000..ad390b4
--- /dev/null
+++ b/tools/perf/contrib/cluster_telemetry/OWNERS
@@ -0,0 +1,4 @@
+rmistry@chromium.org
+
+per-file loading_ct.py=nednguyen@chromium.org
+per-file repaint*=wkorman@chromium.org
diff --git a/tools/perf/contrib/cluster_telemetry/__init__.py b/tools/perf/contrib/cluster_telemetry/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/perf/contrib/cluster_telemetry/__init__.py
diff --git a/tools/perf/benchmarks/ct_benchmarks_unittest.py b/tools/perf/contrib/cluster_telemetry/ct_benchmarks_unittest.py
similarity index 93%
rename from tools/perf/benchmarks/ct_benchmarks_unittest.py
rename to tools/perf/contrib/cluster_telemetry/ct_benchmarks_unittest.py
index e6b3570..30ba296 100644
--- a/tools/perf/benchmarks/ct_benchmarks_unittest.py
+++ b/tools/perf/contrib/cluster_telemetry/ct_benchmarks_unittest.py
@@ -7,9 +7,9 @@
 
 from telemetry.page import shared_page_state
 
-from benchmarks import rasterize_and_record_micro
-from benchmarks import repaint
-from benchmarks import skpicture_printer
+from contrib.cluster_telemetry import rasterize_and_record_micro_ct
+from contrib.cluster_telemetry import repaint
+from contrib.cluster_telemetry import skpicture_printer
 
 
 class MockErrorParser(object):
@@ -25,7 +25,7 @@
 
   def setUp(self):
     self.ct_benchmarks = [
-        rasterize_and_record_micro.RasterizeAndRecordMicroCT(),
+        rasterize_and_record_micro_ct.RasterizeAndRecordMicroCT(),
         repaint.RepaintCT(),
         skpicture_printer.SkpicturePrinterCT(),
     ]
diff --git a/tools/perf/ct_benchmarks_util.py b/tools/perf/contrib/cluster_telemetry/ct_benchmarks_util.py
similarity index 99%
rename from tools/perf/ct_benchmarks_util.py
rename to tools/perf/contrib/cluster_telemetry/ct_benchmarks_util.py
index 580f45ba..746ba2b 100755
--- a/tools/perf/ct_benchmarks_util.py
+++ b/tools/perf/contrib/cluster_telemetry/ct_benchmarks_util.py
@@ -3,7 +3,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-
 def AddBenchmarkCommandLineArgs(parser):
   parser.add_option('--user-agent',  action='store', type='string',
                     default=None, help='Options are mobile and desktop.')
diff --git a/tools/perf/contrib/cluster_telemetry/loading_ct.py b/tools/perf/contrib/cluster_telemetry/loading_ct.py
new file mode 100644
index 0000000..5f637e1d
--- /dev/null
+++ b/tools/perf/contrib/cluster_telemetry/loading_ct.py
@@ -0,0 +1,42 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from benchmarks import loading
+
+from contrib.cluster_telemetry import ct_benchmarks_util
+from contrib.cluster_telemetry import page_set
+
+from telemetry.page import traffic_setting
+
+
+# pylint: disable=protected-access
+class LoadingClusterTelemetry(loading._LoadingBase):
+
+  options = {'upload_results': True}
+
+  _ALL_NET_CONFIGS = traffic_setting.NETWORK_CONFIGS.keys()
+
+  @classmethod
+  def AddBenchmarkCommandLineArgs(cls, parser):
+    super(LoadingClusterTelemetry, cls).AddBenchmarkCommandLineArgs(parser)
+    ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
+    parser.add_option(
+        '--wait-time',  action='store', type='int',
+        default=60, help='Number of seconds to wait for after navigation.')
+    parser.add_option(
+        '--traffic-setting',  choices=cls._ALL_NET_CONFIGS,
+        default=traffic_setting.REGULAR_4G,
+        help='Traffic condition (string). Default to "%%default". Can be: %s' %
+         ', '.join(cls._ALL_NET_CONFIGS))
+
+  def CreateStorySet(self, options):
+    def Wait(action_runner):
+      action_runner.Wait(options.wait_time)
+    return page_set.CTPageSet(
+      options.urls_list, options.user_agent, options.archive_data_file,
+      traffic_setting=options.traffic_setting,
+      run_page_interaction_callback=Wait)
+
+  @classmethod
+  def Name(cls):
+    return 'loading.cluster_telemetry'
diff --git a/tools/perf/benchmarks/multipage_skpicture_printer.py b/tools/perf/contrib/cluster_telemetry/multipage_skpicture_printer.py
similarity index 86%
rename from tools/perf/benchmarks/multipage_skpicture_printer.py
rename to tools/perf/contrib/cluster_telemetry/multipage_skpicture_printer.py
index d74240f..3ad1d47a 100644
--- a/tools/perf/benchmarks/multipage_skpicture_printer.py
+++ b/tools/perf/contrib/cluster_telemetry/multipage_skpicture_printer.py
@@ -4,10 +4,10 @@
 
 from core import perf_benchmark
 
-import ct_benchmarks_util
-import page_sets
-from page_sets import repaint_helpers
-from telemetry import benchmark
+from contrib.cluster_telemetry import ct_benchmarks_util
+from contrib.cluster_telemetry import page_set
+from contrib.cluster_telemetry import repaint_helpers
+
 from telemetry.core import discover
 from telemetry import story
 
@@ -23,9 +23,6 @@
   return None
 
 
-# Disabled because we do not plan on running this mSKP benchmark on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
 class MultipageSkpicturePrinter(perf_benchmark.PerfBenchmark):
 
   @classmethod
@@ -58,9 +55,6 @@
     return story_set_class()
 
 
-# Disabled because we do not plan on running CT benchmarks on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
 class MultipageSkpicturePrinterCT(perf_benchmark.PerfBenchmark):
   """Captures mSKPs for Cluster Telemetry."""
 
@@ -84,6 +78,6 @@
         options.mskp_outdir)
 
   def CreateStorySet(self, options):
-    return page_sets.CTPageSet(
+    return page_set.CTPageSet(
         options.urls_list, options.user_agent, options.archive_data_file,
         run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
diff --git a/tools/perf/page_sets/ct_page_set.py b/tools/perf/contrib/cluster_telemetry/page_set.py
similarity index 100%
rename from tools/perf/page_sets/ct_page_set.py
rename to tools/perf/contrib/cluster_telemetry/page_set.py
diff --git a/tools/perf/contrib/cluster_telemetry/rasterize_and_record_micro_ct.py b/tools/perf/contrib/cluster_telemetry/rasterize_and_record_micro_ct.py
new file mode 100644
index 0000000..706338e
--- /dev/null
+++ b/tools/perf/contrib/cluster_telemetry/rasterize_and_record_micro_ct.py
@@ -0,0 +1,34 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from contrib.cluster_telemetry import ct_benchmarks_util
+from contrib.cluster_telemetry import page_set
+from contrib.cluster_telemetry import repaint_helpers
+
+from benchmarks import rasterize_and_record_micro
+
+
+# pylint: disable=protected-access
+class RasterizeAndRecordMicroCT(
+    rasterize_and_record_micro._RasterizeAndRecordMicro):
+  """Measures rasterize and record performance for Cluster Telemetry."""
+
+  @classmethod
+  def Name(cls):
+    return 'rasterize_and_record_micro_ct'
+
+  @classmethod
+  def AddBenchmarkCommandLineArgs(cls, parser):
+    (rasterize_and_record_micro._RasterizeAndRecordMicro.
+        AddBenchmarkCommandLineArgs(parser))
+    ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
+
+  @classmethod
+  def ProcessCommandLineArgs(cls, parser, args):
+    ct_benchmarks_util.ValidateCommandLineArgs(parser, args)
+
+  def CreateStorySet(self, options):
+    return page_set.CTPageSet(
+        options.urls_list, options.user_agent, options.archive_data_file,
+        run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
diff --git a/tools/perf/benchmarks/repaint.py b/tools/perf/contrib/cluster_telemetry/repaint.py
similarity index 83%
rename from tools/perf/benchmarks/repaint.py
rename to tools/perf/contrib/cluster_telemetry/repaint.py
index 3e1852c..aad4009 100644
--- a/tools/perf/benchmarks/repaint.py
+++ b/tools/perf/contrib/cluster_telemetry/repaint.py
@@ -2,19 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from core import perf_benchmark
+from contrib.cluster_telemetry import ct_benchmarks_util
+from contrib.cluster_telemetry import page_set
+from contrib.cluster_telemetry import repaint_helpers
 
-import ct_benchmarks_util
+from core import perf_benchmark
 from measurements import smoothness
 
-import page_sets
-from page_sets import repaint_helpers
 
-from telemetry import benchmark
-
-# Disabled because we do not plan on running CT benchmarks on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
 class RepaintCT(perf_benchmark.PerfBenchmark):
   """Measures repaint performance for Cluster Telemetry."""
 
@@ -41,7 +36,7 @@
     ct_benchmarks_util.ValidateCommandLineArgs(parser, args)
 
   def CreateStorySet(self, options):
-    return page_sets.CTPageSet(
+    return page_set.CTPageSet(
         options.urls_list, options.user_agent, options.archive_data_file,
         run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
 
diff --git a/tools/perf/page_sets/repaint_helpers.py b/tools/perf/contrib/cluster_telemetry/repaint_helpers.py
similarity index 100%
rename from tools/perf/page_sets/repaint_helpers.py
rename to tools/perf/contrib/cluster_telemetry/repaint_helpers.py
diff --git a/tools/perf/measurements/repaint_unittest.py b/tools/perf/contrib/cluster_telemetry/repaint_unittest.py
similarity index 97%
rename from tools/perf/measurements/repaint_unittest.py
rename to tools/perf/contrib/cluster_telemetry/repaint_unittest.py
index 83c7f13..97bdc210 100644
--- a/tools/perf/measurements/repaint_unittest.py
+++ b/tools/perf/contrib/cluster_telemetry/repaint_unittest.py
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from contrib.cluster_telemetry import repaint_helpers
+
+
 from telemetry import decorators
 from telemetry.page import page as page_module
 from telemetry.testing import options_for_unittests
@@ -9,7 +12,6 @@
 from telemetry.util import wpr_modes
 
 from measurements import smoothness
-from page_sets import repaint_helpers
 
 
 class TestRepaintPage(page_module.Page):
diff --git a/tools/perf/benchmarks/skpicture_printer.py b/tools/perf/contrib/cluster_telemetry/skpicture_printer.py
similarity index 87%
rename from tools/perf/benchmarks/skpicture_printer.py
rename to tools/perf/contrib/cluster_telemetry/skpicture_printer.py
index 09a844d..450f62a0 100644
--- a/tools/perf/benchmarks/skpicture_printer.py
+++ b/tools/perf/contrib/cluster_telemetry/skpicture_printer.py
@@ -4,9 +4,10 @@
 
 from core import perf_benchmark
 
-import ct_benchmarks_util
-import page_sets
-from page_sets import repaint_helpers
+from contrib.cluster_telemetry import ct_benchmarks_util
+from contrib.cluster_telemetry import page_set
+from contrib.cluster_telemetry import repaint_helpers
+
 from telemetry import benchmark
 from telemetry.core import discover
 from telemetry import story
@@ -23,9 +24,6 @@
   return None
 
 
-# Disabled because we do not plan on running this SKP benchmark on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
 @benchmark.Owner(emails=['rmistry@chromium.org'])
 class SkpicturePrinter(perf_benchmark.PerfBenchmark):
 
@@ -58,9 +56,6 @@
     return story_set_class()
 
 
-# Disabled because we do not plan on running CT benchmarks on the perf
-# waterfall any time soon.
-@benchmark.Disabled('all')
 class SkpicturePrinterCT(perf_benchmark.PerfBenchmark):
   """Captures SKPs for Cluster Telemetry."""
 
@@ -83,6 +78,6 @@
     return skpicture_printer.SkpicturePrinter(options.skp_outdir)
 
   def CreateStorySet(self, options):
-    return page_sets.CTPageSet(
+    return page_set.CTPageSet(
         options.urls_list, options.user_agent, options.archive_data_file,
         run_page_interaction_callback=repaint_helpers.WaitThenRepaint)
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 48f51c6..42be34d 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -698,19 +698,6 @@
   return isolated_scripts
 
 
-# List of benchmarks that are to never be run on a waterfall.
-BENCHMARK_NAME_BLACKLIST = [
-    'multipage_skpicture_printer',
-    'multipage_skpicture_printer_ct',
-    'rasterize_and_record_micro_ct',
-    'repaint_ct',
-    'multipage_skpicture_printer',
-    'multipage_skpicture_printer_ct',
-    'skpicture_printer',
-    'skpicture_printer_ct',
-]
-
-
 # Overrides the default 2 hour timeout for swarming tasks.
 BENCHMARK_SWARMING_TIMEOUTS = {
     'loading.mobile': 14400, # 4 hours
@@ -733,12 +720,6 @@
   all_benchmarks = discover.DiscoverClasses(
       benchmarks_dir, top_level_dir, benchmark_module.Benchmark,
       index_by_class_name=True).values()
-  # Remove all blacklisted benchmarks
-  for blacklisted in BENCHMARK_NAME_BLACKLIST:
-    for benchmark in all_benchmarks:
-      if benchmark.Name() == blacklisted:
-        all_benchmarks.remove(benchmark)
-        break
 
   return sorted(all_benchmarks, key=lambda b: b.Name())
 
diff --git a/tools/perf/unowned_benchmarks.txt b/tools/perf/unowned_benchmarks.txt
index bebe0ba..375befb 100644
--- a/tools/perf/unowned_benchmarks.txt
+++ b/tools/perf/unowned_benchmarks.txt
@@ -7,7 +7,6 @@
 gpu_times.gpu_rasterization.top_25_smooth
 gpu_times.key_mobile_sites_smooth
 gpu_times.top_25_smooth
-loading.cluster_telemetry
 load_library_perf_tests
 power.idle_platform
 power.steady_state
diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
index 372bbfc..753a559 100644
--- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
+++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
@@ -18,11 +18,11 @@
 import android.os.Build;
 import android.provider.MediaStore;
 import android.text.TextUtils;
-import android.util.Log;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContentUriUtils;
 import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -39,6 +39,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A dialog that is triggered from a file input field that allows a user to select a file based on
@@ -57,6 +58,9 @@
     private static final String ALL_AUDIO_TYPES = AUDIO_TYPE + "*";
     private static final String ANY_TYPES = "*/*";
 
+    // Duration before temporary camera file is cleaned up, in milliseconds.
+    private static final long DURATION_BEFORE_FILE_CLEAN_UP_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
+
     // A list of some of the more popular image extensions. Not meant to be
     // exhaustive, but should cover the vast majority of image types.
     private static final String[] POPULAR_IMAGE_EXTENSIONS = new String[] {".apng", ".bmp", ".gif",
@@ -617,6 +621,32 @@
         }
     }
 
+    /**
+     * Clears all captured camera files.
+     */
+    public static void clearCapturedCameraFiles() {
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    File path = UiUtils.getDirectoryForImageCapture(
+                            ContextUtils.getApplicationContext());
+                    if (!path.isDirectory()) return;
+                    File[] files = path.listFiles();
+                    if (files == null) return;
+                    long now = System.currentTimeMillis();
+                    for (File file : files) {
+                        if (now - file.lastModified() > DURATION_BEFORE_FILE_CLEAN_UP_IN_MILLIS) {
+                            if (!file.delete()) Log.e(TAG, "Failed to delete: " + file);
+                        }
+                    }
+                } catch (IOException e) {
+                    Log.w(TAG, "Failed to delete captured camera files.", e);
+                }
+            }
+        });
+    }
+
     @VisibleForTesting
     @CalledByNative
     static SelectFileDialog create(long nativeSelectFileDialog) {
diff --git a/ui/app_list/demo/app_list_demo_views.cc b/ui/app_list/demo/app_list_demo_views.cc
index 8f0a806b..9d11240 100644
--- a/ui/app_list/demo/app_list_demo_views.cc
+++ b/ui/app_list/demo/app_list_demo_views.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
diff --git a/ui/app_list/presenter/BUILD.gn b/ui/app_list/presenter/BUILD.gn
index 13b211b..3af3c3fa 100644
--- a/ui/app_list/presenter/BUILD.gn
+++ b/ui/app_list/presenter/BUILD.gn
@@ -16,7 +16,6 @@
     "//services/ui/public/interfaces",
   ]
 
-  component_output_prefix = "app_list_presenter_mojom"
   export_class_attribute = "APP_LIST_PRESENTER_EXPORT"
   export_define = "APP_LIST_PRESENTER_IMPLEMENTATION=1"
   export_header = "ui/app_list/presenter/app_list_presenter_export.h"
diff --git a/ui/aura/mus/mus_context_factory.cc b/ui/aura/mus/mus_context_factory.cc
index 9517875..7169806 100644
--- a/ui/aura/mus/mus_context_factory.cc
+++ b/ui/aura/mus/mus_context_factory.cc
@@ -4,16 +4,28 @@
 
 #include "ui/aura/mus/mus_context_factory.h"
 
+#include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "cc/base/switches.h"
 #include "services/ui/public/cpp/gpu/gpu.h"
 #include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/window_tree_host.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/compositor_util.h"
+#include "ui/display/display_switches.h"
+#include "ui/gfx/switches.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace aura {
 
 MusContextFactory::MusContextFactory(ui::Gpu* gpu)
-    : gpu_(gpu), weak_ptr_factory_(this) {}
+    : gpu_(gpu),
+      renderer_settings_(ui::CreateRendererSettings(
+          [](gfx::BufferFormat format, gfx::BufferUsage usage) -> uint32_t {
+            // TODO(sad): http://crbug.com/675431
+            return GL_TEXTURE_2D;
+          })),
+      weak_ptr_factory_(this) {}
 
 MusContextFactory::~MusContextFactory() {}
 
@@ -62,12 +74,6 @@
   return 60.0;
 }
 
-uint32_t MusContextFactory::GetImageTextureTarget(gfx::BufferFormat format,
-                                                  gfx::BufferUsage usage) {
-  // TODO(sad): http://crbug.com/675431
-  return GL_TEXTURE_2D;
-}
-
 gpu::GpuMemoryBufferManager* MusContextFactory::GetGpuMemoryBufferManager() {
   return gpu_->gpu_memory_buffer_manager();
 }
@@ -76,4 +82,8 @@
   return raster_thread_helper_.task_graph_runner();
 }
 
+const cc::RendererSettings& MusContextFactory::GetRendererSettings() const {
+  return renderer_settings_;
+}
+
 }  // namespace aura
diff --git a/ui/aura/mus/mus_context_factory.h b/ui/aura/mus/mus_context_factory.h
index 11b2065..fd8875c 100644
--- a/ui/aura/mus/mus_context_factory.h
+++ b/ui/aura/mus/mus_context_factory.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "cc/output/renderer_settings.h"
 #include "cc/surfaces/surface_manager.h"
 #include "services/ui/public/cpp/raster_thread_helper.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
@@ -47,15 +48,15 @@
   scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
   void RemoveCompositor(ui::Compositor* compositor) override;
   double GetRefreshRate() const override;
-  uint32_t GetImageTextureTarget(gfx::BufferFormat format,
-                                 gfx::BufferUsage usage) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
+  const cc::RendererSettings& GetRendererSettings() const override;
   void AddObserver(ui::ContextFactoryObserver* observer) override {}
   void RemoveObserver(ui::ContextFactoryObserver* observer) override {}
 
   ui::RasterThreadHelper raster_thread_helper_;
   ui::Gpu* gpu_;
+  const cc::RendererSettings renderer_settings_;
   base::WeakPtrFactory<MusContextFactory> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MusContextFactory);
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index ba60827..b20b90a 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -11,6 +11,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/histogram_tester.h"
diff --git a/ui/base/x/selection_requestor.cc b/ui/base/x/selection_requestor.cc
index d4e13d8..324d642 100644
--- a/ui/base/x/selection_requestor.cc
+++ b/ui/base/x/selection_requestor.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <X11/Xlib.h>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "ui/base/x/selection_utils.h"
 #include "ui/base/x/x11_util.h"
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index c8b233b..83ca119 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -26,6 +26,8 @@
     "compositor_observer.h",
     "compositor_switches.cc",
     "compositor_switches.h",
+    "compositor_util.cc",
+    "compositor_util.h",
     "compositor_vsync_manager.cc",
     "compositor_vsync_manager.h",
     "debug_utils.cc",
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 6676c55d..8ddeb888 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -82,17 +82,6 @@
   refresh_rate_ = settings.renderer_settings.refresh_rate =
       context_factory_->GetRefreshRate();
   settings.main_frame_before_activation_enabled = false;
-  settings.renderer_settings.partial_swap_enabled =
-      !command_line->HasSwitch(switches::kUIDisablePartialSwap);
-#if defined(OS_WIN)
-  settings.renderer_settings.finish_rendering_on_resize = true;
-#elif defined(OS_MACOSX)
-  settings.renderer_settings.release_overlay_resources_after_gpu_query = true;
-#endif
-  settings.renderer_settings.gl_composited_texture_quad_border =
-      command_line->HasSwitch(cc::switches::kGlCompositedTextureQuadBorder);
-  settings.renderer_settings.show_overdraw_feedback =
-      command_line->HasSwitch(cc::switches::kShowOverdrawFeedback);
 
   if (command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders)) {
     std::string layer_borders_string = command_line->GetSwitchValueASCII(
@@ -141,44 +130,25 @@
 
   settings.use_zero_copy = IsUIZeroCopyEnabled();
 
-  if (command_line->HasSwitch(switches::kUIEnableRGBA4444Textures))
-    settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
-
   settings.use_layer_lists =
       command_line->HasSwitch(cc::switches::kUIEnableLayerLists);
 
   settings.enable_color_correct_rasterization =
       command_line->HasSwitch(switches::kEnableColorCorrectRendering);
-  settings.renderer_settings.enable_color_correct_rendering =
-      settings.enable_color_correct_rasterization ||
-      command_line->HasSwitch(switches::kEnableHDR);
 
   // UI compositor always uses partial raster if not using zero-copy. Zero copy
   // doesn't currently support partial raster.
   settings.use_partial_raster = !settings.use_zero_copy;
 
-  // Populate buffer_to_texture_target_map for all buffer usage/formats.
-  for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
-       ++usage_idx) {
-    gfx::BufferUsage usage = static_cast<gfx::BufferUsage>(usage_idx);
-    for (int format_idx = 0;
-         format_idx <= static_cast<int>(gfx::BufferFormat::LAST);
-         ++format_idx) {
-      gfx::BufferFormat format = static_cast<gfx::BufferFormat>(format_idx);
-      uint32_t target = context_factory_->GetImageTextureTarget(format, usage);
-      settings.renderer_settings
-          .buffer_to_texture_target_map[std::make_pair(usage, format)] = target;
-    }
-  }
-
   settings.gpu_memory_policy.bytes_limit_when_visible = 512 * 1024 * 1024;
   settings.gpu_memory_policy.priority_cutoff_when_visible =
       gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
 
   settings.disallow_non_exact_resource_reuse =
       command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
-  settings.renderer_settings.disallow_non_exact_resource_reuse =
-      settings.disallow_non_exact_resource_reuse;
+
+  // TODO(staraz): LayerTreeSettings shouldn't have a RendererSettings.
+  settings.renderer_settings = context_factory_->GetRendererSettings();
 
   base::TimeTicks before_create = base::TimeTicks::Now();
 
@@ -542,10 +512,6 @@
   host_->SetDebugState(debug_state);
 }
 
-const cc::RendererSettings& Compositor::GetRendererSettings() const {
-  return host_->GetSettings().renderer_settings;
-}
-
 std::unique_ptr<CompositorLock> Compositor::GetCompositorLock(
     CompositorLockClient* client,
     base::TimeDelta timeout) {
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 59396ee0..54a104a 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -152,16 +152,15 @@
   // Returns refresh rate. Tests may return higher values.
   virtual double GetRefreshRate() const = 0;
 
-  // Returns the OpenGL target to use for image textures.
-  virtual uint32_t GetImageTextureTarget(gfx::BufferFormat format,
-                                         gfx::BufferUsage usage) = 0;
-
   // Gets the GPU memory buffer manager.
   virtual gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() = 0;
 
   // Gets the task graph runner.
   virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
 
+  // Gets the renderer settings.
+  virtual const cc::RendererSettings& GetRendererSettings() const = 0;
+
   virtual void AddObserver(ContextFactoryObserver* observer) = 0;
 
   virtual void RemoveObserver(ContextFactoryObserver* observer) = 0;
@@ -355,7 +354,6 @@
 
   const cc::LayerTreeDebugState& GetLayerTreeDebugState() const;
   void SetLayerTreeDebugState(const cc::LayerTreeDebugState& debug_state);
-  const cc::RendererSettings& GetRendererSettings() const;
 
   LayerAnimatorCollection* layer_animator_collection() {
     return &layer_animator_collection_;
diff --git a/ui/compositor/compositor_util.cc b/ui/compositor/compositor_util.cc
new file mode 100644
index 0000000..39109bc9
--- /dev/null
+++ b/ui/compositor/compositor_util.cc
@@ -0,0 +1,55 @@
+// 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 "ui/compositor/compositor_util.h"
+
+#include "base/command_line.h"
+#include "cc/base/switches.h"
+#include "cc/output/renderer_settings.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/display/display_switches.h"
+#include "ui/gfx/switches.h"
+
+namespace ui {
+
+cc::RendererSettings CreateRendererSettings(uint32_t (
+    *get_texture_target)(gfx::BufferFormat format, gfx::BufferUsage usage)) {
+  cc::RendererSettings renderer_settings;
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  renderer_settings.partial_swap_enabled =
+      !command_line->HasSwitch(switches::kUIDisablePartialSwap);
+#if defined(OS_WIN)
+  renderer_settings.finish_rendering_on_resize = true;
+#elif defined(OS_MACOSX)
+  renderer_settings.release_overlay_resources_after_gpu_query = true;
+#endif
+  renderer_settings.gl_composited_texture_quad_border =
+      command_line->HasSwitch(cc::switches::kGlCompositedTextureQuadBorder);
+  renderer_settings.show_overdraw_feedback =
+      command_line->HasSwitch(cc::switches::kShowOverdrawFeedback);
+  if (command_line->HasSwitch(switches::kUIEnableRGBA4444Textures))
+    renderer_settings.preferred_tile_format = cc::RGBA_4444;
+  renderer_settings.enable_color_correct_rendering =
+      command_line->HasSwitch(switches::kEnableColorCorrectRendering) ||
+      command_line->HasSwitch(switches::kEnableHDR);
+  // Populate buffer_to_texture_target_map for all buffer usage/formats.
+  for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
+       ++usage_idx) {
+    gfx::BufferUsage usage = static_cast<gfx::BufferUsage>(usage_idx);
+    for (int format_idx = 0;
+         format_idx <= static_cast<int>(gfx::BufferFormat::LAST);
+         ++format_idx) {
+      gfx::BufferFormat format = static_cast<gfx::BufferFormat>(format_idx);
+      renderer_settings
+          .buffer_to_texture_target_map[std::make_pair(usage, format)] =
+          get_texture_target(format, usage);
+    }
+  }
+  renderer_settings.disallow_non_exact_resource_reuse =
+      command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
+
+  return renderer_settings;
+}
+
+}  // namespace ui
diff --git a/ui/compositor/compositor_util.h b/ui/compositor/compositor_util.h
new file mode 100644
index 0000000..9164dba
--- /dev/null
+++ b/ui/compositor/compositor_util.h
@@ -0,0 +1,24 @@
+// 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 UI_COMPOSITOR_COMPOSITOR_UTIL_H_
+#define UI_COMPOSITOR_COMPOSITOR_UTIL_H_
+
+#include <stdint.h>
+
+#include "ui/compositor/compositor_export.h"
+#include "ui/gfx/buffer_types.h"
+
+namespace cc {
+class RendererSettings;
+}
+
+namespace ui {
+
+COMPOSITOR_EXPORT cc::RendererSettings CreateRendererSettings(uint32_t (
+    *get_texture_target)(gfx::BufferFormat format, gfx::BufferUsage usage));
+
+}  // namespace ui
+
+#endif  // UI_COMPOSITOR_COMPOSITOR_UTIL_H_
diff --git a/ui/compositor/test/fake_context_factory.cc b/ui/compositor/test/fake_context_factory.cc
index a1f4219b..cc0cd26 100644
--- a/ui/compositor/test/fake_context_factory.cc
+++ b/ui/compositor/test/fake_context_factory.cc
@@ -4,15 +4,43 @@
 
 #include "ui/compositor/test/fake_context_factory.h"
 
+#include "base/command_line.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "cc/base/switches.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_sink_client.h"
 #include "cc/scheduler/begin_frame_source.h"
 #include "cc/scheduler/delay_based_time_source.h"
 #include "cc/test/fake_compositor_frame_sink.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/display/display_switches.h"
+#include "ui/gfx/switches.h"
 
 namespace ui {
 
+FakeContextFactory::FakeContextFactory() {
+#if defined(OS_WIN)
+  renderer_settings_.finish_rendering_on_resize = true;
+#elif defined(OS_MACOSX)
+  renderer_settings_.release_overlay_resources_after_gpu_query = true;
+#endif
+  // Populate buffer_to_texture_target_map for all buffer usage/formats.
+  for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
+       ++usage_idx) {
+    gfx::BufferUsage usage = static_cast<gfx::BufferUsage>(usage_idx);
+    for (int format_idx = 0;
+         format_idx <= static_cast<int>(gfx::BufferFormat::LAST);
+         ++format_idx) {
+      gfx::BufferFormat format = static_cast<gfx::BufferFormat>(format_idx);
+      renderer_settings_
+          .buffer_to_texture_target_map[std::make_pair(usage, format)] =
+          GL_TEXTURE_2D;
+    }
+  }
+}
+
+FakeContextFactory::~FakeContextFactory() = default;
+
 const cc::CompositorFrame& FakeContextFactory::GetLastCompositorFrame() const {
   return *frame_sink_->last_sent_frame();
 }
@@ -37,11 +65,6 @@
   return 200.0;
 }
 
-uint32_t FakeContextFactory::GetImageTextureTarget(gfx::BufferFormat format,
-                                                   gfx::BufferUsage usage) {
-  return GL_TEXTURE_2D;
-}
-
 gpu::GpuMemoryBufferManager* FakeContextFactory::GetGpuMemoryBufferManager() {
   return &gpu_memory_buffer_manager_;
 }
@@ -50,4 +73,8 @@
   return &task_graph_runner_;
 }
 
+const cc::RendererSettings& FakeContextFactory::GetRendererSettings() const {
+  return renderer_settings_;
+}
+
 }  // namespace ui
diff --git a/ui/compositor/test/fake_context_factory.h b/ui/compositor/test/fake_context_factory.h
index 99e8250..7db8233 100644
--- a/ui/compositor/test/fake_context_factory.h
+++ b/ui/compositor/test/fake_context_factory.h
@@ -5,6 +5,7 @@
 #ifndef UI_COMPOSITOR_TEST_FAKE_CONTEXT_FACTORY_H_
 #define UI_COMPOSITOR_TEST_FAKE_CONTEXT_FACTORY_H_
 
+#include "cc/output/renderer_settings.h"
 #include "cc/test/test_gpu_memory_buffer_manager.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "ui/compositor/compositor.h"
@@ -21,8 +22,8 @@
 
 class FakeContextFactory : public ui::ContextFactory {
  public:
-  FakeContextFactory() = default;
-  ~FakeContextFactory() override = default;
+  FakeContextFactory();
+  ~FakeContextFactory() override;
 
   const cc::CompositorFrame& GetLastCompositorFrame() const;
 
@@ -32,10 +33,9 @@
   scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
   void RemoveCompositor(ui::Compositor* compositor) override;
   double GetRefreshRate() const override;
-  uint32_t GetImageTextureTarget(gfx::BufferFormat format,
-                                 gfx::BufferUsage usage) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
+  const cc::RendererSettings& GetRendererSettings() const override;
   void AddObserver(ui::ContextFactoryObserver* observer) override {}
   void RemoveObserver(ui::ContextFactoryObserver* observer) override {}
 
@@ -43,6 +43,7 @@
   cc::FakeCompositorFrameSink* frame_sink_ = nullptr;
   cc::TestTaskGraphRunner task_graph_runner_;
   cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
+  cc::RendererSettings renderer_settings_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeContextFactory);
 };
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index d15a9988..8d84e41 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread.h"
+#include "cc/base/switches.h"
 #include "cc/output/context_provider.h"
 #include "cc/output/output_surface_client.h"
 #include "cc/output/output_surface_frame.h"
@@ -29,6 +30,8 @@
 #include "ui/compositor/layer.h"
 #include "ui/compositor/reflector.h"
 #include "ui/compositor/test/in_process_context_provider.h"
+#include "ui/display/display_switches.h"
+#include "ui/gfx/switches.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/test/gl_surface_test_support.h"
 
@@ -139,6 +142,25 @@
   DCHECK_NE(gl::GetGLImplementation(), gl::kGLImplementationNone)
       << "If running tests, ensure that main() is calling "
       << "gl::GLSurfaceTestSupport::InitializeOneOff()";
+
+#if defined(OS_WIN)
+  renderer_settings_.finish_rendering_on_resize = true;
+#elif defined(OS_MACOSX)
+  renderer_settings_.release_overlay_resources_after_gpu_query = true;
+#endif
+  // Populate buffer_to_texture_target_map for all buffer usage/formats.
+  for (int usage_idx = 0; usage_idx <= static_cast<int>(gfx::BufferUsage::LAST);
+       ++usage_idx) {
+    gfx::BufferUsage usage = static_cast<gfx::BufferUsage>(usage_idx);
+    for (int format_idx = 0;
+         format_idx <= static_cast<int>(gfx::BufferFormat::LAST);
+         ++format_idx) {
+      gfx::BufferFormat format = static_cast<gfx::BufferFormat>(format_idx);
+      renderer_settings_
+          .buffer_to_texture_target_map[std::make_pair(usage, format)] =
+          GL_TEXTURE_2D;
+    }
+  }
 }
 
 InProcessContextFactory::~InProcessContextFactory() {
@@ -214,11 +236,11 @@
       display_output_surface->capabilities().max_frames_pending));
 
   data->display = base::MakeUnique<cc::Display>(
-      &shared_bitmap_manager_, &gpu_memory_buffer_manager_,
-      compositor->GetRendererSettings(), compositor->frame_sink_id(),
-      begin_frame_source.get(), std::move(display_output_surface),
-      std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(
-                                compositor->task_runner().get()));
+      &shared_bitmap_manager_, &gpu_memory_buffer_manager_, renderer_settings_,
+      compositor->frame_sink_id(), begin_frame_source.get(),
+      std::move(display_output_surface), std::move(scheduler),
+      base::MakeUnique<cc::TextureMailboxDeleter>(
+          compositor->task_runner().get()));
   // Note that we are careful not to destroy a prior |data->begin_frame_source|
   // until we have reset |data->display|.
   data->begin_frame_source = std::move(begin_frame_source);
@@ -275,12 +297,6 @@
   return refresh_rate_;
 }
 
-uint32_t InProcessContextFactory::GetImageTextureTarget(
-    gfx::BufferFormat format,
-    gfx::BufferUsage usage) {
-  return GL_TEXTURE_2D;
-}
-
 gpu::GpuMemoryBufferManager*
 InProcessContextFactory::GetGpuMemoryBufferManager() {
   return &gpu_memory_buffer_manager_;
@@ -312,6 +328,11 @@
   per_compositor_data_[compositor]->display->Resize(size);
 }
 
+const cc::RendererSettings& InProcessContextFactory::GetRendererSettings()
+    const {
+  return renderer_settings_;
+}
+
 void InProcessContextFactory::AddObserver(ContextFactoryObserver* observer) {
   observer_list_.AddObserver(observer);
 }
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h
index d196628..bb41ede54 100644
--- a/ui/compositor/test/in_process_context_factory.h
+++ b/ui/compositor/test/in_process_context_factory.h
@@ -57,8 +57,6 @@
   scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
   void RemoveCompositor(Compositor* compositor) override;
   double GetRefreshRate() const override;
-  uint32_t GetImageTextureTarget(gfx::BufferFormat format,
-                                 gfx::BufferUsage usage) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   cc::FrameSinkId AllocateFrameSinkId() override;
@@ -76,6 +74,7 @@
                                  base::TimeTicks timebase,
                                  base::TimeDelta interval) override {}
   void SetOutputIsSecure(ui::Compositor* compositor, bool secure) override {}
+  const cc::RendererSettings& GetRendererSettings() const override;
   void AddObserver(ContextFactoryObserver* observer) override;
   void RemoveObserver(ContextFactoryObserver* observer) override;
 
@@ -96,6 +95,7 @@
   cc::SurfaceManager* surface_manager_;
   base::ObserverList<ContextFactoryObserver> observer_list_;
 
+  cc::RendererSettings renderer_settings_;
   using PerCompositorDataMap =
       base::hash_map<ui::Compositor*, std::unique_ptr<PerCompositorData>>;
   PerCompositorDataMap per_compositor_data_;
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index 24b6a2ba..2a93385 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/ui/events/ozone/evdev/event_thread_evdev.cc b/ui/events/ozone/evdev/event_thread_evdev.cc
index c963428..d0dc561 100644
--- a/ui/events/ozone/evdev/event_thread_evdev.cc
+++ b/ui/events/ozone/evdev/event_thread_evdev.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/logging.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 9dd93f3..c472235e 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
diff --git a/ui/gfx/animation/animation_unittest.cc b/ui/gfx/animation/animation_unittest.cc
index 8146250..85ce255 100644
--- a/ui/gfx/animation/animation_unittest.cc
+++ b/ui/gfx/animation/animation_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
diff --git a/ui/gfx/font_fallback_win_unittest.cc b/ui/gfx/font_fallback_win_unittest.cc
index c5e2b34..8629f6f 100644
--- a/ui/gfx/font_fallback_win_unittest.cc
+++ b/ui/gfx/font_fallback_win_unittest.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ui/gfx/font_fallback_win.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/font_fallback_win.h"
 
 namespace gfx {
 
diff --git a/ui/gfx/text_elider_unittest.cc b/ui/gfx/text_elider_unittest.cc
index ae6fac4..4620d06e 100644
--- a/ui/gfx/text_elider_unittest.cc
+++ b/ui/gfx/text_elider_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/login/account_picker/md_screen_account_picker.js b/ui/login/account_picker/md_screen_account_picker.js
index 1db4ae6..c156d0e9b 100644
--- a/ui/login/account_picker/md_screen_account_picker.js
+++ b/ui/login/account_picker/md_screen_account_picker.js
@@ -198,20 +198,18 @@
 
         var bubbleAnchor;
         var attachment;
-        if (activatedPod.pinContainer) {
-          // Anchor the bubble to the input field.
-          bubbleAnchor = (
-              activatedPod.getElementsByClassName('auth-container'))[0];
-          if (!bubbleAnchor) {
-            console.error('auth-container not found!');
-            bubbleAnchor = activatedPod.mainInput;
-          }
-          attachment = cr.ui.Bubble.Attachment.RIGHT;
-        } else {
-          // Anchor the bubble to the pod instead of the input.
-          bubbleAnchor = activatedPod;
-          attachment = cr.ui.Bubble.Attachment.BOTTOM;
+        // Anchor the bubble to the input field.
+        bubbleAnchor =
+            activatedPod.getElementsByClassName('auth-container')[0];
+        if (!bubbleAnchor) {
+          console.error('auth-container not found!');
+          bubbleAnchor = activatedPod.mainInput;
         }
+        if (activatedPod.pinContainer &&
+            activatedPod.pinContainer.style.visibility == 'visible')
+          attachment = cr.ui.Bubble.Attachment.RIGHT;
+        else
+          attachment = cr.ui.Bubble.Attachment.BOTTOM;
 
         var bubble = $('bubble');
 
diff --git a/ui/login/account_picker/md_user_pod_row.css b/ui/login/account_picker/md_user_pod_row.css
index 0f43faf..68bf6ef 100644
--- a/ui/login/account_picker/md_user_pod_row.css
+++ b/ui/login/account_picker/md_user_pod_row.css
@@ -25,18 +25,14 @@
 
 .pod {
   -webkit-tap-highlight-color: transparent;
-  background-color: white;
   border-radius: 2px;
-  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2),
-              0 2px 6px rgba(0, 0, 0, 0.15),
-              0 3px 0 rgba(0, 0, 0, 0.08);
   cursor: pointer;
-  height: 213px;
+  height: 346px;
   outline: none;
   position: absolute;
   top: 0;
   transform: scale3d(0.9, 0.9, 0.9);
-  width: 180px;
+  width: 306px;
   z-index: 0;
 }
 
@@ -75,17 +71,16 @@
 }
 
 .user-image-pane {
-  background-color: white;
-  height: 160px;
-  left: 10px;
+  height: 96px;
+  left: 105px;
   position: absolute;
-  top: 10px;
+  top: 54px;
   transition: height 180ms ease-in-out,
               left 180ms ease-in-out,
               right 180ms ease-in-out,
               top 180ms ease-in-out,
               width 180ms ease-in-out;
-  width: 160px;
+  width: 96px;
   z-index: 3;
 }
 
@@ -102,6 +97,12 @@
   width: 100%;
 }
 
+.user-image {
+  border-radius: 50%;
+  height: 100%;
+  width: 100%;
+}
+
 .pod .user-image {
   flex: none;
 }
@@ -139,9 +140,7 @@
 }
 
 .main-pane {
-  left: 10px;
   position: absolute;
-  top: 10px;
   z-index: 2;
 }
 
@@ -150,12 +149,19 @@
   right: 10px;
 }
 
-.name-container,
-.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
-  background-color: white;
+.name-container {
   display: flex;
   position: absolute;
-  top: 160px;
+  top: 182px;
+}
+
+.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
+  display: flex;
+  height: 40px;
+  left: 51px;
+  padding-bottom: 16px;
+  position: absolute;
+  top: 244px;
 /* On chromeos we extend the width to cover the padding on the user pods. This
  is so the submit button on chromeos can extend onto the padding as shown on
  mocks. */
@@ -163,24 +169,26 @@
   width: 160px;
 </if>
 <if expr="chromeos">
-  width: 170px;
+  width: 204px;
 </if>
 }
 
+polygon #arrow[active] {
+  fill: #7BAAF7;
+  opacity: 1;
+}
+
 .auth-container .submit-button[disabled] {
-  color: #000;
-  opacity: 0.26;
+  color: #FFFFFF;
+  opacity: 0.34;
 }
 
 .auth-container .submit-button {
-  box-sizing: border-box;
-  color: var(--google-blue-500);
-  height: 43px;
-  min-height: 43px;
-  min-width: 43px;
-  padding: 11.5px 10px;
-  position: relative;
-  width: 43px;
+  color: #7BAAF7;
+  height: 40px;
+  opacity: 1;
+  padding: 12px 0 4px 0;
+  width: 24px;
 }
 
 .auth-container .submit-button.error-shown {
@@ -192,7 +200,7 @@
 }
 
 .pod.focused .name-container {
-  display: none;
+  display: flex;
 }
 
 .pod.focused.multiprofiles-policy-applied .name-container {
@@ -200,14 +208,13 @@
 }
 
 .name {
-  color: #565656;
+  color: #FFFFFF;
   /* This should be 15.6px - the equivalent of 14px at 90% scale. */
   flex: auto;
-  font-size: 16px;
-  margin-top: 12px;
+  font-family: "Roboto";
+  font-size: 26px;
   outline: none;
   overflow: hidden;
-  padding: 0 6px;
   text-align: center;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -220,6 +227,18 @@
   display: none;
 }
 
+#input-line {
+  opacity: 0.34;
+  position: absolute;
+  stroke: #FFFFFF;
+  stroke-width: 1;
+  top: 40px;
+}
+
+#input-line[active] {
+  opacity: 1;
+}
+
 .pod[is-active-directory] .reauth-warning {
   display: none;
 }
@@ -231,18 +250,25 @@
 }
 
 .password-container {
-  flex: auto;
+  height: 40px;
+  width: 180px;
 }
 
 .pod input[type='password'] {
-  background-color: white;
+  background-color: transparent;
   border: none;
-  padding: 4px 6px;
-  position: relative;
-  top: 6px;
+  color: #FFFFFF;
+  font-family: "Roboto";
+  font-size: 13px;
+  height: 100%;
+  padding: 0;
   width: 100%;
 }
 
+.pod input[type='password']::-webkit-input-placeholder {
+  opacity: 0.34;
+}
+
 .capslock-hint-container {
   display: none;
 }
@@ -458,7 +484,6 @@
   white-space: nowrap;
 }
 
-.action-box-area,
 .user-type-icon-area {
   background-color: white;
   border-radius: 2px;
@@ -469,13 +494,13 @@
 .action-box-area {
   opacity: 0;
   outline: none;
-  right: 0;
   transition: opacity 100ms;
   z-index: 4;
 }
 
 html[dir=rtl] .action-box-area {
   left: 0;
+  position: absolute;
   right: auto;
 }
 
@@ -487,18 +512,10 @@
 }
 
 .action-box-button {
-  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_NORMAL);
-  height: 13px;
-  margin: 5px;
-  width: 13px;
-}
-
-.action-box-button:hover {
-  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_HOVER);
-}
-
-.action-box-area.active .action-box-button {
-  background-image: url(chrome://theme/IDR_OOBE_ACTION_BOX_BUTTON_PRESSED);
+  height: 24px;
+  margin: 3px 0 0 8px;
+  padding: 0;
+  width: 24px;
 }
 
 .action-box-area .action-box-icon {
@@ -588,14 +605,12 @@
 }
 
 .action-box-area.active ~ .action-box-menu {
-  background-color: white;
-  border: 1px solid lightgray;
+  background-color: rgba(0, 0, 0, .34);
   border-radius: 2px;
   display: flex;
   flex-direction: column;
   font-size: 13px;
-  position: absolute;
-  right: 5px;
+  margin: 3px 0 0 12px;
   width: 220px;
 }
 
@@ -608,7 +623,7 @@
 }
 
 .action-box-area.active ~ .action-box-menu:not(.menu-moved-up) {
-  top: 18px;
+  top: 200px;
 }
 
 .action-box-area.active ~ .action-box-menu.menu-moved-up {
@@ -625,10 +640,10 @@
 }
 
 .action-box-menu-title {
-  color: #757575;
+  color: #FFFFFF;
   display: flex;
   flex-direction: column;
-  padding: 7px 20px;
+  padding: 13px 14px 18px;
 }
 
 .action-box-menu-title:focus {
@@ -638,36 +653,43 @@
 .action-box-menu-title-name,
 .action-box-menu-title-email {
   flex: none;
-  height: 23px;
-  line-height: 19px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
 
+.action-box-menu-title-name {
+  padding-bottom: 7px;
+}
+
+.action-box-menu-title-email {
+  opacity: 0.54;
+}
+
 .action-box-menu-remove {
-  border-top: 1px solid lightgray;
-  line-height: 19px;
-  min-height: 24px;
+  border-top: 0.25px solid grey;
+  color: #7BAAF7;
   outline: none;
-  padding: 12px 20px 7px;
+  padding: 18px 14px;
 }
 
 .action-box-menu-remove:hover,
 .action-box-menu-remove:focus {
-  background-color: #f3f3f3;
+  background-color: grey;
+  color: white;
 }
 
 .action-box-remove-user-warning {
-  border-top: 1px solid lightgray;
-  font-size: 12px;
+  border-top: 0.25px solid grey;
+  color: white;
+  font-size: 13px;
   line-height: 18px;
-  padding: 20px;
+  padding: 13px 14px 18px;
 }
 
 .action-box-remove-user-warning > div,
 .action-box-remove-user-warning > table {
-  padding-bottom: 20px;
+  padding-bottom: 19px;
 }
 
 .total-count {
@@ -748,7 +770,7 @@
 }
 
 .pod.public-account.expanded .name-container {
-  display: none;
+  display: flex;
 }
 
 .pod.public-account .learn-more-container {
diff --git a/ui/login/account_picker/md_user_pod_row.js b/ui/login/account_picker/md_user_pod_row.js
index cff4f54..e13d59bf 100644
--- a/ui/login/account_picker/md_user_pod_row.js
+++ b/ui/login/account_picker/md_user_pod_row.js
@@ -48,12 +48,12 @@
    * Variables used for pod placement processing. Width and height should be
    * synced with computed CSS sizes of pods.
    */
-  var CROS_POD_WIDTH = 180;
+  var CROS_POD_WIDTH = 306;
   var DESKTOP_POD_WIDTH = 180;
   var MD_DESKTOP_POD_WIDTH = 160;
   var PUBLIC_EXPANDED_BASIC_WIDTH = 500;
   var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610;
-  var CROS_POD_HEIGHT = 213;
+  var CROS_POD_HEIGHT = 346;
   var DESKTOP_POD_HEIGHT = 226;
   var MD_DESKTOP_POD_HEIGHT = 200;
   var POD_ROW_PADDING = 10;
@@ -1085,14 +1085,6 @@
     },
 
     /**
-     * Gets action box menu, remove user command item.
-     * @type {!HTMLInputElement}
-     */
-    get actionBoxMenuCommandElement() {
-      return this.querySelector('.action-box-menu-remove-command');
-    },
-
-    /**
      * Gets action box menu, remove user command item div.
      * @type {!HTMLInputElement}
      */
@@ -1193,9 +1185,6 @@
 
       this.actionBoxMenuTitleEmailElement.hidden =
           this.user_.legacySupervisedUser;
-
-      this.actionBoxMenuCommandElement.textContent =
-          loadTimeData.getString('removeUser');
     },
 
     customizeUserPodPerUserType: function() {
@@ -2006,16 +1995,24 @@
      * button color and state and hides the error popup bubble.
      */
     updateInput_: function() {
+      var isEmpty = this.passwordElement.value.length == 0;
       if (this.submitButton) {
-        this.submitButton.disabled = this.passwordElement.value.length == 0;
+        this.submitButton.disabled = isEmpty;
         if (this.isFingerprintIconShown()) {
-          this.submitButton.hidden = this.passwordElement.value.length == 0;
+          this.submitButton.hidden = isEmpty;
         } else {
           this.submitButton.hidden = false;
         }
       }
       this.showError = false;
       $('bubble').hide();
+      var inputLine = this.querySelector('#input-line');
+      if (inputLine) {
+        if (!isEmpty)
+          inputLine.setAttribute('active', 'true');
+        else
+          inputLine.removeAttribute('active');
+      }
     },
 
     /**
@@ -3935,6 +3932,8 @@
         this.placePods_();
         this.maybePreselectPod();
       }
+
+      this.updatePodNameArea();
     },
 
     /**
@@ -3964,6 +3963,21 @@
     },
 
     /**
+     * Makes sure user name is centered in each pod and extra long name
+     * does not exceed max width.
+     */
+    updatePodNameArea: function() {
+      this.querySelectorAll('.name-container').forEach(function(nameArea) {
+        var nameElement = nameArea.querySelector('.name');
+        var leftMargin = (CROS_POD_WIDTH - nameElement.offsetWidth) / 2;
+        if (leftMargin > 0)
+          nameArea.style.left = leftMargin + 'px';
+        else
+          nameElement.style.width = CROS_POD_WIDTH + 'px';
+      });
+    },
+
+    /**
      * Preselects pod, if needed.
      */
      maybePreselectPod: function() {
diff --git a/ui/login/account_picker/md_user_pod_template.css b/ui/login/account_picker/md_user_pod_template.css
index fdc9f0f..a3367fe 100644
--- a/ui/login/account_picker/md_user_pod_template.css
+++ b/ui/login/account_picker/md_user_pod_template.css
@@ -7,14 +7,8 @@
  */
 
 .action-box-remove-user-warning .remove-warning-button {
-  --paper-button: {
-    background: var(--google-red-700);
-    color: white;
-    font-weight: 600;
-    @apply(--layout-vertical);
-  };
-  --paper-button-flat-keyboard-focus: {
-    background: rgb(173, 50, 36);
-  };
-  @apply(--action-button);
+  color: #E67C73;
+  margin: 0;
+  padding: 0;
+  text-transform: none;
 }
diff --git a/ui/login/account_picker/md_user_pod_template.html b/ui/login/account_picker/md_user_pod_template.html
index 58215f7..fc4e0fe 100644
--- a/ui/login/account_picker/md_user_pod_template.html
+++ b/ui/login/account_picker/md_user_pod_template.html
@@ -5,6 +5,7 @@
 </dom-module>
 
 <style is="custom-style" include="user-pod-template-shared-styles"></style>
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
 
 <iron-iconset-svg name="user-pod" size="24">
   <svg>
@@ -13,8 +14,12 @@
       Inlined from Polymer's iron-icons to avoid importing everything.
       See http://goo.gl/Y1OdAq for instructions on adding additional icons.
       -->
-      <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/></g>
-      <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g>
+      <g id="arrow-forward" stroke="none" stroke-width="1">
+          <polygon id="arrow" points="10.5 4 9.354375 5.145625 13.888125 9.6875 4 9.6875 4 11.3126 13.888125 11.3125 9.354375 15.854375 10.5 17 17 10.5"></polygon>
+      </g>
+      <g id="dropdown" fill="#FFFFFF" stroke="none" stroke-width="1" fill-rule="evenodd" opacity="0.34">
+          <polygon points="16.59 8.59 12 13.17 7.41 8.59 6 10 12 16 18 10"></polygon>
+      </g>
     </defs>
   </svg>
 </iron-iconset-svg>
@@ -42,6 +47,60 @@
         <div class="learn-more"></div>
       </div>
       <div class="name"></div>
+      <div class="action-box-area">
+        <paper-icon-button class="action-box-button" disabled
+                           icon="user-pod:dropdown" tabindex="-1">
+        </paper-icon-button>
+        <iron-icon icon="cr:more-vert" class="action-box-icon"></iron-icon>
+      </div>
+      <div class="action-box-menu">
+        <div class="action-box-menu-title">
+          <span class="action-box-menu-title-name"></span>
+          <span class="action-box-menu-title-email"></span>
+        </div>
+        <div class="action-box-menu-remove"
+            i18n-content="removeUserWarningButtonTitle">
+        </div>
+        <div class="action-box-remove-user-warning" hidden>
+          <div class="action-box-remove-user-warning-text"></div>
+          <table class="action-box-remove-user-warning-table-nonsync
+                        non-sync has-stats">
+            <tbody>
+              <tr>
+                <td i18n-content="removeUserWarningTextHistory"></td>
+                <td class="action-box-remove-user-warning-history
+                           action-box-remove-user-warning-table-numbers"
+                    i18n-content="removeUserWarningTextCalculating"></td>
+              </tr>
+              <tr>
+                <td i18n-content="removeUserWarningTextPasswords"></td>
+                <td class="action-box-remove-user-warning-passwords
+                           action-box-remove-user-warning-table-numbers"
+                    i18n-content="removeUserWarningTextCalculating"></td>
+              </tr>
+              <tr>
+                <td i18n-content="removeUserWarningTextBookmarks"></td>
+                <td class="action-box-remove-user-warning-bookmarks
+                           action-box-remove-user-warning-table-numbers"
+                    i18n-content="removeUserWarningTextCalculating"></td>
+              </tr>
+              <tr>
+                <td i18n-content="removeUserWarningTextSettings"></td>
+                <td class="action-box-remove-user-warning-settings
+                           action-box-remove-user-warning-table-numbers"
+                    i18n-content="removeUserWarningTextCalculating"></td>
+              </tr>
+            </tbody>
+          </table>
+          <div class="action-box-remove-legacy-supervised-user-warning-text"
+              i18n-content="removeLegacySupervisedUserWarningText"></div>
+          <div class="action-box-remove-non-owner-user-warning-text"
+              i18n-content="removeNonOwnerUserWarningText"></div>
+          <!-- paper-button is imported inside user_manager.html -->
+          <paper-button class="remove-warning-button"
+              i18n-content="removeUserWarningButtonTitle"></paper-button>
+        </div>
+      </div>
     </div>
     <div class="auth-container">
       <!-- Password Authentication -->
@@ -84,66 +143,18 @@
         <button class="launch-app-button" i18n-content="launchAppButton">
         </button>
       </div>
+      <div id="input-line">
+        <svg>
+          <line x1="0" y1="0" x2="204" y2="0">
+        </svg>
+      </div>
     </div>
   </div>
-  <div class="action-box-area">
-    <div class="custom-appearance action-box-button"></div>
-    <!-- iron-icon is imported inside user_manager.html -->
-    <iron-icon icon="cr:more-vert" class="action-box-icon"></iron-icon>
-  </div>
   <div class="user-image-gradient-area">
   </div>
   <div class="user-type-icon-area" hidden>
     <div class="custom-appearance user-type-icon-image"></div>
   </div>
-  <div class="action-box-menu">
-    <div class="action-box-menu-title">
-      <span class="action-box-menu-title-name"></span>
-      <span class="action-box-menu-title-email"></span>
-    </div>
-    <div class="action-box-menu-remove">
-      <span class="action-box-menu-remove-command"/>
-    </div>
-    <div class="action-box-remove-user-warning" hidden>
-      <div class="action-box-remove-user-warning-text"></div>
-      <table class="action-box-remove-user-warning-table-nonsync
-                    non-sync has-stats">
-        <tbody>
-          <tr>
-            <td i18n-content="removeUserWarningTextHistory"></td>
-            <td class="action-box-remove-user-warning-history
-                       action-box-remove-user-warning-table-numbers"
-                i18n-content="removeUserWarningTextCalculating"></td>
-          </tr>
-          <tr>
-            <td i18n-content="removeUserWarningTextPasswords"></td>
-            <td class="action-box-remove-user-warning-passwords
-                       action-box-remove-user-warning-table-numbers"
-                i18n-content="removeUserWarningTextCalculating"></td>
-          </tr>
-          <tr>
-            <td i18n-content="removeUserWarningTextBookmarks"></td>
-            <td class="action-box-remove-user-warning-bookmarks
-                       action-box-remove-user-warning-table-numbers"
-                i18n-content="removeUserWarningTextCalculating"></td>
-          </tr>
-          <tr>
-            <td i18n-content="removeUserWarningTextSettings"></td>
-            <td class="action-box-remove-user-warning-settings
-                       action-box-remove-user-warning-table-numbers"
-                i18n-content="removeUserWarningTextCalculating"></td>
-          </tr>
-        </tbody>
-      </table>
-      <div class="action-box-remove-legacy-supervised-user-warning-text"
-          i18n-content="removeLegacySupervisedUserWarningText"></div>
-      <div class="action-box-remove-non-owner-user-warning-text"
-          i18n-content="removeNonOwnerUserWarningText"></div>
-      <!-- paper-button is imported inside user_manager.html -->
-      <paper-button class="remove-warning-button"
-          i18n-content="removeUserWarningButtonTitle"></paper-button>
-    </div>
-  </div>
   <div class="user-type-bubble">
     <div class="user-type-bubble-header">
       <span class="mp-policy-title"
diff --git a/ui/login/md_screen_container.css b/ui/login/md_screen_container.css
index cd14ace..14fb05b 100644
--- a/ui/login/md_screen_container.css
+++ b/ui/login/md_screen_container.css
@@ -63,11 +63,7 @@
   pointer-events: none;
 }
 
-#oobe-shield {
-  display: none;
-}
-
-#oobe-shield[md-mode] {
+#login-shield {
   background-color: rgba(20, 29, 40, .8); /* #141D28 80% */
   display: block;
   height: 100%;
diff --git a/ui/login/screen_container.css b/ui/login/screen_container.css
index da99850..bb8f8d993 100644
--- a/ui/login/screen_container.css
+++ b/ui/login/screen_container.css
@@ -96,7 +96,7 @@
 #oobe.oauth-enrollment #inner-container,
 #oobe.password-changed #inner-container,
 #oobe.ad-password-change #inner-container,
-#oobe.not([md-mode]).reset #inner-container,
+#oobe:not([md-mode]).reset #inner-container,
 #oobe.supervised-user-creation #inner-container,
 #oobe.supervised-user-creation-dialog #inner-container,
 #oobe.terms-of-service #inner-container,
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index 83c969d..9033eef 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/gfx/animation/slide_animation.h"
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index cc6c9a9b..cd98a36 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -162,6 +162,7 @@
     "gpu/mock_scanout_buffer.h",
     "gpu/mock_scanout_buffer_generator.cc",
     "gpu/mock_scanout_buffer_generator.h",
+    "gpu/proxy_helpers_unittest.cc",
     "gpu/screen_manager_unittest.cc",
   ]
 
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index 06bec8a9..cc0a455 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
diff --git a/ui/ozone/platform/drm/gpu/proxy_helpers.h b/ui/ozone/platform/drm/gpu/proxy_helpers.h
index 0cd73b78..086709c 100644
--- a/ui/ozone/platform/drm/gpu/proxy_helpers.h
+++ b/ui/ozone/platform/drm/gpu/proxy_helpers.h
@@ -22,6 +22,15 @@
   task_runner->PostTask(FROM_HERE, base::Bind(callback, args...));
 }
 
+template <typename... Args>
+void PostAsyncTaskOnce(
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+    base::OnceCallback<void(Args...)> callback,
+    Args... args) {
+  auto closure = base::BindOnce(std::move(callback), std::move(args)...);
+  task_runner->PostTask(FROM_HERE, std::move(closure));
+}
+
 }  // namespace internal
 
 // Posts a task to a different thread and blocks waiting for the task to finish
@@ -40,6 +49,17 @@
                     base::ThreadTaskRunnerHandle::Get(), callback);
 }
 
+// Creates a OnceCallback that will run |callback| on the calling thread. Useful
+// when posting a task on a different thread and expecting a callback when the
+// task finished (and the callback needs to run on the original thread).
+template <typename... Args>
+base::OnceCallback<void(Args...)> CreateSafeOnceCallback(
+    base::OnceCallback<void(Args...)> callback) {
+  return base::BindOnce(&internal::PostAsyncTaskOnce<Args...>,
+                        base::ThreadTaskRunnerHandle::Get(),
+                        std::move(callback));
+}
+
 }  // namespace ui
 
 #endif  // UI_OZONE_PLATFORM_DRM_GPU_PROXY_HELPERS_H_
diff --git a/ui/ozone/platform/drm/gpu/proxy_helpers_unittest.cc b/ui/ozone/platform/drm/gpu/proxy_helpers_unittest.cc
new file mode 100644
index 0000000..3c745f1a
--- /dev/null
+++ b/ui/ozone/platform/drm/gpu/proxy_helpers_unittest.cc
@@ -0,0 +1,159 @@
+// 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 "ui/ozone/platform/drm/gpu/proxy_helpers.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+class ProxyHelpersTest : public testing::Test {
+ public:
+  void SetUp() override {
+    drm_thread_.reset(new base::Thread("drm_thread"));
+    drm_thread_->Start();
+  }
+
+  void TearDown() override {
+    drm_thread_->Stop();
+    drm_thread_ = nullptr;
+  }
+
+  // QuitFunction runs on the DRM thread.
+  void QuitFunction(int a) {
+    EXPECT_TRUE(drm_checker_.CalledOnValidThread());
+
+    message_loop_.task_runner()->PostTask(
+        FROM_HERE, base::Bind(&ProxyHelpersTest::QuitFunctionCallback,
+                              base::Unretained(this), 8));
+  }
+
+  // QuitFunctionCallback runs on the main thread.
+  void QuitFunctionCallback(int a) {
+    EXPECT_TRUE(main_checker_.CalledOnValidThread());
+
+    auto quitter = run_loop_.QuitWhenIdleClosure();
+    message_loop_.task_runner()->PostTask(FROM_HERE, quitter);
+  }
+
+  void SetDrmChecker() { drm_checker_.DetachFromThread(); }
+
+  void MoveType(int a,
+                base::OnceCallback<void(std::unique_ptr<int>)> callback) {
+    EXPECT_TRUE(drm_checker_.CalledOnValidThread());
+
+    std::unique_ptr<int> p(new int);
+    *p = a + 1;
+
+    std::move(callback).Run(std::move(p));
+  }
+
+  void MoveTypeCallback(std::unique_ptr<int> p) {
+    EXPECT_TRUE(main_checker_.CalledOnValidThread());
+
+    *p = *p + 1;
+    move_type_.swap(p);
+    EXPECT_EQ(*p, 50);
+  }
+
+  void ValueType(int a, base::OnceCallback<void(int)> callback) {
+    EXPECT_TRUE(drm_checker_.CalledOnValidThread());
+
+    std::move(callback).Run(a + 1);
+  }
+
+  void ValueTypeCallback(int a) {
+    EXPECT_TRUE(main_checker_.CalledOnValidThread());
+
+    value_type_ = a + 1;
+  }
+
+  void StringType(std::string a,
+                  base::OnceCallback<void(std::string)> callback) {
+    EXPECT_TRUE(drm_checker_.CalledOnValidThread());
+    std::move(callback).Run(a.append("e"));
+  }
+
+  void StringTypeCallback(std::string a) {
+    EXPECT_TRUE(main_checker_.CalledOnValidThread());
+    derived_string_ = a.append("r");
+  }
+
+ protected:
+  // Main thread message loop.
+  base::MessageLoop message_loop_;
+  base::RunLoop run_loop_;
+
+  // Thread to simulate the drm thread in ozone viz process.
+  std::unique_ptr<base::Thread> drm_thread_;
+
+  base::ThreadChecker main_checker_;
+  base::ThreadChecker drm_checker_;
+
+  // Variables to record operation.
+  int value_type_ = 0;
+  std::unique_ptr<int> move_type_;
+  std::string original_string_;
+  std::string derived_string_;
+};
+
+TEST_F(ProxyHelpersTest, PostTask) {
+  // Binds the thread checker on the drm thread.
+  drm_thread_->task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyHelpersTest::SetDrmChecker, base::Unretained(this)));
+
+  // Test passing a type by value.
+  auto value_callback = base::BindOnce(&ProxyHelpersTest::ValueTypeCallback,
+                                       base::Unretained(this));
+  auto safe_value_callback = CreateSafeOnceCallback(std::move(value_callback));
+
+  drm_thread_->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ProxyHelpersTest::ValueType, base::Unretained(this), 100,
+                     std::move(safe_value_callback)));
+
+  // Test passing a move-only type.
+  move_type_.reset(new int);
+  *move_type_ = 50;
+
+  auto move_callback = base::BindOnce(&ProxyHelpersTest::MoveTypeCallback,
+                                      base::Unretained(this));
+  auto safe_move_callback = CreateSafeOnceCallback(std::move(move_callback));
+
+  drm_thread_->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ProxyHelpersTest::MoveType, base::Unretained(this), 100,
+                     std::move(safe_move_callback)));
+
+  // Test that passing a type that supports both move and value semantics
+  // defaults to value.
+  original_string_ = "This is a string";
+
+  auto string_callback = base::BindOnce(&ProxyHelpersTest::StringTypeCallback,
+                                        base::Unretained(this));
+  auto safe_string_callback =
+      CreateSafeOnceCallback(std::move(string_callback));
+
+  drm_thread_->task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ProxyHelpersTest::StringType, base::Unretained(this),
+                     original_string_, std::move(safe_string_callback)));
+
+  // Shutdown the RunLoop.
+  drm_thread_->task_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&ProxyHelpersTest::QuitFunction, base::Unretained(this), 42));
+
+  run_loop_.Run();
+
+  EXPECT_EQ(value_type_, 102);
+  EXPECT_EQ(*move_type_, 102);
+  EXPECT_TRUE(original_string_ == "This is a string");
+  EXPECT_TRUE(derived_string_ == "This is a stringer");
+}
+}  // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_connection_unittest.cc b/ui/ozone/platform/wayland/wayland_connection_unittest.cc
index b261ec16..2fda8c1 100644
--- a/ui/ozone/platform/wayland/wayland_connection_unittest.cc
+++ b/ui/ozone/platform/wayland/wayland_connection_unittest.cc
@@ -5,6 +5,7 @@
 #include <wayland-server-core.h>
 #include <xdg-shell-unstable-v5-server-protocol.h>
 
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/ozone/platform/wayland/fake_server.h"
diff --git a/ui/ozone/platform/wayland/wayland_test.h b/ui/ozone/platform/wayland/wayland_test.h
index c2b5eb3..b5e350c 100644
--- a/ui/ozone/platform/wayland/wayland_test.h
+++ b/ui/ozone/platform/wayland/wayland_test.h
@@ -5,6 +5,7 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_TEST_H_
 #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_TEST_H_
 
+#include "base/message_loop/message_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/ozone/platform/wayland/fake_server.h"
 #include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 700d822..0b6cc5b 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -11,6 +11,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/display/fake_display_delegate.h"
diff --git a/ui/ozone/public/ozone_gpu_test_helper.cc b/ui/ozone/public/ozone_gpu_test_helper.cc
index 55fc4b4..1e8ba71 100644
--- a/ui/ozone/public/ozone_gpu_test_helper.cc
+++ b/ui/ozone/public/ozone_gpu_test_helper.cc
@@ -4,6 +4,7 @@
 
 #include "ui/ozone/public/ozone_gpu_test_helper.h"
 
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ipc/ipc_listener.h"
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index bcd120b6..463760c 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -510,7 +510,7 @@
     // This delegate is owned by the test case itself, so it should not delete
     // itself here.
   }
-  int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
+  int GetDialogButtons() const override { return ui::DIALOG_BUTTON_OK; }
   bool ShouldSnapFrameWidth() const override {
     return override_snap_.value_or(
         BubbleDialogDelegateView::ShouldSnapFrameWidth());
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 1a6e01a..7608aeae 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc
index f6a1707..af4a6df 100644
--- a/ui/views/examples/examples_window.cc
+++ b/ui/views/examples/examples_window.cc
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/combobox_model.h"
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc
index db9e3944..4203d95 100644
--- a/ui/views/mus/mus_client.cc
+++ b/ui/views/mus/mus_client.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ui/public/cpp/gpu/gpu.h"
diff --git a/ui/views/mus/screen_mus_unittest.cc b/ui/views/mus/screen_mus_unittest.cc
index 6895fbf..00116c1 100644
--- a/ui/views/mus/screen_mus_unittest.cc
+++ b/ui/views/mus/screen_mus_unittest.cc
@@ -5,6 +5,7 @@
 #include "ui/views/mus/screen_mus.h"
 
 #include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
 #include "ui/display/display_switches.h"
 #include "ui/display/screen.h"
 #include "ui/views/test/scoped_views_test_helper.h"
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc
index e6b796f..eb76a7f3 100644
--- a/ui/views/mus/views_mus_test_suite.cc
+++ b/ui/views/mus/views_mus_test_suite.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/simple_thread.h"
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm
index 062984c..edd51fb 100644
--- a/ui/views/widget/native_widget_mac_unittest.mm
+++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -12,6 +12,7 @@
 #import "base/mac/scoped_nsobject.h"
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index a2f699d..838221e 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 4fc34c7..de7223cc 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -16,6 +16,7 @@
 #include "base/debug/alias.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index 0c62cdc..efc7e8de 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -133,7 +133,7 @@
 }
 
 bool DialogDelegate::ShouldSnapFrameWidth() const {
-  return true;
+  return GetDialogButtons() != ui::DIALOG_BUTTON_NONE;
 }
 
 int DialogDelegate::GetDialogButtons() const {
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc
index ff365d4f..59e4655 100644
--- a/ui/views/window/dialog_delegate_unittest.cc
+++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -66,6 +66,7 @@
   base::string16 GetWindowTitle() const override { return title_; }
   View* GetInitiallyFocusedView() override { return input_; }
   bool ShouldUseCustomFrame() const override { return true; }
+  int GetDialogButtons() const override { return dialog_buttons_; }
 
   void CheckAndResetStates(bool canceled,
                            bool accepted,
@@ -90,6 +91,9 @@
   void set_should_handle_escape(bool should_handle_escape) {
     should_handle_escape_ = should_handle_escape;
   }
+  void set_dialog_buttons(int dialog_buttons) {
+    dialog_buttons_ = dialog_buttons;
+  }
 
   views::Textfield* input() { return input_; }
 
@@ -103,6 +107,7 @@
   base::string16 title_;
   bool show_close_button_ = true;
   bool should_handle_escape_ = false;
+  int dialog_buttons_ = ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
 
   DISALLOW_COPY_AND_ASSIGN(TestDialog);
 };
@@ -382,4 +387,11 @@
   dialog_widget->CloseNow();
 }
 
+TEST_F(DialogTest, DontSnapWithoutButtons) {
+  TestDialog dialog;
+  EXPECT_TRUE(dialog.ShouldSnapFrameWidth());
+  dialog.set_dialog_buttons(ui::DIALOG_BUTTON_NONE);
+  EXPECT_FALSE(dialog.ShouldSnapFrameWidth());
+}
+
 }  // namespace views