diff --git a/DEPS b/DEPS
index 09de8af..35c6ae1 100644
--- a/DEPS
+++ b/DEPS
@@ -105,7 +105,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '16c9216905c119709366913523146d4968a6a5f5',
+  'skia_revision': '9f9c2ea4282f0c332a0d55472931c39761420f54',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'd082819ca2ad1cadafc2cb261212ee064124a8cc',
+  'angle_revision': '0da73fedd90022e1dd9d4611e44e6307eeedaa13',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -165,7 +165,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': '59297c6f73a6485334542123ebb48c648cef676b',
+  'catapult_revision': 'a115d8de1c986bb73971deac71ee74a5721c32de',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -213,7 +213,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '146eb3bdcf5b7dc021edb3ca9bb9aac18ae904c0',
+  'spv_tools_revision': '2a88bcbaff3e9fa857151284d7698dad9053c1aa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -595,7 +595,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '84f3a15fd9dbacfcf36c396f5817cfd0e81948b3',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '20afd180cccbba7fd7f3cfd082b16fe564f88eb8',
       'condition': 'checkout_linux',
   },
 
@@ -620,7 +620,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '95d4c855637a039f4befbef17af1708ae06386b0',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0daedf7758e157ee22a64e9dabcb089c0da5ef4c',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1106,7 +1106,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '895ce82cabc83bc72bb5ee97b750b2d235901c17',
+    Var('webrtc_git') + '/src.git' + '@' + 'bfff4bac826cace3b76f8e29775009a8dad54433',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1137,7 +1137,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e928488baf668dc39ca71206f0796ad08ea15764',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1ed6f3571d8adb341bd41237cfc7277bc74441ca',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index ffe011f..49fb774 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2176,7 +2176,7 @@
                    'mcnee@chromium.org',
                    'wjmaclean@chromium.org'],
     'headless': ['headless-reviews@chromium.org'],
-    'history_ui': ['pam+watch@chromium.org'],
+    'history_ui': [],
     'i18n': ['jshin+watch@chromium.org'],
     'importer': ['tfarina@chromium.org'],
     'incident_reporting': ['grt+watch@chromium.org'],
@@ -2388,7 +2388,7 @@
                    'jbroman+cpp@chromium.org',
                    'vmpstr+watch@chromium.org'],
     'subresource_filter': ['subresource-filter-reviews@chromium.org'],
-    'supervised_users': ['pam+watch@chromium.org'],
+    'supervised_users': [],
     'sync': ['sync-reviews@chromium.org'],
     'syncfs': ['kinuko+fileapi@chromium.org',
                'nhiroki@chromium.org',
diff --git a/android_webview/browser/aw_pdf_exporter.cc b/android_webview/browser/aw_pdf_exporter.cc
index da885b36..4065691 100644
--- a/android_webview/browser/aw_pdf_exporter.cc
+++ b/android_webview/browser/aw_pdf_exporter.cc
@@ -21,10 +21,10 @@
 namespace {
 
 void JNI_AwPdfExporter_GetPageRanges(JNIEnv* env,
-                                     jintArray int_arr,
+                                     const JavaRef<jintArray>& int_arr,
                                      printing::PageRanges* range_vector) {
   std::vector<int> pages;
-  base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
+  base::android::JavaIntArrayToIntVector(env, int_arr.obj(), &pages);
   for (int page : pages) {
     printing::PageRange range;
     range.from = page;
@@ -56,7 +56,7 @@
 void AwPdfExporter::ExportToPdf(JNIEnv* env,
                                 const JavaParamRef<jobject>& obj,
                                 int fd,
-                                jintArray pages,
+                                const JavaParamRef<jintArray>& pages,
                                 const JavaParamRef<jobject>& cancel_signal) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   printing::PrintSettings print_settings;
diff --git a/android_webview/browser/aw_pdf_exporter.h b/android_webview/browser/aw_pdf_exporter.h
index 8c1be91..a4ca157 100644
--- a/android_webview/browser/aw_pdf_exporter.h
+++ b/android_webview/browser/aw_pdf_exporter.h
@@ -32,7 +32,7 @@
   void ExportToPdf(JNIEnv* env,
                    const base::android::JavaParamRef<jobject>& obj,
                    int fd,
-                   jintArray pages,
+                   const base::android::JavaParamRef<jintArray>& pages,
                    const base::android::JavaParamRef<jobject>& cancel_signal);
 
  private:
diff --git a/android_webview/browser/aw_variations_seed_bridge.cc b/android_webview/browser/aw_variations_seed_bridge.cc
index aeee02e..4b4b95d1 100644
--- a/android_webview/browser/aw_variations_seed_bridge.cc
+++ b/android_webview/browser/aw_variations_seed_bridge.cc
@@ -36,11 +36,8 @@
       Java_AwVariationsSeedBridge_getData(env);
   Java_AwVariationsSeedBridge_clearSeed(env);
 
-  std::vector<uint8_t> u8_data;
-  JavaByteArrayToByteVector(env, j_data.obj(), &u8_data);
-
   auto java_seed = std::make_unique<variations::SeedResponse>();
-  java_seed->data = std::string(u8_data.begin(), u8_data.end());
+  base::android::JavaByteArrayToString(env, j_data.obj(), &java_seed->data);
   java_seed->signature = ConvertJavaStringToUTF8(j_signature);
   java_seed->country = ConvertJavaStringToUTF8(j_country);
   java_seed->date = ConvertJavaStringToUTF8(j_date);
diff --git a/ash/ash_service_unittest.cc b/ash/ash_service_unittest.cc
index 79bbda3..8e5bbb0e 100644
--- a/ash/ash_service_unittest.cc
+++ b/ash/ash_service_unittest.cc
@@ -20,6 +20,7 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/env.h"
 #include "ui/aura/mus/property_converter.h"
+#include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/mus/window_tree_client_delegate.h"
 #include "ui/aura/mus/window_tree_host_mus.h"
@@ -124,8 +125,6 @@
       aura::CreateInitParamsForTopLevel(client.get(), std::move(properties)));
   window_tree_host_mus.InitHost();
   aura::Window* child_window = new aura::Window(nullptr);
-  child_window->SetProperty(aura::client::kEmbedType,
-                            aura::client::WindowEmbedType::EMBED_IN_OWNER);
   child_window->Init(ui::LAYER_NOT_DRAWN);
   window_tree_host_mus.window()->AddChild(child_window);
 
@@ -133,8 +132,8 @@
   // |child_window|. This blocks until it succeeds.
   ws::mojom::WindowTreeClientPtr tree_client;
   auto tree_client_request = MakeRequest(&tree_client);
-  client->Embed(child_window, std::move(tree_client), 0u,
-                base::BindOnce(&OnEmbed));
+  aura::WindowPortMus::Get(child_window)
+      ->Embed(std::move(tree_client), 0u, base::BindOnce(&OnEmbed));
   std::unique_ptr<aura::WindowTreeClient> child_client =
       aura::WindowTreeClient::CreateForEmbedding(
           connector(), &window_tree_delegate, std::move(tree_client_request),
diff --git a/ash/public/interfaces/ash_window_manager.mojom b/ash/public/interfaces/ash_window_manager.mojom
index 48bba44f..cc619dd 100644
--- a/ash/public/interfaces/ash_window_manager.mojom
+++ b/ash/public/interfaces/ash_window_manager.mojom
@@ -4,6 +4,8 @@
 
 module ash.mojom;
 
+import "ui/events/mojo/event_constants.mojom";
+
 // The previewed snap state for a window, corresponding to the use of a
 // PhantomWindowController.
 enum SnapDirection {
@@ -21,4 +23,8 @@
   ShowSnapPreview(uint64 window_id, SnapDirection snap);
 
   CommitSnap(uint64 window_id, SnapDirection snap);
+
+  // Maximizes the window in response to a double click or tap on the HTCAPTION
+  // area.
+  MaximizeWindowByCaptionClick(uint64 window_id, ui.mojom.PointerKind pointer);
 };
diff --git a/ash/ws/ash_window_manager.cc b/ash/ws/ash_window_manager.cc
index 7d4d6ce..008de13b 100644
--- a/ash/ws/ash_window_manager.cc
+++ b/ash/ws/ash_window_manager.cc
@@ -6,7 +6,10 @@
 
 #include "ash/shell.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "ash/wm/window_state.h"
+#include "ash/wm/wm_event.h"
 #include "base/logging.h"
+#include "base/metrics/user_metrics.h"
 #include "services/ws/window_tree.h"
 
 namespace ash {
@@ -49,4 +52,28 @@
   }
 }
 
+void AshWindowManager::MaximizeWindowByCaptionClick(
+    ws::Id window_id,
+    ui::mojom::PointerKind pointer) {
+  aura::Window* window = window_tree_->GetWindowByTransportId(window_id);
+  if (!window || !window_tree_->IsTopLevel(window)) {
+    DVLOG(1) << "MaximizeWindowByCaptionClick passed invalid window, id="
+             << window_id;
+    return;
+  }
+
+  if (pointer == ui::mojom::PointerKind::MOUSE) {
+    base::RecordAction(base::UserMetricsAction("Caption_ClickTogglesMaximize"));
+  } else if (pointer == ui::mojom::PointerKind::TOUCH) {
+    base::RecordAction(
+        base::UserMetricsAction("Caption_GestureTogglesMaximize"));
+  } else {
+    DVLOG(1) << "MaximizeWindowByCaptionClick passed invalid event";
+    return;
+  }
+
+  const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION);
+  wm::GetWindowState(window)->OnWMEvent(&wm_event);
+}
+
 }  // namespace ash
diff --git a/ash/ws/ash_window_manager.h b/ash/ws/ash_window_manager.h
index 242b68a..d786d4f 100644
--- a/ash/ws/ash_window_manager.h
+++ b/ash/ws/ash_window_manager.h
@@ -33,6 +33,8 @@
   void AddWindowToTabletMode(ws::Id window_id) override;
   void ShowSnapPreview(ws::Id window_id, mojom::SnapDirection snap) override;
   void CommitSnap(ws::Id window_id, mojom::SnapDirection snap) override;
+  void MaximizeWindowByCaptionClick(ws::Id window_id,
+                                    ui::mojom::PointerKind pointer) override;
 
  private:
   ws::WindowTree* window_tree_;
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc
index 52b1679..403c56e 100644
--- a/base/android/jni_array.cc
+++ b/base/android/jni_array.cc
@@ -45,6 +45,12 @@
   return ToJavaByteArray(env, bytes.data(), bytes.size());
 }
 
+ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env,
+                                               const std::string& str) {
+  return ToJavaByteArray(env, reinterpret_cast<const uint8_t*>(str.data()),
+                         str.size());
+}
+
 ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray(JNIEnv* env,
                                                      const bool* bools,
                                                      size_t len) {
@@ -215,6 +221,17 @@
   AppendJavaByteArrayToByteVector(env, byte_array, out);
 }
 
+void JavaByteArrayToString(JNIEnv* env,
+                           jbyteArray byte_array,
+                           std::string* out) {
+  DCHECK(out);
+  DCHECK(byte_array);
+
+  std::vector<uint8_t> byte_vector;
+  JavaByteArrayToByteVector(env, byte_array, &byte_vector);
+  out->assign(byte_vector.begin(), byte_vector.end());
+}
+
 void JavaBooleanArrayToBoolVector(JNIEnv* env,
                                   jbooleanArray boolean_array,
                                   std::vector<bool>* out) {
diff --git a/base/android/jni_array.h b/base/android/jni_array.h
index 66c56ef..0ec38e9 100644
--- a/base/android/jni_array.h
+++ b/base/android/jni_array.h
@@ -26,6 +26,12 @@
     JNIEnv* env,
     const std::vector<uint8_t>& bytes);
 
+// Returns a new Java byte array converted from the given string. No UTF-8
+// conversion is performed.
+BASE_EXPORT ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
+    JNIEnv* env,
+    const std::string& str);
+
 // Returns a new Java boolean array converted from the given bool array.
 BASE_EXPORT ScopedJavaLocalRef<jbooleanArray>
 ToJavaBooleanArray(JNIEnv* env, const bool* bools, size_t len);
@@ -80,11 +86,17 @@
                                                  jbyteArray byte_array,
                                                  std::vector<uint8_t>* out);
 
-// Replaces the content of |out| with the Java bytes in |bytes_array|.
+// Replaces the content of |out| with the Java bytes in |byte_array|.
 BASE_EXPORT void JavaByteArrayToByteVector(JNIEnv* env,
                                            jbyteArray byte_array,
                                            std::vector<uint8_t>* out);
 
+// Replaces the content of |out| with the Java bytes in |byte_array|. No UTF-8
+// conversion is performed.
+BASE_EXPORT void JavaByteArrayToString(JNIEnv* env,
+                                       jbyteArray byte_array,
+                                       std::string* out);
+
 // Replaces the content of |out| with the Java booleans in |boolean_array|.
 BASE_EXPORT void JavaBooleanArrayToBoolVector(JNIEnv* env,
                                               jbooleanArray boolean_array,
diff --git a/base/android/jni_array_unittest.cc b/base/android/jni_array_unittest.cc
index 245cd50..eb5bec7 100644
--- a/base/android/jni_array_unittest.cc
+++ b/base/android/jni_array_unittest.cc
@@ -45,6 +45,18 @@
   EXPECT_EQ(expected_vec, vectorFromBytes);
 }
 
+TEST(JniArray, ByteArrayStringConversions) {
+  JNIEnv* env = AttachCurrentThread();
+  std::string inputString("hello\0world");
+  ScopedJavaLocalRef<jbyteArray> bytesFromString =
+      ToJavaByteArray(env, inputString);
+  ASSERT_TRUE(bytesFromString.obj());
+
+  std::string stringFromString;
+  JavaByteArrayToString(env, bytesFromString.obj(), &stringFromString);
+  EXPECT_EQ(inputString, stringFromString);
+}
+
 void CheckBoolConversion(JNIEnv* env,
                          const bool* bool_array,
                          const size_t len,
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h
index 0e4b91d..69b47dc8 100644
--- a/base/debug/stack_trace.h
+++ b/base/debug/stack_trace.h
@@ -108,11 +108,18 @@
   void InitTrace(const _CONTEXT* context_record);
 #endif
 
+#if defined(OS_WIN) || defined(OS_ANDROID)
   // From http://msdn.microsoft.com/en-us/library/bb204633.aspx,
   // the sum of FramesToSkip and FramesToCapture must be less than 63,
-  // so set it to 62. Even if on POSIX it could be a larger value, it usually
-  // doesn't give much more information.
-  static const int kMaxTraces = 62;
+  // so set it to 62.
+  // Testing indicates that Android has issues with a larger value
+  // here, so leave Android at 62 also.
+  static constexpr int kMaxTraces = 62;
+#else
+  // For other architectures, use 250. This seems reasonable without
+  // being huge.
+  static constexpr int kMaxTraces = 250;
+#endif
 
   void* trace_[kMaxTraces];
 
diff --git a/base/debug/task_annotator.cc b/base/debug/task_annotator.cc
index 18083c1..382bb39 100644
--- a/base/debug/task_annotator.cc
+++ b/base/debug/task_annotator.cc
@@ -44,10 +44,8 @@
                            TRACE_EVENT_FLAG_FLOW_OUT);
   }
 
-  // TODO(https://crbug.com/826902): Fix callers that invoke WillQueueTask()
-  // twice for the same PendingTask.
-  // DCHECK(!pending_task.task_backtrace[0])
-  //     << "Task backtrace was already set, task posted twice??";
+  DCHECK(!pending_task->task_backtrace[0])
+      << "Task backtrace was already set, task posted twice??";
   if (!pending_task->task_backtrace[0]) {
     const PendingTask* parent_task = GetTLSForCurrentPendingTask()->Get();
     if (parent_task) {
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h
index d623cbc..403d0dcc 100644
--- a/base/message_loop/message_loop_current.h
+++ b/base/message_loop/message_loop_current.h
@@ -38,9 +38,9 @@
 class BASE_EXPORT MessageLoopCurrent {
  public:
   // MessageLoopCurrent is effectively just a disguised pointer and is fine to
-  // copy around.
+  // copy/move around.
   MessageLoopCurrent(const MessageLoopCurrent& other) = default;
-  MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = default;
+  MessageLoopCurrent(MessageLoopCurrent&& other) = default;
 
   // Returns a proxy object to interact with the MessageLoop running the
   // current thread. It must only be used on the thread it was obtained.
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index d3d3839..922af436 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -204,7 +204,7 @@
     TimeTicks time_domain_delayed_run_time = time_domain_now + task.delay;
     PushOntoDelayedIncomingQueueFromMainThread(
         Task(std::move(task), time_domain_delayed_run_time, sequence_number),
-        time_domain_now);
+        time_domain_now, /* notify_task_annotator */ true);
   } else {
     // NOTE posting a delayed task from a different thread is not expected to
     // be common. This pathway is less optimal than perhaps it could be
@@ -225,8 +225,10 @@
 
 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
     Task pending_task,
-    TimeTicks now) {
-  main_thread_only().sequence_manager->WillQueueTask(&pending_task);
+    TimeTicks now,
+    bool notify_task_annotator) {
+  if (notify_task_annotator)
+    main_thread_only().sequence_manager->WillQueueTask(&pending_task);
   main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
 
   LazyNow lazy_now(now);
@@ -266,7 +268,7 @@
   } else {
     // If |delayed_run_time| is in the future we can queue it as normal.
     PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task),
-                                               time_domain_now);
+                                               time_domain_now, false);
   }
   TraceQueueSize();
 }
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index cdb0bb9..9036c28 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -296,7 +296,8 @@
   // Push the task onto the |delayed_incoming_queue|. Lock-free main thread
   // only fast path.
   void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task,
-                                                  TimeTicks now);
+                                                  TimeTicks now,
+                                                  bool notify_task_annotator);
 
   // Push the task onto the |delayed_incoming_queue|.  Slow path from other
   // threads.
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 083fbe2..c3bbd2a 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -68,6 +68,7 @@
 
 #if defined(OS_FUCHSIA)
 #include <lib/zx/job.h>
+#include "base/atomic_sequence_num.h"
 #include "base/base_paths_fuchsia.h"
 #include "base/fuchsia/default_job.h"
 #include "base/fuchsia/file_utils.h"
@@ -347,11 +348,10 @@
   // Create the test subdirectory with a name that is unique to the child test
   // process (qualified by parent PID and an autoincrementing test process
   // index).
-  static size_t child_launch_index = 0;
+  static base::AtomicSequenceNumber child_launch_index;
   base::FilePath nested_data_path = data_path.AppendASCII(
-      base::StringPrintf("test-%" PRIuS "-%" PRIuS,
-                         base::Process::Current().Pid(), child_launch_index));
-  ++child_launch_index;
+      base::StringPrintf("test-%" PRIuS "-%d", base::Process::Current().Pid(),
+                         child_launch_index.GetNext()));
   CHECK(!base::DirectoryExists(nested_data_path));
   CHECK(base::CreateDirectory(nested_data_path));
   DCHECK(base::DirectoryExists(nested_data_path));
diff --git a/build/chromeos/create_vm_test_script.py b/build/chromeos/create_vm_test_script.py
index 5760cc7f..b6ae3ad 100755
--- a/build/chromeos/create_vm_test_script.py
+++ b/build/chromeos/create_vm_test_script.py
@@ -52,6 +52,7 @@
   parser.add_argument('--board')
   parser.add_argument('--deploy-chrome', action='store_true')
   parser.add_argument('--suite-name')
+  parser.add_argument('--tast-conditional')
   parser.add_argument('--tast-tests', action='append')
   args = parser.parse_args(args)
 
@@ -72,14 +73,20 @@
         '--test-exe',
         args.test_exe,
     ])
-  elif args.tast_tests:
+  elif args.tast_conditional or args.tast_tests:
     vm_test_args.extend([
         'tast',
         '--suite-name',
         args.suite_name,
     ])
-    for t in args.tast_tests:
-      vm_test_args.extend(['-t', t])
+    if args.tast_conditional:
+      vm_test_args.extend([
+          '--conditional',
+          args.tast_conditional,
+      ])
+    else:
+      for t in args.tast_tests:
+        vm_test_args.extend(['-t', t])
   else:
     vm_test_args.append('host-cmd')
     if args.deploy_chrome:
diff --git a/build/chromeos/run_vm_test.py b/build/chromeos/run_vm_test.py
index d40bb7c..8d574e3 100755
--- a/build/chromeos/run_vm_test.py
+++ b/build/chromeos/run_vm_test.py
@@ -8,6 +8,7 @@
 import json
 import logging
 import os
+import pipes
 import re
 import signal
 import sys
@@ -159,6 +160,7 @@
 
     self._suite_name = args.suite_name
     self._tests = args.tests
+    self._conditional = args.conditional
 
   @property
   def suite_name(self):
@@ -177,7 +179,10 @@
         '--',
         'local_test_runner',
     ]
-    self._vm_test_cmd.extend(self._tests)
+    if self._conditional:
+      self._vm_test_cmd.append(pipes.quote(self._conditional))
+    else:
+      self._vm_test_cmd.extend(self._tests)
 
 
 class GTestTest(RemoteTest):
@@ -260,26 +265,7 @@
       test_invocation += ' --test-launcher-summary-output=%s' % vm_result_file
     if self._additional_args:
       test_invocation += ' %s' % ' '.join(self._additional_args)
-    vm_test_script_contents += [
-        test_invocation,
-        'test_retcode=$?',
-    ]
-
-    # Clear out directories that persist logs and crash dumps. These can
-    # accumulate over a VM's lifetime and consume disk space, so remove any
-    # that the test generated.
-    # TODO(crbug.com/878526): Remove this once cros_run_vm_test handles it.
-    vm_test_script_contents += [
-        # We run tests as chronos, but need to be root to rm the files. So pass
-        # in the public plaintext root password to sudo via stdin.
-        'echo "test0000" | '
-        'sudo -S find /var/spool/crash/ -type f -print -delete',
-        'echo "test0000" | '
-        'sudo -S find /var/log/chrome/ -type f -print -delete',
-        # Make sure the exit code is that of the test, and not the post-test
-        # cleanup.
-        'exit $test_retcode',
-    ]
+    vm_test_script_contents.append(test_invocation)
 
     logging.info('Running the following command in the VM:')
     logging.info('\n' + '\n'.join(vm_test_script_contents))
@@ -540,7 +526,11 @@
       '--test-launcher-summary-output', type=str,
       help='Generates a simple GTest-style JSON result file for the test run.')
   tast_test_parser.add_argument(
-      '--test', '-t', action='append', dest='tests', required=True,
+      '--conditional', type=str,
+      help='A conditional whose matching tests will run '
+           '(eg: ("dep:chrome" || "dep:chrome_login")).')
+  tast_test_parser.add_argument(
+      '--test', '-t', action='append', dest='tests',
       help='A Tast test to run in the VM (eg: "ui.ChromeLogin").')
 
   add_common_args(gtest_parser)
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni
index d5dbde7..ef0e5060 100644
--- a/build/config/chromeos/rules.gni
+++ b/build/config/chromeos/rules.gni
@@ -19,6 +19,7 @@
 # Args:
 #   test_exe: Name of test binary located in the out dir. This will get copied
 #       to the VM and executed there.
+#   tast_conditional: Tast conditional to pass to local_test_runner on the VM.
 #   tast_tests: List of Tast tests to run on the VM. Note that when this is
 #       specified, the target name used to invoke this template will be
 #       designated as the "name" of this test and will primarly used for test
@@ -39,6 +40,7 @@
                            "deploy_chrome",
                            "generated_script",
                            "runtime_deps_file",
+                           "tast_conditional",
                            "tast_tests",
                            "testonly",
                            "test_exe",
@@ -50,7 +52,8 @@
   assert(defined(generated_script),
          "Must specify where to place generated test launcher script via " +
              "'generated_script'")
-  assert(!(defined(tast_tests) && defined(test_exe)),
+  is_tast = defined(tast_conditional) || defined(tast_tests)
+  assert(!(is_tast && defined(test_exe)),
          "Tast tests are invoked from binaries shipped with the VM image. " +
              "There should be no locally built binary needed.")
 
@@ -134,30 +137,41 @@
           rebase_path(runtime_deps_file, root_build_dir),
         ]
       }
-    } else if (defined(tast_tests)) {
+    } else if (is_tast) {
       # When --tast-tests is specified, run_vm_test will call local_test_runner
       # on the VM to run the set of tests.
       args += [
         "--suite-name",
         target_name,
       ]
-      foreach(test, tast_tests) {
+      if (defined(tast_conditional)) {
         args += [
-          "--tast-tests",
-          test,
+          "--tast-conditional",
+          tast_conditional,
         ]
+      } else {
+        foreach(test, tast_tests) {
+          args += [
+            "--tast-tests",
+            test,
+          ]
+        }
       }
     }
   }
 }
 
-# TODO(crbug.com/876587): Support Tast conditionals as well.
 template("tast_test") {
-  assert(defined(invoker.tast_tests), "A list of tast_tests must be specified.")
+  assert(defined(invoker.tast_conditional) != defined(invoker.tast_tests),
+         "Specify one of tast_tests or tast_conditional.")
 
   generate_vm_runner_script(target_name) {
     testonly = true
-    tast_tests = invoker.tast_tests
+    if (defined(invoker.tast_conditional)) {
+      tast_conditional = invoker.tast_conditional
+    } else if (defined(invoker.tast_tests)) {
+      tast_tests = invoker.tast_tests
+    }
     generated_script = "$root_build_dir/bin/run_${target_name}"
     runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
     deploy_chrome = true
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java
new file mode 100644
index 0000000..00f6cd5
--- /dev/null
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java
@@ -0,0 +1,98 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feed;
+
+import android.text.TextUtils;
+
+import org.chromium.chrome.browser.ChromeFeatureList;
+
+class FeedConfiguration {
+    private static final String FEED_SERVER_ENDPOINT = "feed_server_endpoint";
+    /** Default value for server endpoint. */
+    public static final String FEED_SERVER_ENDPOINT_DEFAULT =
+            "https://www.google.com/httpservice/noretry/NowStreamService/FeedQuery";
+
+    private static final String FEED_SERVER_METHOD = "feed_server_method";
+    /** Default value for feed server method. */
+    public static final String FEED_SERVER_METHOD_DEFAULT = "GET";
+
+    private static final String FEED_SERVER_RESPONSE_LENGTH_PREFIXED =
+            "feed_server_response_length_prefixed";
+    /** Default value for feed server response length prefixed. */
+    public static final boolean FEED_SERVER_RESPONSE_LENGTH_PREFIXED_DEFAULT = true;
+
+    private static final String LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS =
+            "logging_immediate_content_threshold_ms";
+    /** Default value for logging immediate content threshold. */
+    public static final int LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS_DEFAULT = 1000;
+
+    private static final String SESSION_LIFETIME_MS = "session_lifetime_ms";
+    /** Default value for session lifetime. */
+    public static final int SESSION_LIFETIME_MS_DEFAULT = 3600000;
+
+    private static final String TRIGGER_IMMEDIATE_PAGINATION = "trigger_immediate_pagination";
+    /** Default value for triggering immediate pagination. */
+    public static final boolean TRIGGER_IMMEDIATE_PAGINATION_DEFAULT = false;
+
+    private static final String VIEW_LOG_THRESHOLD = "view_log_threshold";
+    /** Default value for logging view threshold. */
+    public static final double VIEW_LOG_THRESHOLD_DEFAULT = 0.66d;
+
+    /** @return Feed server endpoint to use to fetch content suggestions. */
+    public static String getFeedServerEndpoint() {
+        String paramValue = ChromeFeatureList.getFieldTrialParamByFeature(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, FEED_SERVER_ENDPOINT);
+        return TextUtils.isEmpty(paramValue) ? FEED_SERVER_ENDPOINT_DEFAULT : paramValue;
+    }
+
+    /** @return Feed server method to use when fetching content suggestions. */
+    public static String getFeedServerMethod() {
+        String paramValue = ChromeFeatureList.getFieldTrialParamByFeature(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, FEED_SERVER_METHOD);
+        return TextUtils.isEmpty(paramValue) ? FEED_SERVER_METHOD_DEFAULT : paramValue;
+    }
+
+    /** @return Whether server response should be length prefixed. */
+    public static boolean getFeedServerReponseLengthPrefixed() {
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS,
+                FEED_SERVER_RESPONSE_LENGTH_PREFIXED, FEED_SERVER_RESPONSE_LENGTH_PREFIXED_DEFAULT);
+    }
+
+    /**
+     * @return How long before showing content after opening NTP is no longer considered immediate
+     *         in UMA.
+     */
+    public static long getLoggingImmediateContentThresholdMs() {
+        return (long) ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS,
+                LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS,
+                LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS_DEFAULT);
+    }
+
+    /** @return Time until feed stops restoring the UI. */
+    public static long getSessionLifetimeMs() {
+        return (long) ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, SESSION_LIFETIME_MS,
+                SESSION_LIFETIME_MS_DEFAULT);
+    }
+
+    /**
+     * @return Whether UI initially shows "More" button upon reaching the end of known content,
+     *         when server could potentially have more content.
+     */
+    public static boolean getTriggerImmedatePagination() {
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, TRIGGER_IMMEDIATE_PAGINATION,
+                TRIGGER_IMMEDIATE_PAGINATION_DEFAULT);
+    }
+
+    /** @return How much of a card must be on screen to generate a UMA log view. */
+    public static double getViewLogThreshold() {
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, VIEW_LOG_THRESHOLD,
+                VIEW_LOG_THRESHOLD_DEFAULT);
+    }
+}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
index eece2ac..fb811a5 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -126,7 +126,12 @@
                 .put(ConfigKey.FEED_SERVER_HOST, "https://www.google.com")
                 .put(ConfigKey.FEED_SERVER_PATH_AND_PARAMS,
                         "/httpservice/noretry/NowStreamService/FeedQuery")
-                .put(ConfigKey.SESSION_LIFETIME_MS, 300000L)
+                .put(ConfigKey.SESSION_LIFETIME_MS, FeedConfiguration.getSessionLifetimeMs())
+                .put(ConfigKey.VIEW_LOG_THRESHOLD, FeedConfiguration.getViewLogThreshold())
+                .put(ConfigKey.LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS,
+                        FeedConfiguration.getLoggingImmediateContentThresholdMs())
+                .put(ConfigKey.TRIGGER_IMMEDIATE_PAGINATION,
+                        FeedConfiguration.getTriggerImmedatePagination())
                 .build();
     }
 
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index 31067a2..2e58c75 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -11,6 +11,7 @@
   feed_java_sources = [
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedAppLifecycle.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java",
+    "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoader.java",
@@ -48,6 +49,7 @@
 
   feed_test_java_sources = [
     "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java",
+    "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java",
     "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNetworkBridgeConformanceTest.java",
     "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java",
     "//chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java",
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml
index 4ebd26b..1d038396 100644
--- a/chrome/android/java/res/xml/main_preferences.xml
+++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -30,20 +30,20 @@
         android:order="4"
         android:title="@string/prefs_search_engine"/>
     <org.chromium.chrome.browser.preferences.ChromeBasePreference
-        android:fragment="org.chromium.chrome.browser.preferences.autofill.AutofillProfilesFragment"
-        android:key="autofill_addresses"
+        android:fragment="org.chromium.chrome.browser.preferences.password.SavePasswordsPreferences"
+        android:key="saved_passwords"
         android:order="5"
-        android:title="@string/autofill_addresses_settings_title"/>
+        android:title="@string/prefs_saved_passwords_title"/>
     <org.chromium.chrome.browser.preferences.ChromeBasePreference
         android:fragment="org.chromium.chrome.browser.preferences.autofill.AutofillPaymentMethodsFragment"
         android:key="autofill_payment_methods"
         android:order="6"
         android:title="@string/autofill_payment_methods"/>
     <org.chromium.chrome.browser.preferences.ChromeBasePreference
-        android:fragment="org.chromium.chrome.browser.preferences.password.SavePasswordsPreferences"
-        android:key="saved_passwords"
+        android:fragment="org.chromium.chrome.browser.preferences.autofill.AutofillProfilesFragment"
+        android:key="autofill_addresses"
         android:order="7"
-        android:title="@string/prefs_saved_passwords_title"/>
+        android:title="@string/autofill_addresses_settings_title"/>
     <Preference
         android:fragment="org.chromium.chrome.browser.preferences.NotificationsPreferences"
         android:key="notifications"
diff --git a/chrome/android/java/res/xml/single_website_preferences.xml b/chrome/android/java/res/xml/single_website_preferences.xml
index fdd182c..a76920c0 100644
--- a/chrome/android/java/res/xml/single_website_preferences.xml
+++ b/chrome/android/java/res/xml/single_website_preferences.xml
@@ -61,6 +61,8 @@
     <org.chromium.chrome.browser.preferences.ChromeBaseListPreference
         android:key="background_sync_permission_list" />
     <org.chromium.chrome.browser.preferences.ChromeBaseListPreference
+        android:key="automatic_downloads_permission_list" />
+    <org.chromium.chrome.browser.preferences.ChromeBaseListPreference
         android:key="protected_media_identifier_permission_list" />
     <org.chromium.chrome.browser.preferences.ChromeBaseListPreference
         android:key="autoplay_permission_list" />
diff --git a/chrome/android/java/res/xml/site_settings_preferences.xml b/chrome/android/java/res/xml/site_settings_preferences.xml
index 8165826..d5ae426 100644
--- a/chrome/android/java/res/xml/site_settings_preferences.xml
+++ b/chrome/android/java/res/xml/site_settings_preferences.xml
@@ -53,6 +53,10 @@
     <org.chromium.chrome.browser.preferences.website.SiteSettingsPreference
         android:fragment="org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences"
         android:key="background_sync" />
+    <!-- Automatic Downloads -->
+    <org.chromium.chrome.browser.preferences.website.SiteSettingsPreference
+        android:fragment="org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences"
+        android:key="automatic_downloads" />
     <!-- Protected content -->
     <org.chromium.chrome.browser.preferences.website.SiteSettingsPreference
         android:fragment="org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
index 67a5037..ee1aed5a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -615,7 +615,7 @@
      * @param includeNameInLabel Whether to include the name in the profile's label.
      * @return The list of profiles to suggest to the user.
      */
-    public List<AutofillProfile> getProfilesToSuggest(boolean includeNameInLabel) {
+    public ArrayList<AutofillProfile> getProfilesToSuggest(boolean includeNameInLabel) {
         ThreadUtils.assertOnUiThread();
         return getProfilesWithLabels(
                 nativeGetProfileLabelsToSuggest(
@@ -632,7 +632,7 @@
      *
      * @return The list of billing addresses to suggest to the user.
      */
-    public List<AutofillProfile> getBillingAddressesToSuggest() {
+    public ArrayList<AutofillProfile> getBillingAddressesToSuggest() {
         ThreadUtils.assertOnUiThread();
         return getProfilesWithLabels(
                 nativeGetProfileLabelsToSuggest(
@@ -641,9 +641,9 @@
                 nativeGetProfileGUIDsToSuggest(mPersonalDataManagerAndroid));
     }
 
-    private List<AutofillProfile> getProfilesWithLabels(
+    private ArrayList<AutofillProfile> getProfilesWithLabels(
             String[] profileLabels, String[] profileGUIDs) {
-        List<AutofillProfile> profiles = new ArrayList<AutofillProfile>(profileGUIDs.length);
+        ArrayList<AutofillProfile> profiles = new ArrayList<AutofillProfile>(profileGUIDs.length);
         for (int i = 0; i < profileGUIDs.length; i++) {
             AutofillProfile profile =
                     nativeGetProfileByGUID(mPersonalDataManagerAndroid, profileGUIDs[i]);
@@ -688,14 +688,14 @@
      * will have been processed to be more relevant to the user.
      * @param includeServerCards Whether server cards should be included in the response.
      */
-    public List<CreditCard> getCreditCardsToSuggest(boolean includeServerCards) {
+    public ArrayList<CreditCard> getCreditCardsToSuggest(boolean includeServerCards) {
         ThreadUtils.assertOnUiThread();
         return getCreditCards(
                 nativeGetCreditCardGUIDsToSuggest(mPersonalDataManagerAndroid, includeServerCards));
     }
 
-    private List<CreditCard> getCreditCards(String[] creditCardGUIDs) {
-        List<CreditCard> cards = new ArrayList<CreditCard>(creditCardGUIDs.length);
+    private ArrayList<CreditCard> getCreditCards(String[] creditCardGUIDs) {
+        ArrayList<CreditCard> cards = new ArrayList<CreditCard>(creditCardGUIDs.length);
         for (int i = 0; i < creditCardGUIDs.length; i++) {
             cards.add(nativeGetCreditCardByGUID(mPersonalDataManagerAndroid, creditCardGUIDs[i]));
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
index 84d7b75..fec1a30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -15,8 +15,13 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
+import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsBridge.ContextualSuggestionsResult;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
@@ -68,6 +73,7 @@
     private final EnabledStateMonitor mEnabledStateMonitor;
     private final Handler mHandler = new Handler();
     private final Provider<ContextualSuggestionsSource> mSuggestionSourceProvider;
+    private @Nullable final OverviewModeBehavior mOverviewModeBehavior;
 
     private ContextualSuggestionsCoordinator mCoordinator;
     private View mIphParentView;
@@ -95,15 +101,18 @@
      *         events.
      * @param model The {@link ContextualSuggestionsModel} for the component.
      * @param toolbarManager The {@link ToolbarManager} for the containing activity.
+     * @param layoutManager The {@link LayoutManager} used to retrieve the
+     *         {@link OverviewModeBehavior} if it exists.
      * @param enabledStateMonitor The state monitor that will alert the mediator if the enabled
      *         state for contextual suggestions changes.
-     * @param suggestionSourceProvider The provider of {@link ContextualSuggestionsSource} instances.
+     * @param suggestionSourceProvider The provider of {@link ContextualSuggestionsSource}
+     *         instances.
      */
     @Inject
     ContextualSuggestionsMediator(@Named(LAST_USED_PROFILE) Profile profile,
             TabModelSelector tabModelSelector, ChromeFullscreenManager fullscreenManager,
             ContextualSuggestionsModel model, ToolbarManager toolbarManager,
-            EnabledStateMonitor enabledStateMonitor,
+            LayoutManager layoutManager, EnabledStateMonitor enabledStateMonitor,
             Provider<ContextualSuggestionsSource> suggestionSourceProvider) {
         mProfile = profile.getOriginalProfile();
         mTabModelSelector = tabModelSelector;
@@ -135,6 +144,18 @@
             @Override
             public void onBottomControlsHeightChanged(int bottomControlsHeight) {}
         });
+
+        if (layoutManager instanceof LayoutManagerChrome) {
+            mOverviewModeBehavior = (LayoutManagerChrome) layoutManager;
+            mOverviewModeBehavior.addOverviewModeObserver(new EmptyOverviewModeObserver() {
+                @Override
+                public void onOverviewModeFinishedHiding() {
+                    reportToolbarButtonShown();
+                }
+            });
+        } else {
+            mOverviewModeBehavior = null;
+        }
     }
 
     /**
@@ -243,6 +264,8 @@
                     view -> onToolbarButtonClicked(),
                     R.drawable.contextual_suggestions,
                     R.string.contextual_suggestions_button_description);
+            RecordHistogram.recordBooleanHistogram(
+                    "ContextualSuggestions.ResultsReturnedInOverviewMode", isOverviewModeVisible());
             reportToolbarButtonShown();
         });
     }
@@ -281,7 +304,7 @@
     }
 
     private void reportToolbarButtonShown() {
-        if (mHasRecordedButtonShownForTab || areBrowserControlsHidden()
+        if (mHasRecordedButtonShownForTab || areBrowserControlsHidden() || isOverviewModeVisible()
                 || mSuggestionsSource == null || !mModel.hasSuggestions()) {
             return;
         }
@@ -483,6 +506,10 @@
         mSuggestionsSource.reportEvent(mTabModelSelector.getCurrentTab().getWebContents(), event);
     }
 
+    private boolean isOverviewModeVisible() {
+        return mOverviewModeBehavior != null && mOverviewModeBehavior.overviewVisible();
+    }
+
     @VisibleForTesting
     void showContentInSheetForTesting(boolean disablePeekDelay) {
         if (disablePeekDelay) mHasPeekDelayPassed = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java
index 0d23f29..751713d3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java
@@ -7,6 +7,7 @@
 import android.content.res.Resources;
 
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
@@ -42,7 +43,6 @@
         return mActivity.getTabModelSelector();
     }
 
-
     @Provides
     public ChromeFullscreenManager provideChromeFullscreenManager() {
         return mActivity.getFullscreenManager();
@@ -54,6 +54,11 @@
     }
 
     @Provides
+    public LayoutManager provideLayoutManager() {
+        return mActivity.getCompositorViewHolder().getLayoutManager();
+    }
+
+    @Provides
     public ChromeActivity provideChromeActivity() {
         // Ideally this should provide only the Context instead of specific activity, but currently
         // a lot of code is coupled specifically to ChromeActivity.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java
index 2ab9f1a..199eb937d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/ImageViewHolder.java
@@ -35,7 +35,7 @@
         mThumbnail = itemView.findViewById(R.id.thumbnail);
     }
 
-    // ThumbnailAwareViewHolder implementation.
+    // ListItemViewHolder implementation.
     @Override
     public void bind(PropertyModel properties, ListItem item) {
         OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java
index 6b462f1c..591e4ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/VideoViewHolder.java
@@ -48,6 +48,7 @@
         mThumbnail = itemView.findViewById(R.id.thumbnail);
     }
 
+    // MoreButtonViewHolder implementation.
     @Override
     public void bind(PropertyModel properties, ListItem item) {
         super.bind(properties, item);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/view/AsyncImageView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/view/AsyncImageView.java
index 54c1d5f..8267d1db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/view/AsyncImageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/view/AsyncImageView.java
@@ -39,12 +39,10 @@
     private final Drawable mUnavailableDrawable;
     private final Drawable mWaitingDrawable;
 
-    /**
-     * Used to handle synchronous responses to the callback in
-     * {@link #setAsyncImageDrawable(Factory)}.
-     */
-    private boolean mWaitingForResponse;
+    private Factory mFactory;
+
     private Runnable mCancelable;
+    private boolean mWaitingForResponse;
 
     /** Creates an {@link AsyncImageDrawable instance. */
     public AsyncImageView(Context context) {
@@ -81,10 +79,10 @@
     public void setAsyncImageDrawable(Factory factory) {
         // This will clear out any outstanding request.
         setImageDrawable(null);
-
         setForegroundDrawableCompat(mWaitingDrawable);
-        mCancelable = factory.get(this ::setAsyncImageDrawableResponse, getWidth(), getHeight());
-        if (!mWaitingForResponse) mCancelable = null;
+
+        mFactory = factory;
+        retrieveDrawableIfNeeded();
     }
 
     // RoundedCornerImageView implementation.
@@ -92,20 +90,52 @@
     public void setImageDrawable(Drawable drawable) {
         // If we had an outstanding async request, cancel it because we're now setting the drawable
         // to something else.
-        if (mWaitingForResponse) {
-            if (mCancelable != null) mCancelable.run();
-            mCancelable = null;
-            mWaitingForResponse = false;
-            setForegroundDrawableCompat(null);
-        }
+        cancelPreviousDrawableRequest();
 
+        setForegroundDrawableCompat(null);
         super.setImageDrawable(drawable);
     }
 
+    // View implementation.
+    @Override
+    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+
+        retrieveDrawableIfNeeded();
+    }
+
     private void setAsyncImageDrawableResponse(Drawable drawable) {
         mCancelable = null;
         mWaitingForResponse = false;
         setForegroundDrawableCompat(drawable == null ? mUnavailableDrawable : null);
         setImageDrawable(drawable);
     }
-}
\ No newline at end of file
+
+    private void cancelPreviousDrawableRequest() {
+        mFactory = null;
+
+        if (mCancelable != null) {
+            mCancelable.run();
+            mCancelable = null;
+            mWaitingForResponse = false;
+        }
+    }
+
+    private void retrieveDrawableIfNeeded() {
+        // If width or height are not valid, don't start to retrieve the drawable since the
+        // thumbnail may be scaled down to 0.
+        if (getWidth() <= 0 || getHeight() <= 0) return;
+
+        if (mFactory != null) {
+            // Start to retrieve the drawable.
+            mWaitingForResponse = true;
+            mCancelable =
+                    mFactory.get(this ::setAsyncImageDrawableResponse, getWidth(), getHeight());
+
+            // If setAsyncImageDrawableResponse is called synchronously, clear mCancelable.
+            if (!mWaitingForResponse) mCancelable = null;
+
+            mFactory = null;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
index 6d43da68..36b709d3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -357,7 +357,7 @@
 
     @Override
     public int getBottomControlsHeight() {
-        return mBottomControlContainerHeight;
+        return VrModuleProvider.getDelegate().isInVr() ? 0 : mBottomControlContainerHeight;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java
index 8bc01f3..9b58248 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java
@@ -38,6 +38,20 @@
     }
 
     /**
+     * Gets the idle reason. Only meaningful if we are in PLAYER_STATE_IDLE.
+     * - IDLE_REASON_NONE = 0
+     * - IDLE_REASON_FINISHED = 1
+     * - IDLE_REASON_CANCELED = 2
+     * - IDLE_REASON_INTERRUPTED = 3
+     * - IDLE_REASON_ERROR = 4
+     * See https://developers.google.com/android/reference/com/google/android/gms/cast/MediaStatus
+     */
+    @CalledByNative
+    public int idleReason() {
+        return mStatus.getIdleReason();
+    }
+
+    /**
      * The main title of the media. For example, in a MediaStatus representing
      * a YouTube Cast session, this could be the title of the video.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 884fa69..67e8ab0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -280,7 +280,7 @@
 
         if (FeatureUtilities.isBottomToolbarEnabled()) {
             ((MarginLayoutParams) getLayoutParams()).bottomMargin =
-                    getResources().getDimensionPixelSize(R.dimen.bottom_toolbar_height);
+                    mTab.getFullscreenManager().getBottomControlsHeight();
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
index 582bdc8..500b10d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorController.java
@@ -56,6 +56,7 @@
 
     @SuppressLint("StaticFieldLeak")
     private static OfflineIndicatorController sInstance;
+    private static int sTimeToWaitForStableOfflineForTesting;
 
     private boolean mIsShowingOfflineIndicator;
     // Set to true if the offline indicator has been shown once since the activity has resumed.
@@ -266,9 +267,14 @@
     }
 
     int getTimeToWaitForStableOffline() {
-        int seconds = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                ChromeFeatureList.OFFLINE_INDICATOR, PARAM_STABLE_OFFLINE_WAIT_SECONDS,
-                STABLE_OFFLINE_DEFAULT_WAIT_SECONDS);
+        int seconds;
+        if (sTimeToWaitForStableOfflineForTesting != 0) {
+            seconds = sTimeToWaitForStableOfflineForTesting;
+        } else {
+            seconds = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                    ChromeFeatureList.OFFLINE_INDICATOR, PARAM_STABLE_OFFLINE_WAIT_SECONDS,
+                    STABLE_OFFLINE_DEFAULT_WAIT_SECONDS);
+        }
         return seconds * 1000;
     }
 
@@ -280,6 +286,11 @@
     }
 
     @VisibleForTesting
+    static void setTimeToWaitForStableOfflineForTesting(int waitSeconds) {
+        sTimeToWaitForStableOfflineForTesting = waitSeconds;
+    }
+
+    @VisibleForTesting
     ConnectivityDetector getConnectivityDetectorForTesting() {
         return mConnectivityDetector;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
index 2bae25c..7ef19b4b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
@@ -340,6 +340,14 @@
     }
 
     /**
+     * @return true if automatic downloads is managed by policy.
+     */
+    public boolean isAutomaticDownloadsManaged() {
+        return isContentSettingManaged(
+                ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS);
+    }
+
+    /**
      * Sets the preference that controls translate
      */
     public void setTranslateEnabled(boolean enabled) {
@@ -682,15 +690,15 @@
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_USB_GUARD:
                 setContentSettingEnabled(contentSettingsType, allow);
                 break;
+            case ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
+                nativeSetAutomaticDownloadsEnabled(allow);
+                break;
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOPLAY:
                 nativeSetAutoplayEnabled(allow);
                 break;
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC:
                 nativeSetBackgroundSyncEnabled(allow);
                 break;
-            case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
-                nativeSetCameraEnabled(allow);
-                break;
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_CLIPBOARD_READ:
                 nativeSetClipboardEnabled(allow);
                 break;
@@ -700,6 +708,9 @@
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION:
                 nativeSetAllowLocationEnabled(allow);
                 break;
+            case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+                nativeSetCameraEnabled(allow);
+                break;
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
                 nativeSetMicEnabled(allow);
                 break;
@@ -730,14 +741,16 @@
             // Returns true if websites are allowed to request permission to access USB devices.
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_USB_GUARD:
                 return isContentSettingEnabled(contentSettingsType);
+            case ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
+                return nativeGetAutomaticDownloadsEnabled();
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOPLAY:
                 return nativeGetAutoplayEnabled();
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC:
                 return nativeGetBackgroundSyncEnabled();
-            case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
-                return nativeGetCameraEnabled();
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_COOKIES:
                 return nativeGetAcceptCookiesEnabled();
+            case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+                return nativeGetCameraEnabled();
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
                 return nativeGetMicEnabled();
             case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
@@ -1069,6 +1082,7 @@
     private native boolean nativeGetAcceptCookiesEnabled();
     private native boolean nativeGetAcceptCookiesUserModifiable();
     private native boolean nativeGetAcceptCookiesManagedByCustodian();
+    private native boolean nativeGetAutomaticDownloadsEnabled();
     private native boolean nativeGetAutoplayEnabled();
     private native boolean nativeGetBackgroundSyncEnabled();
     private native boolean nativeGetBlockThirdPartyCookiesEnabled();
@@ -1084,11 +1098,11 @@
     private native boolean nativeGetPasswordEchoEnabled();
     private native boolean nativeGetFirstRunEulaAccepted();
     private native boolean nativeGetCameraEnabled();
-    private native void nativeSetCameraEnabled(boolean allow);
+    private native void nativeSetCameraEnabled(boolean enabled);
     private native boolean nativeGetCameraUserModifiable();
     private native boolean nativeGetCameraManagedByCustodian();
     private native boolean nativeGetMicEnabled();
-    private native void nativeSetMicEnabled(boolean allow);
+    private native void nativeSetMicEnabled(boolean enabled);
     private native boolean nativeGetMicUserModifiable();
     private native boolean nativeGetMicManagedByCustodian();
     private native boolean nativeGetTranslateEnabled();
@@ -1114,23 +1128,24 @@
             int clearBrowsingDataTab, int timePeriod);
     private native int nativeGetLastClearBrowsingDataTab();
     private native void nativeSetLastClearBrowsingDataTab(int lastTab);
-    private native void nativeSetAutoplayEnabled(boolean allow);
-    private native void nativeSetAllowCookiesEnabled(boolean allow);
-    private native void nativeSetBackgroundSyncEnabled(boolean allow);
+    private native void nativeSetAutomaticDownloadsEnabled(boolean enabled);
+    private native void nativeSetAutoplayEnabled(boolean enabled);
+    private native void nativeSetAllowCookiesEnabled(boolean enabled);
+    private native void nativeSetBackgroundSyncEnabled(boolean enabled);
     private native void nativeSetBlockThirdPartyCookiesEnabled(boolean enabled);
-    private native void nativeSetClipboardEnabled(boolean allow);
+    private native void nativeSetClipboardEnabled(boolean enabled);
     private native void nativeSetDoNotTrackEnabled(boolean enabled);
     private native void nativeSetRememberPasswordsEnabled(boolean allow);
     private native void nativeSetPasswordManagerAutoSigninEnabled(boolean enabled);
     private native boolean nativeGetAllowLocationEnabled();
     private native boolean nativeGetNotificationsEnabled();
     private native boolean nativeGetNotificationsVibrateEnabled();
-    private native void nativeSetAllowLocationEnabled(boolean allow);
-    private native void nativeSetNotificationsEnabled(boolean allow);
+    private native void nativeSetAllowLocationEnabled(boolean enabled);
+    private native void nativeSetNotificationsEnabled(boolean enabled);
     private native void nativeSetNotificationsVibrateEnabled(boolean enabled);
     private native void nativeSetPasswordEchoEnabled(boolean enabled);
-    private native void nativeSetSensorsEnabled(boolean allow);
-    private native void nativeSetSoundEnabled(boolean allow);
+    private native void nativeSetSensorsEnabled(boolean enabled);
+    private native void nativeSetSoundEnabled(boolean enabled);
     private native boolean nativeCanPrefetchAndPrerender();
     private native AboutVersionStrings nativeGetAboutVersionStrings();
     private native void nativeSetContextualSearchPreference(String preference);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingException.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingException.java
index c1458df..19f7048 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingException.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingException.java
@@ -17,8 +17,9 @@
  * Exception information for a given origin.
  */
 public class ContentSettingException implements Serializable {
-    @IntDef({Type.ADS, Type.AUTOPLAY, Type.BACKGROUND_SYNC, Type.COOKIE, Type.JAVASCRIPT,
-            Type.POPUP, Type.SOUND})
+    @IntDef({Type.ADS, Type.AUTOMATIC_DOWNLOADS, Type.AUTOPLAY,
+             Type.BACKGROUND_SYNC, Type.COOKIE, Type.JAVASCRIPT, Type.POPUP,
+             Type.SOUND})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {
         // Values used to address array index below, inside Website and SingleWebsitePreferences.
@@ -30,13 +31,16 @@
         int JAVASCRIPT = 4;
         int POPUP = 5;
         int SOUND = 6;
+        int AUTOMATIC_DOWNLOADS = 7;
         /**
          * Number of handled exceptions used for calculating array sizes.
          */
-        int NUM_ENTRIES = 7;
+        int NUM_ENTRIES = 8;
     }
 
     // Mapping from {@link Type} to ContentSettingType.
+    // TODO(https://crbug.com/616321) Add a unit test to verify that Type and
+    // CONTENT_TYPES are in sync.
     final static int[] CONTENT_TYPES = {
             ContentSettingsType.CONTENT_SETTINGS_TYPE_ADS,
             ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOPLAY,
@@ -45,7 +49,7 @@
             ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT,
             ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS,
             ContentSettingsType.CONTENT_SETTINGS_TYPE_SOUND,
-    };
+            ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS};
 
     private final int mContentSettingType;
     private final String mPattern;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
index 2ac9b6d..e89efcd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
@@ -96,6 +96,11 @@
                             R.string.ads_permission_title, ContentSetting.ALLOW,
                             ContentSetting.BLOCK, 0,
                             R.string.website_settings_category_ads_blocked));
+            localMap.put(ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
+                    new ResourceItem(R.drawable.infobar_downloading,
+                            R.string.automatic_downloads_permission_title,
+                            R.string.automatic_downloads_permission_title, ContentSetting.ASK,
+                            ContentSetting.BLOCK, R.string.website_settings_category_ask, 0));
             localMap.put(ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOPLAY,
                     new ResourceItem(R.drawable.settings_autoplay, R.string.autoplay_title,
                                  R.string.autoplay_title, ContentSetting.ALLOW,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index 45e2c8b..c625f1b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -484,7 +484,9 @@
 
     private String getAddExceptionDialogMessage() {
         int resource = 0;
-        if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)) {
+        if (mCategory.showSites(SiteSettingsCategory.Type.AUTOMATIC_DOWNLOADS)) {
+            resource = R.string.website_settings_add_site_description_automatic_downloads;
+        } else if (mCategory.showSites(SiteSettingsCategory.Type.AUTOPLAY)) {
             resource = R.string.website_settings_add_site_description_autoplay;
         } else if (mCategory.showSites(SiteSettingsCategory.Type.BACKGROUND_SYNC)) {
             resource = R.string.website_settings_add_site_description_background_sync;
@@ -580,6 +582,10 @@
                 && !PrefServiceBridge.getInstance().isCategoryEnabled(
                            ContentSettingsType.CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC)) {
             exception = true;
+        } else if (mCategory.showSites(SiteSettingsCategory.Type.AUTOMATIC_DOWNLOADS)
+                && !PrefServiceBridge.getInstance().isCategoryEnabled(
+                           ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS)) {
+            exception = true;
         }
         if (exception) {
             getPreferenceScreen().addPreference(new AddExceptionPreference(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
index 9e2596b..9fe6008 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -73,6 +73,8 @@
             "ads_permission_list", // ContentSettingException.Type.ADS
             "autoplay_permission_list", // ContentSettingException.Type.AUTOPLAY
             "background_sync_permission_list", // ContentSettingException.Type.BACKGROUND_SYNC
+            "automatic_downloads_permission_list",
+            // ContentSettingException.Type.AUTOMATIC_DOWNLOADS
             "cookies_permission_list", // ContentSettingException.Type.COOKIE
             "javascript_permission_list", // ContentSettingException.Type.JAVASCRIPT
             "popup_permission_list", // ContentSettingException.Type.POPUP
@@ -84,7 +86,8 @@
             "microphone_permission_list", // PermissionInfo.Type.MICROPHONE
             "midi_sysex_permission_list", // PermissionInfo.Type.MIDI
             "push_notifications_list", // PermissionInfo.Type.NOTIFICATION
-            "protected_media_identifier_permission_list", // PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER
+            "protected_media_identifier_permission_list",
+            // PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER
             "sensors_permission_list", // PermissionInfo.Type.SENSORS
     };
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsCategory.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsCategory.java
index 51f2196..ae496a6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsCategory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsCategory.java
@@ -37,10 +37,10 @@
  * A base class for dealing with website settings categories.
  */
 public class SiteSettingsCategory {
-    @IntDef({Type.ALL_SITES, Type.ADS, Type.AUTOPLAY, Type.BACKGROUND_SYNC, Type.CAMERA,
-            Type.CLIPBOARD, Type.COOKIES, Type.DEVICE_LOCATION, Type.JAVASCRIPT, Type.MICROPHONE,
-            Type.NOTIFICATIONS, Type.POPUPS, Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND,
-            Type.USE_STORAGE, Type.USB})
+    @IntDef({Type.ALL_SITES, Type.ADS, Type.AUTOMATIC_DOWNLOADS, Type.AUTOPLAY,
+            Type.BACKGROUND_SYNC, Type.CAMERA, Type.CLIPBOARD, Type.COOKIES, Type.DEVICE_LOCATION,
+            Type.JAVASCRIPT, Type.MICROPHONE, Type.NOTIFICATIONS, Type.POPUPS, Type.PROTECTED_MEDIA,
+            Type.SENSORS, Type.SOUND, Type.USE_STORAGE, Type.USB})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {
         // Values used to address array index. Should be enumerated from 0 and
@@ -63,15 +63,18 @@
         int SOUND = 14;
         int USE_STORAGE = 15;
         int USB = 16;
+        int AUTOMATIC_DOWNLOADS = 17;
         /**
          * Number of handled categories used for calculating array sizes.
          */
-        int NUM_ENTRIES = 17;
+        int NUM_ENTRIES = 18;
     }
 
     /**
      * Mapping from Type to String used in preferences. Values are sorted like
      * Type constants.
+     * TODO(https://crbug.com:/616321) Add a unit test to verify that Type and
+     * PREFERENCE_KEYS are in sync.
      */
     private static final String[] PREFERENCE_KEYS = {
             "all_sites", // Type.ALL_SITES
@@ -91,6 +94,7 @@
             "sound", // Type.SOUND
             "use_storage", // Type.USE_STORAGE
             "usb", // Type.USB
+            "automatic_downloads", // Type.AUTOMATIC_DOWNLOADS
     };
 
     /**
@@ -117,6 +121,8 @@
             ContentSettingsType.CONTENT_SETTINGS_TYPE_SOUND, // Type.SOUND
             -1, // Type.USE_STORAGE
             ContentSettingsType.CONTENT_SETTINGS_TYPE_USB_GUARD, // Type.USB
+            ContentSettingsType
+                    .CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, // Type.AUTOMATIC_DOWNLOADS,
     };
 
     // The id of this category.
@@ -217,7 +223,9 @@
      */
     public boolean isManaged() {
         PrefServiceBridge prefs = PrefServiceBridge.getInstance();
-        if (showSites(Type.BACKGROUND_SYNC)) {
+        if (showSites(Type.AUTOMATIC_DOWNLOADS)) {
+            return prefs.isAutomaticDownloadsManaged();
+        } else if (showSites(Type.BACKGROUND_SYNC)) {
             return prefs.isBackgroundSyncManaged();
         } else if (showSites(Type.COOKIES)) {
             return !prefs.isAcceptCookiesUserModifiable();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
index 970ed7b..95a1c12 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
@@ -136,6 +136,8 @@
             if (SiteSettingsCategory.adsCategoryEnabled()) {
                 websitePrefs.add(Type.ADS);
             }
+            websitePrefs.add(Type.AUTOMATIC_DOWNLOADS);
+
             // When showing the main menu, if Protected Content is not available, only Autoplay
             // will be visible.
             if (!mProtectedContentMenuAvailable) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
index f6c60444..815cdf9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
@@ -131,6 +131,9 @@
         // Background sync permission is per-origin.
         queue.add(new ExceptionInfoFetcher(
                 ContentSettingsType.CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC));
+        // Automatic Downloads permission is per-origin.
+        queue.add(new ExceptionInfoFetcher(
+                ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS));
         // Autoplay permission is per-origin.
         queue.add(new ExceptionInfoFetcher(ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOPLAY));
         // USB device permission is per-origin and per-embedder.
@@ -196,6 +199,10 @@
             // Background sync info is per-origin.
             queue.add(new ExceptionInfoFetcher(
                     ContentSettingsType.CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC));
+        } else if (category.showSites(SiteSettingsCategory.Type.AUTOMATIC_DOWNLOADS)) {
+            // Automatic downloads info is per-origin.
+            queue.add(new ExceptionInfoFetcher(
+                    ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS));
         } else if (category.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
             // Protected media identifier permission is per-origin and per-embedder.
             queue.add(new PermissionInfoFetcher(PermissionInfo.Type.PROTECTED_MEDIA_IDENTIFIER));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java
index d599fff..28efe5c1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java
@@ -13,12 +13,16 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.ActivityTabProvider.HintlessActivityTabObserver;
 import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.layouts.ToolbarSwipeLayout;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.BottomToolbarViewBinder.ViewHolder;
 import org.chromium.chrome.browser.toolbar.ToolbarButtonSlotData.ToolbarButtonData;
@@ -62,7 +66,8 @@
      * @param secondSlotData The data required to fill in the second bottom toolbar button slot.
      */
     public BottomToolbarCoordinator(ChromeFullscreenManager fullscreenManager, ViewGroup root,
-            ToolbarButtonSlotData firstSlotData, ToolbarButtonSlotData secondSlotData) {
+            ToolbarButtonSlotData firstSlotData, ToolbarButtonSlotData secondSlotData,
+            final ActivityTabProvider tabProvider) {
         BottomToolbarModel model = new BottomToolbarModel();
 
         int shadowHeight =
@@ -92,6 +97,16 @@
 
         mMediator = new BottomToolbarMediator(model, fullscreenManager, root.getResources(),
                 firstSlotData, secondSlotData, mNormalPrimaryColor);
+
+        final View iphAnchor = toolbarRoot.findViewById(R.id.bottom_toolbar_container);
+        tabProvider.addObserverAndTrigger(new HintlessActivityTabObserver() {
+            @Override
+            public void onActivityTabChanged(Tab tab) {
+                if (tab == null) return;
+                mMediator.showIPH(iphAnchor, TrackerFactory.getTrackerForProfile(tab.getProfile()));
+                tabProvider.removeObserver(this);
+            }
+        });
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
index 899a7d5..7965a56 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.toolbar;
 
 import android.content.res.Resources;
+import android.view.View;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver;
@@ -18,9 +19,13 @@
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
 import org.chromium.chrome.browser.toolbar.ToolbarButtonSlotData.ToolbarButtonData;
+import org.chromium.chrome.browser.widget.textbubble.TextBubble;
+import org.chromium.components.feature_engagement.FeatureConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.base.WindowAndroid.KeyboardVisibilityListener;
 import org.chromium.ui.resources.ResourceManager;
+import org.chromium.ui.widget.ViewRectProvider;
 
 /**
  * This class is responsible for reacting to events from the outside world, interacting with other
@@ -30,6 +35,9 @@
 class BottomToolbarMediator implements FullscreenListener, KeyboardVisibilityListener,
                                        OverlayPanelManagerObserver, OverviewModeObserver,
                                        SceneChangeObserver {
+    /** The amount of time to show the Duet help bubble for. */
+    private static final int DUET_IPH_BUBBLE_SHOW_DURATION_MS = 6000;
+
     /** The model for the bottom toolbar that holds all of its state. */
     private BottomToolbarModel mModel;
 
@@ -240,4 +248,21 @@
     void setPrimaryColor(int color) {
         mModel.set(BottomToolbarModel.PRIMARY_COLOR, color);
     }
+
+    /**
+     * Maybe show the IPH bubble for Chrome Duet.
+     * @param anchor The view to anchor the IPH to.
+     * @param tracker A tracker for IPH.
+     */
+    void showIPH(View anchor, Tracker tracker) {
+        if (tracker.shouldTriggerHelpUI(FeatureConstants.CHROME_DUET_FEATURE)) {
+            TextBubble bubble =
+                    new TextBubble(anchor.getContext(), anchor, R.string.iph_duet_icons_moved,
+                            R.string.iph_duet_icons_moved, true, new ViewRectProvider(anchor));
+            bubble.setAutoDismissTimeout(DUET_IPH_BUBBLE_SHOW_DURATION_MS);
+            bubble.addOnDismissListener(
+                    () -> tracker.dismissed(FeatureConstants.CHROME_DUET_FEATURE));
+            bubble.show();
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 26792e8..ed6f4cf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.toolbar;
 
 import android.content.res.Configuration;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Looper;
@@ -148,9 +147,6 @@
     private static final ActionEvent ACCELERATOR_BUTTON_TAP_ACTION =
             new ActionEvent("MobileToolbarOmniboxAcceleratorTap");
 
-    /** The amount of time to show the Duet help bubble for. */
-    private static final int DUET_IPH_BUBBLE_SHOW_DURATION_MS = 6000;
-
     /**
      * The number of ms to wait before reporting to UMA omnibox interaction metrics.
      */
@@ -692,7 +688,7 @@
                     new ToolbarButtonSlotData(createSearchAccelerator());
             mBottomToolbarCoordinator = new BottomToolbarCoordinator(
                     mActivity.getFullscreenManager(), mActivity.findViewById(R.id.coordinator),
-                    firstButtonSlot, secondButtonSlot);
+                    firstButtonSlot, secondButtonSlot, mActivity.getActivityTabProvider());
             if (mAppMenuButtonHelper != null) mAppMenuButtonHelper.setMenuShowsFromBottom(true);
         }
     }
@@ -923,9 +919,6 @@
                                 wrapBottomToolbarClickListenerForIPH(newTabClickHandler)),
                         tabModelSelector.getCurrentModel().isIncognito());
 
-                Tab currentTab = tabModelSelector.getCurrentTab();
-                maybeShowDuetHelpBubble(currentTab);
-
                 // Allow the bottom toolbar to be focused in accessibility after the top toolbar.
                 ApiCompatibilityUtils.setAccessibilityTraversalBefore(
                         mLocationBar.getContainerView(), R.id.bottom_toolbar);
@@ -937,34 +930,6 @@
     }
 
     /**
-     * Maybe show the IPH bubble for Chrome Duet.
-     * @param tab The active tab.
-     */
-    private void maybeShowDuetHelpBubble(Tab tab) {
-        if (tab == null) return;
-        assert mToolbar != null;
-        final Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
-        if (tracker.shouldTriggerHelpUI(FeatureConstants.CHROME_DUET_FEATURE)) {
-            TextBubble bubble;
-            // If on the NTP, there is no toolbar. Place the bubble in the space where the toolbar
-            // would be.
-            if (NewTabPage.isNTPUrl(tab.getUrl())) {
-                bubble = new TextBubble(mToolbar.getContext(), mToolbar,
-                        R.string.iph_duet_icons_moved, R.string.iph_duet_icons_moved, false,
-                        new Rect(0, 0, mToolbar.getWidth(), 0));
-            } else {
-                bubble = new TextBubble(mToolbar.getContext(), mToolbar,
-                        R.string.iph_duet_icons_moved, R.string.iph_duet_icons_moved, true,
-                        new ViewRectProvider(mToolbar));
-            }
-            bubble.setAutoDismissTimeout(DUET_IPH_BUBBLE_SHOW_DURATION_MS);
-            bubble.addOnDismissListener(
-                    () -> tracker.dismissed(FeatureConstants.CHROME_DUET_FEATURE));
-            bubble.show();
-        }
-    }
-
-    /**
      * Show the update badge in both the top and bottom toolbar.
      * TODO(amaralp): Only the top or bottom menu should be visible.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java
index ea181134..b8d08db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -1252,7 +1252,7 @@
     }
 
     public void registerUiOperationCallbackForTesting(
-            int actionType, Runnable resultCallback, int quiescenceTimeoutMs) {
+            int actionType, Runnable resultCallback, int timeoutMs, int elementName) {
         assert actionType < UiTestOperationType.NUM_UI_TEST_OPERATION_TYPES;
         // Fill the ArrayLists if this is the first time the method has been called.
         if (mUiOperationResults == null) {
@@ -1265,16 +1265,15 @@
                 mUiOperationResultCallbacks.add(null);
             }
         }
-        // We currently have two callback types, and only one of them actually cares about the
-        // value given to the callback, so we can blindly set the default here. If more are added,
-        // their defaults will have to be properly set here.
-        mUiOperationResults.set(actionType, VrUiTestActivityResult.UNREPORTED);
+        mUiOperationResults.set(actionType, UiTestOperationResult.UNREPORTED);
         mUiOperationResultCallbacks.set(actionType, resultCallback);
 
         // In the case of the UI activity quiescence callback type, we need to let the native UI
         // know how long to wait before timing out.
         if (actionType == UiTestOperationType.UI_ACTIVITY_RESULT) {
-            nativeSetUiExpectingActivityForTesting(mNativeVrShell, quiescenceTimeoutMs);
+            nativeSetUiExpectingActivityForTesting(mNativeVrShell, timeoutMs);
+        } else if (actionType == UiTestOperationType.ELEMENT_VISIBILITY_CHANGE) {
+            nativeWatchElementForVisibilityChangeForTesting(mNativeVrShell, elementName, timeoutMs);
         }
     }
 
@@ -1344,6 +1343,8 @@
             long nativeVrShell, int quiescenceTimeoutMs);
     private native void nativeSaveNextFrameBufferToDiskForTesting(
             long nativeVrShell, String filepathBase);
+    private native void nativeWatchElementForVisibilityChangeForTesting(
+            long nativeVrShell, int elementName, int timeoutMs);
     private native void nativeResumeContentRendering(long nativeVrShell);
     private native void nativeOnOverlayTextureEmptyChanged(long nativeVrShell, boolean empty);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java
index 347c2be..39dfa74 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java
@@ -17,6 +17,7 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
@@ -31,6 +32,7 @@
 
     private static IGvrKeyboardLoader sLoader;
     private static ClassLoader sRemoteClassLoader;
+    private static boolean sFailLoadForTesting;
     // GVR doesn't support setting the context twice in the application's lifetime and crashes if we
     // do so. Setting the same context wrapper is a no-op, so we keep a reference to the one we
     // create and use it across re-initialization of the keyboard api.
@@ -67,7 +69,13 @@
         }
     }
 
+    @VisibleForTesting
+    public static void setFailLoadForTesting(boolean shouldFail) {
+        sFailLoadForTesting = shouldFail;
+    }
+
     private static IGvrKeyboardLoader getLoader() {
+        if (sFailLoadForTesting) return null;
         if (sLoader == null) {
             ClassLoader remoteClassLoader = (ClassLoader) getRemoteClassLoader();
             if (remoteClassLoader != null) {
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 6067c00..9a7a278 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -915,6 +915,9 @@
       <message name="IDS_BACKGROUND_SYNC_PERMISSION_TITLE" desc="Title of the permission that allows websites to queue an operation for the next time the device is online[CHAR-LIMIT=32]">
         Background sync
       </message>
+      <message name="IDS_AUTOMATIC_DOWNLOADS_PERMISSION_TITLE" desc="Title of the permission that allows websites to download multiple files automatically.">
+        Automatic downloads
+      </message>
       <message name="IDS_WEBSITE_SETTINGS_ADD_SITE" desc="The label for the button to add a new website to the exception list.">
         Add site exception
       </message>
@@ -936,6 +939,9 @@
       <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_BACKGROUND_SYNC" desc="The description for the allow Background Sync for website dialog.">
         Allow Background Sync for a specific site.
       </message>
+      <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_AUTOMATIC_DOWNLOADS" desc="The description for the allow Automatic Downloads for website dialog.">
+        Allow a site to download multiple files automatically.
+      </message>
       <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_SOUND_ALLOW" desc="The description for the allow sound for website dialog.">
         Allow sound for a specific site.
       </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
index fa38a152..7611959f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
@@ -51,7 +51,8 @@
 
         List<String> finalDisabledList = getArgsList(false);
         assertThat(finalDisabledList, hasItems("Two"));
-        assertThat(finalDisabledList.size(), equalTo(1));
+        // ChromeActivityTestRule disables OFFLINE_INDICATOR feature.
+        assertThat(finalDisabledList.size(), equalTo(2));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
index 0ddc3d6..e0748ca 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
@@ -16,6 +16,7 @@
 import static org.chromium.chrome.browser.download.DownloadSnackbarController.INVALID_NOTIFICATION_ID;
 
 import android.app.Notification;
+import android.support.annotation.IntDef;
 import android.support.test.filters.SmallTest;
 import android.support.v4.app.ServiceCompat;
 
@@ -29,6 +30,8 @@
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -49,14 +52,22 @@
      * Mimics behavior of DownloadForegroundService except for calls to the actual service.
      */
     public static class MockDownloadForegroundService extends DownloadForegroundService {
-        static enum MethodID { START_FOREGROUND, STOP_FOREGROUND_FLAGS, RELAUNCH_NOTIFICATION }
+        @IntDef({MethodID.START_FOREGROUND, MethodID.STOP_FOREGROUND_FLAGS,
+                MethodID.RELAUNCH_NOTIFICATION})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface MethodID {
+            int START_FOREGROUND = 0;
+            int STOP_FOREGROUND_FLAGS = 1;
+            int RELAUNCH_NOTIFICATION = 2;
+        }
 
         int mTargetSdk = 20;
         int mStopForegroundFlags = -1;
         int mRelaunchedNotificationId = INVALID_NOTIFICATION_ID;
         int mNextNotificationId = INVALID_NOTIFICATION_ID;
 
-        List<MethodID> mMethodCalls = new ArrayList<>();
+        // Used for saving MethodID values.
+        List<Integer> mMethodCalls = new ArrayList<>();
 
         // Clears stored flags/boolean/id/method calls. Call between tests runs.
         void clearStoredState() {
@@ -123,7 +134,7 @@
     @Feature({"Download"})
     public void testStartForeground_sdkAtLeast24() {
         mForegroundService.mTargetSdk = 24;
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.START_FOREGROUND);
 
         // Test the case where there is no other pinned notification and the service starts.
@@ -165,7 +176,7 @@
     @SmallTest
     @Feature({"Download"})
     public void testStartForeground_sdkLessThan24() {
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.START_FOREGROUND);
 
         // Test the case where there is no other pinned notification and the service starts.
@@ -204,7 +215,7 @@
     @Feature({"Download"})
     public void testStopForeground_sdkAtLeast24() {
         mForegroundService.mTargetSdk = 24;
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS);
 
         // When the service gets stopped with request to detach but not kill notification (pause).
@@ -264,7 +275,7 @@
         boolean isNotificationHandledProperly = mForegroundService.stopDownloadForegroundService(
                 DownloadForegroundService.StopForegroundNotification.DETACH_OR_PERSIST,
                 FAKE_DOWNLOAD_ID1, mNotification);
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS);
         assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls);
         assertEquals(ServiceCompat.STOP_FOREGROUND_DETACH, mForegroundService.mStopForegroundFlags);
@@ -323,7 +334,7 @@
         boolean isNotificationHandledProperly = mForegroundService.stopDownloadForegroundService(
                 DownloadForegroundService.StopForegroundNotification.DETACH_OR_PERSIST,
                 FAKE_DOWNLOAD_ID1, mNotification);
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS);
         assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls);
         assertEquals(ServiceCompat.STOP_FOREGROUND_DETACH, mForegroundService.mStopForegroundFlags);
@@ -381,7 +392,7 @@
         boolean isNotificationHandledProperly = mForegroundService.stopDownloadForegroundService(
                 DownloadForegroundService.StopForegroundNotification.DETACH_OR_PERSIST,
                 FAKE_DOWNLOAD_ID1, mNotification);
-        List<MockDownloadForegroundService.MethodID> expectedMethodCalls =
+        List<Integer> expectedMethodCalls =
                 Arrays.asList(MockDownloadForegroundService.MethodID.RELAUNCH_NOTIFICATION,
                         MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS);
         assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
index d021622d..f08dd36 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadManagerServiceTest.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.support.annotation.IntDef;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 import android.util.Log;
@@ -37,6 +38,8 @@
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.net.ConnectionType;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Queue;
@@ -63,18 +66,23 @@
         /**
          * The Ids of different methods in this mock object.
          */
-        static enum MethodID {
-            DOWNLOAD_SUCCESSFUL,
-            DOWNLOAD_FAILED,
-            DOWNLOAD_PROGRESS,
-            DOWNLOAD_PAUSED,
-            DOWNLOAD_INTERRUPTED,
-            CANCEL_DOWNLOAD_ID,
-            CLEAR_PENDING_DOWNLOADS
+        @IntDef({MethodID.DOWNLOAD_SUCCESSFUL, MethodID.DOWNLOAD_FAILED, MethodID.DOWNLOAD_PROGRESS,
+                MethodID.DOWNLOAD_PAUSED, MethodID.DOWNLOAD_INTERRUPTED,
+                MethodID.CANCEL_DOWNLOAD_ID, MethodID.CLEAR_PENDING_DOWNLOADS})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface MethodID {
+            int DOWNLOAD_SUCCESSFUL = 0;
+            int DOWNLOAD_FAILED = 1;
+            int DOWNLOAD_PROGRESS = 2;
+            int DOWNLOAD_PAUSED = 3;
+            int DOWNLOAD_INTERRUPTED = 4;
+            int CANCEL_DOWNLOAD_ID = 5;
+            int CLEAR_PENDING_DOWNLOADS = 6;
         }
 
-        private final Queue<Pair<MethodID, Object>> mExpectedCalls =
-                new ConcurrentLinkedQueue<Pair<MethodID, Object>>();
+        // Use MethodID for Integer values.
+        private final Queue<Pair<Integer, Object>> mExpectedCalls =
+                new ConcurrentLinkedQueue<Pair<Integer, Object>>();
 
         public MockDownloadNotifier() {
             expect(MethodID.CLEAR_PENDING_DOWNLOADS, null);
@@ -85,7 +93,7 @@
             this();
         }
 
-        public MockDownloadNotifier expect(MethodID method, Object param) {
+        public MockDownloadNotifier expect(@MethodID int method, Object param) {
             mExpectedCalls.clear();
             mExpectedCalls.add(getMethodSignature(method, param));
             return this;
@@ -101,21 +109,21 @@
                     });
         }
 
-        public MockDownloadNotifier andThen(MethodID method, Object param) {
+        public MockDownloadNotifier andThen(@MethodID int method, Object param) {
             mExpectedCalls.add(getMethodSignature(method, param));
             return this;
         }
 
-        static Pair<MethodID, Object> getMethodSignature(MethodID methodId, Object param) {
-            return new Pair<MethodID, Object>(methodId, param);
+        static Pair<Integer, Object> getMethodSignature(@MethodID int methodId, Object param) {
+            return new Pair<Integer, Object>(methodId, param);
         }
 
-        void assertCorrectExpectedCall(MethodID methodId, Object param, boolean matchParams) {
+        void assertCorrectExpectedCall(@MethodID int methodId, Object param, boolean matchParams) {
             Log.w("MockDownloadNotifier", "Called: " + methodId);
             Assert.assertFalse("Unexpected call:, no call expected, but got: " + methodId,
                     mExpectedCalls.isEmpty());
-            Pair<MethodID, Object> actual = getMethodSignature(methodId, param);
-            Pair<MethodID, Object> expected = mExpectedCalls.poll();
+            Pair<Integer, Object> actual = getMethodSignature(methodId, param);
+            Pair<Integer, Object> expected = mExpectedCalls.poll();
             Assert.assertEquals("Unexpected call", expected.first, actual.first);
             if (matchParams) {
                 Assert.assertTrue(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java
new file mode 100644
index 0000000..feb2dc6
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java
@@ -0,0 +1,111 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feed;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.test.ChromeBrowserTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.browser.Features;
+
+/** Tests for {@link FeedConfiguration}. */
+@SmallTest
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class FeedConfigurationTest {
+    @Rule
+    public final ChromeBrowserTestRule mRule = new ChromeBrowserTestRule();
+
+    @Test
+    @Feature({"Feed"})
+    @Features.EnableFeatures({ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS})
+    public void testDefaultFeedConfigurationValues() {
+        Assert.assertEquals(FeedConfiguration.FEED_SERVER_ENDPOINT_DEFAULT,
+                FeedConfiguration.getFeedServerEndpoint());
+        Assert.assertEquals(FeedConfiguration.FEED_SERVER_METHOD_DEFAULT,
+                FeedConfiguration.getFeedServerMethod());
+        Assert.assertEquals(FeedConfiguration.FEED_SERVER_RESPONSE_LENGTH_PREFIXED_DEFAULT,
+                FeedConfiguration.getFeedServerReponseLengthPrefixed());
+        Assert.assertEquals(FeedConfiguration.LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS_DEFAULT,
+                FeedConfiguration.getLoggingImmediateContentThresholdMs());
+        Assert.assertEquals(FeedConfiguration.SESSION_LIFETIME_MS_DEFAULT,
+                FeedConfiguration.getSessionLifetimeMs());
+        Assert.assertFalse(FeedConfiguration.getTriggerImmedatePagination());
+        Assert.assertEquals(FeedConfiguration.VIEW_LOG_THRESHOLD_DEFAULT,
+                FeedConfiguration.getViewLogThreshold(), 0.001d);
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:feed_server_endpoint/"
+                    + "https%3A%2F%2Ffeed%2Egoogle%2Ecom%2Fpath"})
+    public void testFeedServerEndpointParameter() {
+        Assert.assertEquals(
+                "https://feed.google.com/path", FeedConfiguration.getFeedServerEndpoint());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:feed_server_method/POST"})
+    public void testFeedServerMethodParameter() {
+        Assert.assertEquals("POST", FeedConfiguration.getFeedServerMethod());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:feed_server_response_length_prefixed/false"})
+    public void testFeedServerResponseLengthPrefixedParameter() {
+        Assert.assertEquals(false, FeedConfiguration.getFeedServerReponseLengthPrefixed());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:logging_immediate_content_threshold_ms/5000"})
+    public void testLoggingImmediateContentThresholdMs() {
+        Assert.assertEquals(5000, FeedConfiguration.getLoggingImmediateContentThresholdMs());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:session_lifetime_ms/60000"})
+    public void testSessionLifetimeMs() {
+        Assert.assertEquals(60000, FeedConfiguration.getSessionLifetimeMs());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:trigger_immediate_pagination/true"})
+    public void testTriggerImmedatePagination() {
+        Assert.assertTrue(FeedConfiguration.getTriggerImmedatePagination());
+    }
+
+    @Test
+    @Feature({"Feed"})
+    @CommandLineFlags.
+    Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group",
+            "force-fieldtrial-params=Trial.Group:view_log_threshold/0.33"})
+    public void testViewLogThreshold() {
+        Assert.assertEquals(0.33d, FeedConfiguration.getViewLogThreshold(), 0.001d);
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
index 388a4272..c5949dd6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -353,8 +353,7 @@
     @Test
     @LargeTest
     @Feature({"Fullscreen"})
-    @Features.DisableFeatures(
-            {ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_BUTTON, ChromeFeatureList.OFFLINE_INDICATOR})
+    @Features.DisableFeatures({ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_BUTTON})
     public void testHidingBrowserControlsRemovesSurfaceFlingerOverlay()
             throws InterruptedException {
         FullscreenManagerTestUtils.disableBrowserOverrides();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
index d33cded..0c97bcaa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.test.util.ActivityUtils;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.MenuUtils;
+import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.offlinepages.SavePageResult;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -47,11 +48,7 @@
 
 /** Unit tests for offline indicator interacting with chrome activity. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        "enable-features=" + ChromeFeatureList.OFFLINE_INDICATOR + "<FakeStudy",
-        "force-fieldtrials=FakeStudy/FakeGroup",
-        "force-fieldtrial-params=FakeStudy.FakeGroup:"
-                + OfflineIndicatorController.PARAM_STABLE_OFFLINE_WAIT_SECONDS + "/1"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 // TODO(jianli): Add test for disabled feature.
 public class OfflineIndicatorControllerTest {
     @Rule
@@ -67,6 +64,10 @@
 
     @Before
     public void setUp() throws Exception {
+        // ChromeActivityTestRule disables offline indicator feature. We want to enable it to do
+        // our own testing.
+        Features.getInstance().enable(ChromeFeatureList.OFFLINE_INDICATOR);
+        OfflineIndicatorController.setTimeToWaitForStableOfflineForTesting(1);
         ConnectivityDetector.skipSystemCheckForTesting();
         ConnectivityDetector.skipHttpProbeForTesting();
         mActivityTestRule.startMainActivityOnBlankPage();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaBaseTest.java
index bfcd2778..b6d445ff1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaBaseTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/OmahaBaseTest.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.support.annotation.IntDef;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -28,6 +29,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.SocketTimeoutException;
@@ -72,7 +75,8 @@
         private TimestampPair mTimestampsOnRegisterNewRequest;
         private TimestampPair mTimestampsOnSaveState;
 
-        MockOmahaDelegate(Context context, DeviceType deviceType, InstallSource installSource) {
+        MockOmahaDelegate(
+                Context context, DeviceType deviceType, @InstallSource int installSource) {
             mContext = context;
             mIsOnTablet = deviceType == DeviceType.TABLET;
             mIsInForeground = true;
@@ -143,11 +147,40 @@
         }
     }
 
-    private enum InstallSource { SYSTEM_IMAGE, ORGANIC }
-    private enum ServerResponse { SUCCESS, FAILURE }
-    private enum ConnectionStatus { RESPONDS, TIMES_OUT }
-    private enum InstallEvent { SEND, DONT_SEND }
-    private enum PostStatus { DUE, NOT_DUE }
+    @IntDef({InstallSource.SYSTEM_IMAGE, InstallSource.ORGANIC})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface InstallSource {
+        int SYSTEM_IMAGE = 0;
+        int ORGANIC = 1;
+    }
+
+    @IntDef({ServerResponse.SUCCESS, ServerResponse.FAILURE})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ServerResponse {
+        int SUCCESS = 0;
+        int FAILURE = 1;
+    }
+
+    @IntDef({ConnectionStatus.RESPONDS, ConnectionStatus.TIMES_OUT})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ConnectionStatus {
+        int RESPONDS = 0;
+        int TIMES_OUT = 1;
+    }
+
+    @IntDef({InstallEvent.SEND, InstallEvent.DONT_SEND})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface InstallEvent {
+        int SEND = 0;
+        int DONT_SEND = 1;
+    }
+
+    @IntDef({PostStatus.DUE, PostStatus.NOT_DUE})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface PostStatus {
+        int DUE = 0;
+        int NOT_DUE = 1;
+    }
 
     private AdvancedMockContext mContext;
     private MockOmahaDelegate mDelegate;
@@ -159,7 +192,7 @@
     }
 
     private MockOmahaBase createOmahaBase(
-            ServerResponse response, ConnectionStatus status, DeviceType deviceType) {
+            @ServerResponse int response, @ConnectionStatus int status, DeviceType deviceType) {
         MockOmahaBase omahaClient = new MockOmahaBase(mDelegate, response, status, deviceType);
         return omahaClient;
     }
@@ -183,8 +216,8 @@
         private final boolean mConnectionTimesOut;
         private final boolean mIsOnTablet;
 
-        public MockOmahaBase(OmahaDelegate delegate, ServerResponse serverResponse,
-                ConnectionStatus connectionStatus, DeviceType deviceType) {
+        public MockOmahaBase(OmahaDelegate delegate, @ServerResponse int serverResponse,
+                @ConnectionStatus int connectionStatus, DeviceType deviceType) {
             super(delegate);
             mSendValidResponse = serverResponse == ServerResponse.SUCCESS;
             mConnectionTimesOut = connectionStatus == ConnectionStatus.TIMES_OUT;
@@ -588,9 +621,9 @@
             mConnectionTimesOut = connectionTimesOut;
 
             if (sendValidResponse) {
-                mHTTPResponseCode = 200;
+                mHTTPResponseCode = HttpURLConnection.HTTP_OK; // 200
             } else {
-                mHTTPResponseCode = 404;
+                mHTTPResponseCode = HttpURLConnection.HTTP_NOT_FOUND; // 404
             }
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
index 2769674..93cb8004 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
@@ -667,6 +667,39 @@
         doTestUsbGuardPermission(false);
     }
 
+    /**
+     * Helper function to test allowing and blocking automatic downloads.
+     * @param enabled true to test enabling automatic downloads, false to test disabling the
+     * feature.
+     */
+    private void doTestAutomaticDownloadsPermission(final boolean enabled) {
+        setGlobalToggleForCategory(SiteSettingsCategory.Type.AUTOMATIC_DOWNLOADS, enabled);
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                Assert.assertEquals(
+                        "Automatic Downloads should be " + (enabled ? "enabled" : "disabled"),
+                        PrefServiceBridge.getInstance().isCategoryEnabled(
+                                ContentSettingsType.CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS),
+                        enabled);
+            }
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    public void testAllowAutomaticDownloads() {
+        doTestAutomaticDownloadsPermission(true);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    public void testBlockAutomaticDownloads() {
+        doTestAutomaticDownloadsPermission(false);
+    }
+
     private int getTabCount() {
         return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer>() {
             @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsSheetVisibilityChangeObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsSheetVisibilityChangeObserverTest.java
index 616e646..892ee33 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsSheetVisibilityChangeObserverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/SuggestionsSheetVisibilityChangeObserverTest.java
@@ -7,10 +7,8 @@
 import static org.junit.Assert.assertEquals;
 
 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
-import static org.chromium.chrome.browser.suggestions.SuggestionsSheetVisibilityChangeObserverTest.TestVisibilityChangeObserver.Event.Hidden;
-import static org.chromium.chrome.browser.suggestions.SuggestionsSheetVisibilityChangeObserverTest.TestVisibilityChangeObserver.Event.InitialReveal;
-import static org.chromium.chrome.browser.suggestions.SuggestionsSheetVisibilityChangeObserverTest.TestVisibilityChangeObserver.Event.StateChange;
 
+import android.support.annotation.IntDef;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.Espresso;
 import android.support.test.espresso.action.ViewActions;
@@ -29,6 +27,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ntp.NtpUiCaptureTestData;
+import org.chromium.chrome.browser.suggestions.SuggestionsSheetVisibilityChangeObserverTest.TestVisibilityChangeObserver.Event;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.test.BottomSheetTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -36,6 +35,8 @@
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
 import org.chromium.ui.test.util.UiRestriction;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -75,16 +76,16 @@
     public void testHomeSheetVisibilityOnWebPage() {
         // Pull sheet to half. We use the animated variants to be closer to user triggered events.
         mActivityRule.setSheetState(BottomSheet.SheetState.HALF, true);
-        mObserver.expectEvents(InitialReveal, StateChange);
+        mObserver.expectEvents(Event.INITIAL_REVEAL, Event.STATE_CHANGE);
         mEventReporter.surfaceOpenedHelper.waitForCallback();
 
         // Pull sheet to full.
         mActivityRule.setSheetState(BottomSheet.SheetState.FULL, true);
-        mObserver.expectEvents(StateChange);
+        mObserver.expectEvents(Event.STATE_CHANGE);
 
         // close
         Espresso.pressBack();
-        mObserver.expectEvents(Hidden, StateChange, StateChange);
+        mObserver.expectEvents(Event.HIDDEN, Event.STATE_CHANGE, Event.STATE_CHANGE);
     }
 
     @Test
@@ -119,19 +120,26 @@
 
         // Changing the state of the sheet closes the omnibox suggestions and shows the home sheet.
         mActivityRule.setSheetState(BottomSheet.SheetState.HALF, true);
-        mObserver.expectEvents(InitialReveal, StateChange);
+        mObserver.expectEvents(Event.INITIAL_REVEAL, Event.STATE_CHANGE);
         mEventReporter.surfaceOpenedHelper.waitForCallback();
 
         // Back closes the bottom sheet.
         Espresso.pressBack();
-        mObserver.expectEvents(Hidden, StateChange, StateChange);
+        mObserver.expectEvents(Event.HIDDEN, Event.STATE_CHANGE, Event.STATE_CHANGE);
         assertEquals(BottomSheet.SheetState.PEEK, mActivityRule.getBottomSheet().getSheetState());
 
         mEventReporter.surfaceOpenedHelper.verifyCallCount();
     }
 
     static class TestVisibilityChangeObserver extends SuggestionsSheetVisibilityChangeObserver {
-        public enum Event { InitialReveal, Shown, Hidden, StateChange }
+        @IntDef({Event.INITIAL_REVEAL, Event.SHOWN, Event.HIDDEN, Event.STATE_CHANGE})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Event {
+            int INITIAL_REVEAL = 0;
+            int SHOWN = 1;
+            int HIDDEN = 2;
+            int STATE_CHANGE = 3;
+        }
 
         private final ChromeActivity mActivity;
 
@@ -167,19 +175,19 @@
             mStateChangedHelper.notifyCalled();
         }
 
-        public void expectEvents(Event... events) {
-            for (Event e : events) {
+        public void expectEvents(@Event int... events) {
+            for (@Event int e : events) {
                 switch (e) {
-                    case InitialReveal:
+                    case Event.INITIAL_REVEAL:
                         mInitialRevealHelper.waitForCallback();
                         break;
-                    case Shown:
+                    case Event.SHOWN:
                         mShownHelper.waitForCallback();
                         break;
-                    case Hidden:
+                    case Event.HIDDEN:
                         mHiddenHelper.waitForCallback();
                         break;
-                    case StateChange:
+                    case Event.STATE_CHANGE:
                         mStateChangedHelper.waitForCallback();
                         break;
                 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
index 141757f..ad619f8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
@@ -6,11 +6,14 @@
 
 import android.content.Context;
 import android.os.SystemClock;
+import android.support.annotation.IntDef;
 
 import com.google.vr.testframework.controller.ControllerTestApi;
 
 import org.junit.Assert;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -23,7 +26,15 @@
  *   - PairedControllerAddress: "FOO"
  */
 public class EmulatedVrController {
-    public enum ScrollDirection { UP, DOWN, LEFT, RIGHT }
+    @IntDef({ScrollDirection.UP, ScrollDirection.DOWN, ScrollDirection.LEFT, ScrollDirection.RIGHT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScrollDirection {
+        int UP = 0;
+        int DOWN = 1;
+        int LEFT = 2;
+        int RIGHT = 3;
+    }
+
     private static final int FIRST_INPUT_DELAY_MS = 1000;
     private final ControllerTestApi mApi;
     private boolean mHaveSentInputSinceEnteringVr;
@@ -121,23 +132,23 @@
      * @param speed how long to wait between steps in the scroll, with higher
      *        numbers resulting in a faster scroll.
      */
-    public void scroll(ScrollDirection direction, int steps, int speed) {
+    public void scroll(@ScrollDirection int direction, int steps, int speed) {
         float startX, startY, endX, endY;
         startX = startY = endX = endY = 0.5f;
         switch (direction) {
-            case UP:
+            case ScrollDirection.UP:
                 startY = 0.1f;
                 endY = 0.9f;
                 break;
-            case DOWN:
+            case ScrollDirection.DOWN:
                 startY = 0.9f;
                 endY = 0.1f;
                 break;
-            case LEFT:
+            case ScrollDirection.LEFT:
                 startX = 0.1f;
                 endX = 0.9f;
                 break;
-            case RIGHT:
+            case ScrollDirection.RIGHT:
                 startX = 0.9f;
                 endX = 0.1f;
                 break;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
index c8e4fee8..9302b9e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
@@ -95,9 +95,9 @@
     }
 
     public void registerUiOperationCallbackForTesting(
-            int actionType, Runnable resultCallback, int quiescenceTimeoutMs) {
+            int actionType, Runnable resultCallback, int timeoutMs, int elementName) {
         getVrShell().registerUiOperationCallbackForTesting(
-                actionType, resultCallback, quiescenceTimeoutMs);
+                actionType, resultCallback, timeoutMs, elementName);
     }
 
     public void saveNextFrameBufferToDiskForTesting(String filepathBase) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
index 71e8a625..285b6ca 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
@@ -12,6 +12,7 @@
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE;
 
 import android.graphics.PointF;
+import android.support.annotation.IntDef;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 
@@ -44,6 +45,8 @@
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.DOMUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.concurrent.TimeoutException;
 
@@ -73,9 +76,28 @@
     private static final String TEST_PAGE_WEBXR_URL =
             WebXrVrTestFramework.getFileUrlForHtmlTestFile("test_navigation_webxr_page");
 
-    private enum Page { PAGE_2D, PAGE_2D_2, PAGE_WEBVR, PAGE_WEBXR }
-    private enum PresentationMode { NON_PRESENTING, PRESENTING }
-    private enum FullscreenMode { NON_FULLSCREENED, FULLSCREENED }
+    @IntDef({Page.PAGE_2D, Page.PAGE_2D_2, Page.PAGE_WEBVR, Page.PAGE_WEBXR})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Page {
+        int PAGE_2D = 0;
+        int PAGE_2D_2 = 1;
+        int PAGE_WEBVR = 2;
+        int PAGE_WEBXR = 3;
+    }
+
+    @IntDef({PresentationMode.NON_PRESENTING, PresentationMode.PRESENTING})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface PresentationMode {
+        int NON_PRESENTING = 0;
+        int PRESENTING = 1;
+    }
+
+    @IntDef({FullscreenMode.NON_FULLSCREENED, FullscreenMode.FULLSCREENED})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface FullscreenMode {
+        int NON_FULLSCREENED = 0;
+        int FULLSCREENED = 1;
+    }
 
     @Before
     public void setUp() throws Exception {
@@ -85,15 +107,15 @@
         VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
     }
 
-    private String getUrl(Page page) {
+    private String getUrl(@Page int page) {
         switch (page) {
-            case PAGE_2D:
+            case Page.PAGE_2D:
                 return TEST_PAGE_2D_URL;
-            case PAGE_2D_2:
+            case Page.PAGE_2D_2:
                 return TEST_PAGE_2D_2_URL;
-            case PAGE_WEBVR:
+            case Page.PAGE_WEBVR:
                 return TEST_PAGE_WEBVR_URL;
-            case PAGE_WEBXR:
+            case Page.PAGE_WEBXR:
                 return TEST_PAGE_WEBXR_URL;
             default:
                 throw new UnsupportedOperationException("Don't know page type " + page);
@@ -105,7 +127,7 @@
      * {@link ChromeActivityTestRule#loadUrl loadUrl} but makes sure page initiates the
      * navigation. This is desirable since we are testing navigation transitions end-to-end.
      */
-    private void navigateTo(final Page to) throws InterruptedException {
+    private void navigateTo(final @Page int to) throws InterruptedException {
         ChromeTabUtils.waitForTabPageLoaded(mTestRule.getActivity().getActivityTab(), () -> {
             mVrBrowserTestFramework.runJavaScriptOrFail(
                     "window.location.href = '" + getUrl(to) + "';", POLL_TIMEOUT_SHORT_MS);
@@ -119,8 +141,8 @@
         Assert.assertTrue("Failed to enter fullscreen", DOMUtils.isFullscreen(webContents));
     }
 
-    private void assertState(WebContents wc, Page page, PresentationMode presentationMode,
-            FullscreenMode fullscreenMode) throws InterruptedException, TimeoutException {
+    private void assertState(WebContents wc, @Page int page, @PresentationMode int presentationMode,
+            @FullscreenMode int fullscreenMode) throws InterruptedException, TimeoutException {
         Assert.assertTrue("Browser is not in VR", VrShellDelegate.isInVr());
         Assert.assertEquals("Browser is not on correct web site", getUrl(page), wc.getVisibleUrl());
         Assert.assertEquals("Browser's presentation mode does not match expectation",
@@ -193,7 +215,7 @@
         impl2dToWeb(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void impl2dToWeb(Page page, WebXrVrTestFramework framework)
+    private void impl2dToWeb(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
 
@@ -226,7 +248,7 @@
         impl2dFullscreenToWeb(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void impl2dFullscreenToWeb(Page page, WebXrVrTestFramework framework)
+    private void impl2dFullscreenToWeb(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
         enterFullscreenOrFail(framework.getFirstTabWebContents());
@@ -260,7 +282,7 @@
         webTo2dImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webTo2dImpl(Page page, WebXrVrTestFramework framework)
+    private void webTo2dImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
 
@@ -293,7 +315,7 @@
         webToWebImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webToWebImpl(Page page, WebXrVrTestFramework framework)
+    private void webToWebImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
 
@@ -326,7 +348,7 @@
         webPresentingTo2dImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webPresentingTo2dImpl(Page page, WebXrVrTestFramework framework)
+    private void webPresentingTo2dImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
         framework.enterSessionWithUserGestureOrFail();
@@ -360,7 +382,7 @@
         webPresentingToWebImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webPresentingToWebImpl(Page page, WebXrVrTestFramework framework)
+    private void webPresentingToWebImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
         framework.enterSessionWithUserGestureOrFail();
@@ -394,7 +416,7 @@
         webFullscreenTo2dImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webFullscreenTo2dImpl(Page page, WebXrVrTestFramework framework)
+    private void webFullscreenTo2dImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
         enterFullscreenOrFail(framework.getFirstTabWebContents());
@@ -428,7 +450,7 @@
         webFullscreenToWebImpl(Page.PAGE_WEBXR, mWebXrVrTestFramework);
     }
 
-    private void webFullscreenToWebImpl(Page page, WebXrVrTestFramework framework)
+    private void webFullscreenToWebImpl(@Page int page, WebXrVrTestFramework framework)
             throws InterruptedException, TimeoutException {
         framework.loadUrlAndAwaitInitialization(getUrl(page), PAGE_LOAD_TIMEOUT_S);
         enterFullscreenOrFail(framework.getFirstTabWebContents());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
index e1539b1..3cd7df9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
@@ -4,8 +4,12 @@
 
 package org.chromium.chrome.browser.vr;
 
+import static org.chromium.chrome.browser.vr.XrTestFramework.PAGE_LOAD_TIMEOUT_S;
+import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_LONG_MS;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_SVR;
+import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
 
+import android.graphics.PointF;
 import android.os.Build;
 import android.support.test.filters.MediumTest;
 import android.view.View;
@@ -26,7 +30,10 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.vr.keyboard.GvrKeyboardLoaderClient;
 import org.chromium.chrome.browser.vr.rules.XrActivityRestriction;
+import org.chromium.chrome.browser.vr.util.NativeUiUtils;
+import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils;
 import org.chromium.chrome.browser.vr.util.VrInfoBarUtils;
 import org.chromium.chrome.browser.vr.util.VrShellDelegateUtils;
 import org.chromium.chrome.browser.vr.util.VrTestRuleUtils;
@@ -39,7 +46,7 @@
 /**
  * End-to-end tests for the InfoBar that prompts the user to update or install
  * VrCore (VR Services) when attempting to use a VR feature with an outdated
- * or entirely missing version.
+ * or entirely missing version or other VR-related update prompts.
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@@ -143,4 +150,49 @@
     public void testInfoBarNotPresentWhenVrServicesNotSupported() throws InterruptedException {
         infoBarTestHelper(VrCoreCompatibility.VR_NOT_SUPPORTED);
     }
+
+    /**
+     * Tests that the install/upgrade prompt for the keyboard appears when clicking on the URL
+     * bar without the keyboard installed.
+     */
+    @Test
+    @MediumTest
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
+    public void testKeyboardInstallUpgradePromptUrlBar() throws InterruptedException {
+        testKeyboardInstallUpgradeImpl(UserFriendlyElementName.URL);
+    }
+
+    /**
+     * Tests that the install/upgrade prompt for the keyboard appears when interacting with a web
+     * text input field without the keyboard installed.
+     */
+    @Test
+    @MediumTest
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
+    public void testKeyboardInstallUpgradePromptWebInput() throws InterruptedException {
+        testKeyboardInstallUpgradeImpl(UserFriendlyElementName.CONTENT_QUAD);
+    }
+
+    private void testKeyboardInstallUpgradeImpl(final int uiElementToClick)
+            throws InterruptedException {
+        mVrTestRule.loadUrl(
+                VrBrowserTestFramework.getFileUrlForHtmlTestFile("test_web_input_editing"),
+                PAGE_LOAD_TIMEOUT_S);
+        GvrKeyboardLoaderClient.setFailLoadForTesting(true);
+        VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
+        // The prompt takes significantly longer to show when clicking on the web content, so we
+        // can't just wait for quiescence since that gets reached before the prompt shows (not sure
+        // what's causing a UI change other than the prompt). Instead, explicitly wait for the
+        // prompt to become visible before waiting for quiescence.
+        NativeUiUtils.performActionAndWaitForUiQuiescence(() -> {
+            try {
+                NativeUiUtils.performActionAndWaitForVisibilityChange(
+                        UserFriendlyElementName.EXIT_PROMPT,
+                        () -> { NativeUiUtils.clickElement(uiElementToClick, new PointF()); });
+            } catch (InterruptedException e) {
+                Assert.fail("Interrupted while waiting for UI visibility change");
+            }
+
+        });
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityVrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityVrTestRule.java
index d16f2936..0b184244 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityVrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityVrTestRule.java
@@ -39,7 +39,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.CTA;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java
index d90cbcc..742be80 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java
@@ -28,7 +28,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.CTA;
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityVrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityVrTestRule.java
index e9f3d5a..8c3e4f3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityVrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityVrTestRule.java
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.CCT;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java
index 690c725..493d448 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java
@@ -31,7 +31,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.CCT;
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/HeadTrackingMode.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/HeadTrackingMode.java
index 060c8f7..8fc90b4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/HeadTrackingMode.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/HeadTrackingMode.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.vr.rules;
 
+import android.support.annotation.IntDef;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -30,16 +32,19 @@
 @Target({ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface HeadTrackingMode {
-    public enum SupportedMode {
-        FROZEN, // Locked looking straight forward.
-        SWEEP, // Rotates back and forth horizontally in a 180 degree arc.
-        ROTATE, // Rotates 360 degrees.
-        CIRCLE_STRAFE, // Rotates 360 degrees, and if 6DOF is supported, changes position.
-        MOTION_SICKNESS // Moves in a figure-eight-like pattern.
+    @IntDef({SupportedMode.FROZEN, SupportedMode.SWEEP, SupportedMode.ROTATE,
+            SupportedMode.CIRCLE_STRAFE, SupportedMode.MOTION_SICKNESS})
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface SupportedMode {
+        int FROZEN = 0; // Locked looking straight forward.
+        int SWEEP = 1; // Rotates back and forth horizontally in a 180 degree arc.
+        int ROTATE = 2; // Rotates 360 degrees.
+        int CIRCLE_STRAFE = 3; // Rotates 360 degrees, and if 6DOF is supported, changes position.
+        int MOTION_SICKNESS = 4; // Moves in a figure-eight-like pattern.
     }
 
     /**
      * @return The supported mode.
      */
-    public SupportedMode value();
+    public @SupportedMode int value();
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrActivityRestrictionRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrActivityRestrictionRule.java
index 1e50127..c8ad520 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrActivityRestrictionRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/VrActivityRestrictionRule.java
@@ -18,9 +18,9 @@
  * one of the supported Activity types for the test.
  */
 public class VrActivityRestrictionRule implements TestRule {
-    private SupportedActivity mCurrentRestriction;
+    private @SupportedActivity int mCurrentRestriction;
 
-    public VrActivityRestrictionRule(SupportedActivity currentRestriction) {
+    public VrActivityRestrictionRule(@SupportedActivity int currentRestriction) {
         mCurrentRestriction = currentRestriction;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityVrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityVrTestRule.java
index aca50b6..c588891 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityVrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityVrTestRule.java
@@ -37,7 +37,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.WAA;
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java
index 57193f4..76078ff 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java
@@ -29,7 +29,7 @@
     }
 
     @Override
-    public SupportedActivity getRestriction() {
+    public @SupportedActivity int getRestriction() {
         return SupportedActivity.WAA;
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestriction.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestriction.java
index e3a16063..93bf892 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestriction.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestriction.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.vr.rules;
 
+import android.support.annotation.IntDef;
+
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -25,15 +27,18 @@
 @Target({ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface XrActivityRestriction {
-    public enum SupportedActivity {
-        CTA, // ChromeTabbedActivity/Normal Chrome
-        CCT, // CustomTabActivity/Chrome Custom Tab
-        WAA, // WebappActivity/Progressive Web App
-        ALL // Run in all of the above
+    @IntDef({SupportedActivity.CTA, SupportedActivity.CCT, SupportedActivity.WAA,
+            SupportedActivity.ALL})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SupportedActivity {
+        int CTA = 0; // ChromeTabbedActivity/Normal Chrome
+        int CCT = 1; // CustomTabActivity/Chrome Custom Tab
+        int WAA = 2; // WebappActivity/Progressive Web App
+        int ALL = 3; // Run in all of the above
     }
 
     /**
      * @return A list of activity restrictions.
      */
-    public SupportedActivity[] value();
+    public @SupportedActivity int[] value();
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestrictionRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestrictionRule.java
index e304bb8..1177262a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestrictionRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrActivityRestrictionRule.java
@@ -17,9 +17,9 @@
  * one of the supported Activity types for the test.
  */
 public class XrActivityRestrictionRule implements TestRule {
-    private SupportedActivity mCurrentRestriction;
+    private @SupportedActivity int mCurrentRestriction;
 
-    public XrActivityRestrictionRule(SupportedActivity currentRestriction) {
+    public XrActivityRestrictionRule(@SupportedActivity int currentRestriction) {
         mCurrentRestriction = currentRestriction;
     }
 
@@ -35,7 +35,8 @@
             return generateIgnoreStatement();
         }
 
-        SupportedActivity[] activities = annotation.value();
+        @SupportedActivity
+        int[] activities = annotation.value();
         for (int i = 0; i < activities.length; i++) {
             if (activities[i] == mCurrentRestriction || activities[i] == SupportedActivity.ALL) {
                 return base;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
index 35809e0f..87b373b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/XrTestRule.java
@@ -15,5 +15,5 @@
      * @return The XrActivityRestriction.SupportedActivity that this rule is restricted to running
      *         in.
      */
-    public SupportedActivity getRestriction();
+    public @SupportedActivity int getRestriction();
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
index ea8443e..db025650 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/HeadTrackingUtils.java
@@ -152,7 +152,7 @@
      * @param rule The VrTestRule used by the current test case.
      * @param mode The HeadTrackingMode.SupportedMode value to set the fake head tracker mode to.
      */
-    public static void applyHeadTrackingMode(VrTestRule rule, SupportedMode mode) {
+    public static void applyHeadTrackingMode(VrTestRule rule, @SupportedMode int mode) {
         applyHeadTrackingModeInternal(rule, mode);
         // TODO(bsheedy): Remove this sleep if the head tracking service ever exposes a way to be
         // notified when a setting has been applied.
@@ -198,24 +198,24 @@
         InstrumentationRegistry.getContext().startService(typeIntent);
     }
 
-    public static String supportedModeToString(SupportedMode mode) {
+    public static String supportedModeToString(@SupportedMode int mode) {
         switch (mode) {
-            case FROZEN:
+            case SupportedMode.FROZEN:
                 return "frozen";
-            case SWEEP:
+            case SupportedMode.SWEEP:
                 return "sweep";
-            case ROTATE:
+            case SupportedMode.ROTATE:
                 return "rotate";
-            case CIRCLE_STRAFE:
+            case SupportedMode.CIRCLE_STRAFE:
                 return "circle_strafe";
-            case MOTION_SICKNESS:
+            case SupportedMode.MOTION_SICKNESS:
                 return "motion_sickness";
             default:
                 return "unknown_mode";
         }
     }
 
-    private static void applyHeadTrackingModeInternal(VrTestRule rule, SupportedMode mode) {
+    private static void applyHeadTrackingModeInternal(VrTestRule rule, @SupportedMode int mode) {
         restartHeadTrackingServiceIfNecessary(rule);
         // Set the fake tracker mode to the given value.
         Intent modeIntent = new Intent(ACTION_SET_FAKE_TRACKER_MODE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
index a882d22..fbeead5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
@@ -15,12 +15,12 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.vr.TestVrShellDelegate;
+import org.chromium.chrome.browser.vr.UiTestOperationResult;
 import org.chromium.chrome.browser.vr.UiTestOperationType;
 import org.chromium.chrome.browser.vr.UserFriendlyElementName;
 import org.chromium.chrome.browser.vr.VrControllerTestAction;
 import org.chromium.chrome.browser.vr.VrDialog;
 import org.chromium.chrome.browser.vr.VrShell;
-import org.chromium.chrome.browser.vr.VrUiTestActivityResult;
 import org.chromium.chrome.browser.vr.VrViewContainer;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 
@@ -139,8 +139,10 @@
         // Run on the UI thread to prevent issues with registering a new callback before
         // ReportUiOperationResultForTesting has finished.
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            instance.registerUiOperationCallbackForTesting(UiTestOperationType.UI_ACTIVITY_RESULT,
-                    () -> { resultLatch.countDown(); }, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS);
+            instance.registerUiOperationCallbackForTesting(
+                    UiTestOperationType.UI_ACTIVITY_RESULT, () -> {
+                        resultLatch.countDown();
+                    }, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, 0 /* unused */);
         });
         action.run();
 
@@ -149,8 +151,37 @@
         int uiResult =
                 instance.getLastUiOperationResultForTesting(UiTestOperationType.UI_ACTIVITY_RESULT);
         Assert.assertEquals("UI reported non-quiescent result '"
-                        + vrUiTestActivityResultToString(uiResult) + "'",
-                VrUiTestActivityResult.QUIESCENT, uiResult);
+                        + uiTestOperationResultToString(uiResult) + "'",
+                UiTestOperationResult.QUIESCENT, uiResult);
+    }
+
+    /**
+     * Runs the given Runnable and waits until the specified element changes its visibility.
+     *
+     * @param elementName The UserFriendlyElementName to wait on to change visibility.
+     * @param action A Runnable containing the action to perform.
+     */
+    public static void performActionAndWaitForVisibilityChange(
+            final int elementName, Runnable action) throws InterruptedException {
+        final TestVrShellDelegate instance = TestVrShellDelegate.getInstance();
+        final CountDownLatch resultLatch = new CountDownLatch(1);
+        // Run on the UI thread to prevent issues with registering a new callback before
+        // ReportUiOperationResultForTesting has finished.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            instance.registerUiOperationCallbackForTesting(
+                    UiTestOperationType.ELEMENT_VISIBILITY_CHANGE, () -> {
+                        resultLatch.countDown();
+                    }, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, elementName);
+        });
+        action.run();
+
+        // Wait for the result to be reported.
+        resultLatch.await();
+        int result = instance.getLastUiOperationResultForTesting(
+                UiTestOperationType.ELEMENT_VISIBILITY_CHANGE);
+        Assert.assertEquals("UI reported non-visibility-changed result '"
+                        + uiTestOperationResultToString(result) + "'",
+                UiTestOperationResult.VISIBILITY_CHANGE, result);
     }
 
     /**
@@ -197,7 +228,7 @@
         // ReportUiOperationResultForTesting has finished.
         ThreadUtils.runOnUiThreadBlocking(() -> {
             instance.registerUiOperationCallbackForTesting(UiTestOperationType.FRAME_BUFFER_DUMPED,
-                    () -> { resultLatch.countDown(); }, 0 /* unused */);
+                    () -> { resultLatch.countDown(); }, 0 /* unused */, 0 /* unused */);
         });
         instance.saveNextFrameBufferToDiskForTesting(filepathBase);
         resultLatch.await();
@@ -244,16 +275,20 @@
         clickElementAndWaitForUiQuiescence(UserFriendlyElementName.BROWSING_DIALOG, buttonCenter);
     }
 
-    private static String vrUiTestActivityResultToString(int result) {
+    private static String uiTestOperationResultToString(int result) {
         switch (result) {
-            case VrUiTestActivityResult.UNREPORTED:
+            case UiTestOperationResult.UNREPORTED:
                 return "Unreported";
-            case VrUiTestActivityResult.QUIESCENT:
+            case UiTestOperationResult.QUIESCENT:
                 return "Quiescent";
-            case VrUiTestActivityResult.TIMEOUT_NO_START:
+            case UiTestOperationResult.TIMEOUT_NO_START:
                 return "Timeout (UI activity not started)";
-            case VrUiTestActivityResult.TIMEOUT_NO_END:
+            case UiTestOperationResult.TIMEOUT_NO_END:
                 return "Timeout (UI activity not stopped)";
+            case UiTestOperationResult.VISIBILITY_CHANGE:
+                return "Visibility change";
+            case UiTestOperationResult.TIMEOUT_NO_CHANGE:
+                return "Timeout (Element visibility did not change)";
             default:
                 return "Unknown result";
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
index 977c9760..cb04109 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrInfoBarUtils.java
@@ -7,12 +7,16 @@
 import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_CHECK_INTERVAL_SHORT_MS;
 import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_SHORT_MS;
 
+import android.support.annotation.IntDef;
+
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.infobar.InfoBar;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.util.InfoBarUtil;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /**
@@ -20,8 +24,12 @@
  * a high level.
  */
 public class VrInfoBarUtils {
-    public enum Button { PRIMARY, SECONDARY }
-    ;
+    @IntDef({Button.PRIMARY, Button.SECONDARY})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Button {
+        int PRIMARY = 0;
+        int SECONDARY = 1;
+    }
 
     /**
      * Determines whether InfoBars are present in the current activity.
@@ -43,12 +51,12 @@
      * @param rule The ChromeActivityTestRule to get the InfoBars from.
      */
     @SuppressWarnings("unchecked")
-    public static void clickInfoBarButton(final Button button, ChromeActivityTestRule rule) {
+    public static void clickInfoBarButton(final @Button int button, ChromeActivityTestRule rule) {
         if (!isInfoBarPresent(rule)) return;
         final List<InfoBar> infoBars = rule.getInfoBars();
         ThreadUtils.runOnUiThreadBlocking(() -> {
             switch (button) {
-                case PRIMARY:
+                case Button.PRIMARY:
                     InfoBarUtil.clickPrimaryButton(infoBars.get(0));
                     break;
                 default:
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
index 21ea3bb1..73c47f7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
@@ -83,15 +83,15 @@
      * @param activity The SupportedActivity value to convert to a String.
      * @return A String representation of the activity.
      */
-    public static String supportedActivityToString(SupportedActivity activity) {
+    public static String supportedActivityToString(@SupportedActivity int activity) {
         switch (activity) {
-            case CTA:
+            case SupportedActivity.CTA:
                 return "ChromeTabbedActivity";
-            case CCT:
+            case SupportedActivity.CCT:
                 return "CustomTabActivity";
-            case WAA:
+            case SupportedActivity.WAA:
                 return "WebappActivity";
-            case ALL:
+            case SupportedActivity.ALL:
                 return "AllActivities";
             default:
                 return "UnknownActivity";
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni
index 163111e..a8d3cc18 100644
--- a/chrome/android/webapk/shell_apk/current_version/current_version.gni
+++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@
 # //chrome/android/webapk/shell_apk:webapk is changed. This includes
 # Java files, Android resource files and AndroidManifest.xml. Does not affect
 # Chrome.apk
-current_shell_apk_version = 58
+current_shell_apk_version = 59
diff --git a/chrome/android/webapk/shell_apk/res/drawable-xxhdpi/splash_icon.xml b/chrome/android/webapk/shell_apk/res/drawable-xxhdpi/splash_icon.xml
index ab81c74..52efad7 100644
--- a/chrome/android/webapk/shell_apk/res/drawable-xxhdpi/splash_icon.xml
+++ b/chrome/android/webapk/shell_apk/res/drawable-xxhdpi/splash_icon.xml
@@ -4,4 +4,4 @@
      found in the LICENSE file. -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@mipmap/app_icon_xxxhdpi"/>
+    android:src="@mipmap/splash_icon_xxhdpi"/>
diff --git a/chrome/android/webapk/shell_apk/res/drawable-xxxhdpi/splash_icon.xml b/chrome/android/webapk/shell_apk/res/drawable-xxxhdpi/splash_icon.xml
index ab81c74..c74e9e37 100644
--- a/chrome/android/webapk/shell_apk/res/drawable-xxxhdpi/splash_icon.xml
+++ b/chrome/android/webapk/shell_apk/res/drawable-xxxhdpi/splash_icon.xml
@@ -4,4 +4,4 @@
      found in the LICENSE file. -->
 
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@mipmap/app_icon_xxxhdpi"/>
+    android:src="@mipmap/splash_icon_xxxhdpi"/>
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxhdpi.png b/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxhdpi.png
new file mode 100644
index 0000000..953536227
--- /dev/null
+++ b/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxhdpi.png
Binary files differ
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxxhdpi.png b/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxxhdpi.png
new file mode 100644
index 0000000..8f5d336
--- /dev/null
+++ b/chrome/android/webapk/shell_apk/res/mipmap-nodpi/splash_icon_xxxhdpi.png
Binary files differ
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 97b94c4..5b336c6 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -92,6 +92,8 @@
     "app_controller_mac.mm",
     "app_mode/app_mode_utils.cc",
     "app_mode/app_mode_utils.h",
+    "assist_ranker/assist_ranker_service_factory.cc",
+    "assist_ranker/assist_ranker_service_factory.h",
     "autocomplete/autocomplete_classifier_factory.cc",
     "autocomplete/autocomplete_classifier_factory.h",
     "autocomplete/chrome_autocomplete_provider_client.cc",
@@ -478,39 +480,6 @@
     "engagement/site_engagement_service_factory.h",
     "engagement/top_sites/site_engagement_top_sites_provider.cc",
     "engagement/top_sites/site_engagement_top_sites_provider.h",
-    "lifetime/browser_shutdown.cc",
-    "lifetime/browser_shutdown.h",
-    "media/webrtc/audio_debug_recordings_handler.cc",
-    "media/webrtc/audio_debug_recordings_handler.h",
-    "media/webrtc/webrtc_event_log_history.cc",
-    "media/webrtc/webrtc_event_log_history.h",
-    "media/webrtc/webrtc_event_log_manager.cc",
-    "media/webrtc/webrtc_event_log_manager.h",
-    "media/webrtc/webrtc_event_log_manager_common.cc",
-    "media/webrtc/webrtc_event_log_manager_common.h",
-    "media/webrtc/webrtc_event_log_manager_local.cc",
-    "media/webrtc/webrtc_event_log_manager_local.h",
-    "media/webrtc/webrtc_event_log_manager_remote.cc",
-    "media/webrtc/webrtc_event_log_manager_remote.h",
-    "media/webrtc/webrtc_event_log_uploader.cc",
-    "media/webrtc/webrtc_event_log_uploader.h",
-    "media/webrtc/webrtc_log_uploader.cc",
-    "media/webrtc/webrtc_log_uploader.h",
-    "media/webrtc/webrtc_log_util.cc",
-    "media/webrtc/webrtc_log_util.h",
-    "media/webrtc/webrtc_logging_handler_host.cc",
-    "media/webrtc/webrtc_logging_handler_host.h",
-    "media/webrtc/webrtc_rtp_dump_handler.cc",
-    "media/webrtc/webrtc_rtp_dump_handler.h",
-    "media/webrtc/webrtc_rtp_dump_writer.cc",
-    "media/webrtc/webrtc_rtp_dump_writer.h",
-    "media/webrtc/webrtc_text_log_handler.cc",
-    "media/webrtc/webrtc_text_log_handler.h",
-
-    # Oh hey, all the cool browser/extensions files are hanging out in
-    # //chrome/browser/extensions/BUILD.gn
-    "assist_ranker/assist_ranker_service_factory.cc",
-    "assist_ranker/assist_ranker_service_factory.h",
     "external_protocol/external_protocol_handler.cc",
     "external_protocol/external_protocol_handler.h",
     "external_protocol/external_protocol_observer.cc",
@@ -639,6 +608,8 @@
     "lifetime/application_lifetime.cc",
     "lifetime/application_lifetime.h",
     "lifetime/application_lifetime_mac.mm",
+    "lifetime/browser_shutdown.cc",
+    "lifetime/browser_shutdown.h",
     "loader/chrome_navigation_data.cc",
     "loader/chrome_navigation_data.h",
     "loader/chrome_resource_dispatcher_host_delegate.cc",
@@ -697,6 +668,8 @@
     "media/platform_verification_impl.h",
     "media/router/media_router_feature.cc",
     "media/router/media_router_feature.h",
+    "media/webrtc/audio_debug_recordings_handler.cc",
+    "media/webrtc/audio_debug_recordings_handler.h",
     "media/webrtc/desktop_media_list.h",
     "media/webrtc/desktop_media_list_base.cc",
     "media/webrtc/desktop_media_list_base.h",
@@ -718,10 +691,34 @@
     "media/webrtc/native_desktop_media_list.h",
     "media/webrtc/permission_bubble_media_access_handler.cc",
     "media/webrtc/permission_bubble_media_access_handler.h",
+    "media/webrtc/webrtc_event_log_history.cc",
+    "media/webrtc/webrtc_event_log_history.h",
+    "media/webrtc/webrtc_event_log_manager.cc",
+    "media/webrtc/webrtc_event_log_manager.h",
+    "media/webrtc/webrtc_event_log_manager_common.cc",
+    "media/webrtc/webrtc_event_log_manager_common.h",
     "media/webrtc/webrtc_event_log_manager_keyed_service.cc",
     "media/webrtc/webrtc_event_log_manager_keyed_service.h",
     "media/webrtc/webrtc_event_log_manager_keyed_service_factory.cc",
     "media/webrtc/webrtc_event_log_manager_keyed_service_factory.h",
+    "media/webrtc/webrtc_event_log_manager_local.cc",
+    "media/webrtc/webrtc_event_log_manager_local.h",
+    "media/webrtc/webrtc_event_log_manager_remote.cc",
+    "media/webrtc/webrtc_event_log_manager_remote.h",
+    "media/webrtc/webrtc_event_log_uploader.cc",
+    "media/webrtc/webrtc_event_log_uploader.h",
+    "media/webrtc/webrtc_log_uploader.cc",
+    "media/webrtc/webrtc_log_uploader.h",
+    "media/webrtc/webrtc_log_util.cc",
+    "media/webrtc/webrtc_log_util.h",
+    "media/webrtc/webrtc_logging_handler_host.cc",
+    "media/webrtc/webrtc_logging_handler_host.h",
+    "media/webrtc/webrtc_rtp_dump_handler.cc",
+    "media/webrtc/webrtc_rtp_dump_handler.h",
+    "media/webrtc/webrtc_rtp_dump_writer.cc",
+    "media/webrtc/webrtc_rtp_dump_writer.h",
+    "media/webrtc/webrtc_text_log_handler.cc",
+    "media/webrtc/webrtc_text_log_handler.h",
     "media/webrtc/window_icon_util.h",
     "media/webrtc/window_icon_util_chromeos.cc",
     "media/webrtc/window_icon_util_mac.mm",
@@ -1109,6 +1106,8 @@
     "policy/schema_registry_service.h",
     "policy/schema_registry_service_factory.cc",
     "policy/schema_registry_service_factory.h",
+    "policy/webusb_allow_devices_for_urls_policy_handler.cc",
+    "policy/webusb_allow_devices_for_urls_policy_handler.h",
     "predictors/autocomplete_action_predictor.cc",
     "predictors/autocomplete_action_predictor.h",
     "predictors/autocomplete_action_predictor_factory.cc",
@@ -4674,6 +4673,7 @@
       "../android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java",
       "../android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java",
       "../android/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java",
+      "../android/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java",
       "../android/java/src/org/chromium/chrome/browser/metrics/LaunchMetrics.java",
       "../android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java",
       "../android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java",
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index bc14baf..a6dd975 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -25,6 +25,7 @@
 
 using base::android::AttachCurrentThread;
 using base::android::JavaParamRef;
+using base::android::JavaRef;
 
 namespace autofill_assistant {
 namespace switches {
@@ -34,12 +35,15 @@
 namespace {
 
 // Builds a map from two Java arrays of strings with the same length.
-std::unique_ptr<std::map<std::string, std::string>>
-BuildParametersFromJava(JNIEnv* env, jobjectArray names, jobjectArray values) {
+std::unique_ptr<std::map<std::string, std::string>> BuildParametersFromJava(
+    JNIEnv* env,
+    const JavaRef<jobjectArray>& names,
+    const JavaRef<jobjectArray>& values) {
   std::vector<std::string> names_vector;
-  base::android::AppendJavaStringArrayToStringVector(env, names, &names_vector);
+  base::android::AppendJavaStringArrayToStringVector(env, names.obj(),
+                                                     &names_vector);
   std::vector<std::string> values_vector;
-  base::android::AppendJavaStringArrayToStringVector(env, values,
+  base::android::AppendJavaStringArrayToStringVector(env, values.obj(),
                                                      &values_vector);
   DCHECK_EQ(names_vector.size(), values_vector.size());
   auto parameters = std::make_unique<std::map<std::string, std::string>>();
diff --git a/chrome/browser/android/explore_sites/explore_sites_bridge.cc b/chrome/browser/android/explore_sites/explore_sites_bridge.cc
index fae0347..7da3aab 100644
--- a/chrome/browser/android/explore_sites/explore_sites_bridge.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_bridge.cc
@@ -16,6 +16,8 @@
 #include "chrome/browser/android/explore_sites/explore_sites_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
 #include "jni/ExploreSitesBridge_jni.h"
 #include "jni/ExploreSitesCategory_jni.h"
 #include "jni/ExploreSitesSite_jni.h"
@@ -152,8 +154,18 @@
     return;
   }
 
-  service->UpdateCatalogFromNetwork(base::BindOnce(
-      &UpdateCatalogDone, ScopedJavaGlobalRef<jobject>(j_callback_obj)));
+  // TODO(petewil): It might be better to move the PrefService work inside
+  // ExploreSitesService.
+  std::string accept_languages;
+  PrefService* pref_service = profile->GetPrefs();
+  if (pref_service != nullptr) {
+    accept_languages = pref_service->GetString(prefs::kAcceptLanguages);
+  }
+
+  service->UpdateCatalogFromNetwork(
+      accept_languages,
+      base::BindOnce(&UpdateCatalogDone,
+                     ScopedJavaGlobalRef<jobject>(j_callback_obj)));
 }
 
 // static
diff --git a/chrome/browser/android/explore_sites/explore_sites_fetcher.cc b/chrome/browser/android/explore_sites/explore_sites_fetcher.cc
index 1897421..1bc1d4bc 100644
--- a/chrome/browser/android/explore_sites/explore_sites_fetcher.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_fetcher.cc
@@ -26,6 +26,7 @@
 #include "google_apis/google_api_keys.h"
 #include "net/base/load_flags.h"
 #include "net/base/url_util.h"
+#include "net/http/http_request_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
@@ -68,10 +69,12 @@
     Callback callback,
     const std::string catalog_version,
     const std::string country_code,
+    const std::string accept_languages,
     scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
   GURL url = GetCatalogURL();
-  return base::WrapUnique(new ExploreSitesFetcher(
-      std::move(callback), url, catalog_version, country_code, loader_factory));
+  return base::WrapUnique(
+      new ExploreSitesFetcher(std::move(callback), url, catalog_version,
+                              country_code, accept_languages, loader_factory));
 }
 
 std::unique_ptr<ExploreSitesFetcher>
@@ -79,10 +82,12 @@
     Callback callback,
     const std::string catalog_version,
     const std::string country_code,
+    const std::string accept_languages,
     scoped_refptr<network::SharedURLLoaderFactory> loader_factory) {
   GURL url = GetCategoriesURL();
-  return base::WrapUnique(new ExploreSitesFetcher(
-      std::move(callback), url, catalog_version, country_code, loader_factory));
+  return base::WrapUnique(
+      new ExploreSitesFetcher(std::move(callback), url, catalog_version,
+                              country_code, accept_languages, loader_factory));
 }
 
 ExploreSitesFetcher::ExploreSitesFetcher(
@@ -90,6 +95,7 @@
     const GURL& url,
     const std::string catalog_version,
     const std::string country_code,
+    const std::string accept_languages,
     scoped_refptr<network::SharedURLLoaderFactory> loader_factory)
     : callback_(std::move(callback)),
       url_loader_factory_(loader_factory),
@@ -116,8 +122,12 @@
                                           : google_apis::GetNonStableAPIKey();
   resource_request->headers.SetHeader("x-goog-api-key", api_key);
   resource_request->headers.SetHeader("X-Client-Version", client_version);
-  resource_request->headers.SetHeader("Content-Type", kRequestContentType);
-  // TODO(freedjm): Implement Accept-Language support.
+  resource_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
+                                      kRequestContentType);
+  if (!accept_languages.empty()) {
+    resource_request->headers.SetHeader(
+        net::HttpRequestHeaders::kAcceptLanguage, accept_languages);
+  }
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
                                                  traffic_annotation);
diff --git a/chrome/browser/android/explore_sites/explore_sites_fetcher.h b/chrome/browser/android/explore_sites/explore_sites_fetcher.h
index fa257861..5cfe57b9 100644
--- a/chrome/browser/android/explore_sites/explore_sites_fetcher.h
+++ b/chrome/browser/android/explore_sites/explore_sites_fetcher.h
@@ -34,6 +34,7 @@
       Callback callback,
       const std::string catalog_version,
       const std::string country_code,
+      const std::string accept_languages,
       scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
 
   // Creates a fetcher for the GetCategories RPC.
@@ -41,6 +42,7 @@
       Callback callback,
       const std::string catalog_version,
       const std::string country_code,
+      const std::string accept_languages,
       scoped_refptr<network::SharedURLLoaderFactory> loader_factory);
 
   ~ExploreSitesFetcher();
@@ -51,6 +53,7 @@
       const GURL& url,
       const std::string catalog_version,
       const std::string country_code,
+      const std::string accept_languages,
       scoped_refptr<network ::SharedURLLoaderFactory> loader_factory);
 
   // Invoked from SimpleURLLoader after download is complete.
diff --git a/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc b/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc
index 414e466..ac05eb46 100644
--- a/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "chrome/browser/android/explore_sites/catalog.pb.h"
 #include "chrome/browser/android/explore_sites/explore_sites_types.h"
+#include "net/http/http_request_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_status.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -23,6 +24,10 @@
 using testing::Eq;
 using testing::SaveArg;
 
+namespace {
+const char kAcceptLanguages[] = "en-US,en;q=0.5";
+}  // namespace
+
 namespace explore_sites {
 
 // TODO(freedjm): Add tests for the headers.
@@ -156,6 +161,7 @@
     std::string* data_received) {
   std::unique_ptr<ExploreSitesFetcher> fetcher =
       ExploreSitesFetcher::CreateForGetCatalog(StoreResult(), "123", "KE",
+                                               kAcceptLanguages,
                                                test_shared_url_loader_factory_);
 
   std::move(respond_callback).Run();
@@ -223,4 +229,31 @@
             "getcatalog?country_code=KE&version_token=123");
 }
 
+TEST_F(ExploreSitesFetcherTest, TestHeaders) {
+  std::string data;
+  EXPECT_EQ(ExploreSitesRequestStatus::kSuccess,
+            RunFetcherWithData("Any data.", &data));
+
+  net::HttpRequestHeaders headers = last_resource_request.headers;
+  std::string content_type;
+  std::string languages;
+  bool success;
+
+  success = headers.HasHeader("x-goog-api-key");
+  EXPECT_TRUE(success);
+
+  success = headers.HasHeader("X-Client-Version");
+  EXPECT_TRUE(success);
+
+  success =
+      headers.GetHeader(net::HttpRequestHeaders::kContentType, &content_type);
+  EXPECT_TRUE(success);
+  EXPECT_EQ(content_type, "application/x-protobuf");
+
+  success =
+      headers.GetHeader(net::HttpRequestHeaders::kAcceptLanguage, &languages);
+  EXPECT_TRUE(success);
+  EXPECT_EQ(languages, kAcceptLanguages);
+}
+
 }  // namespace explore_sites
diff --git a/chrome/browser/android/explore_sites/explore_sites_service.h b/chrome/browser/android/explore_sites/explore_sites_service.h
index 37ce6a3..9bdd70a 100644
--- a/chrome/browser/android/explore_sites/explore_sites_service.h
+++ b/chrome/browser/android/explore_sites/explore_sites_service.h
@@ -30,8 +30,10 @@
   virtual void GetSiteImage(int site_id, BitmapCallback callback) = 0;
 
   // Fetch the latest catalog from the network and stores it locally. Returns
-  // true in the callback for success.
-  virtual void UpdateCatalogFromNetwork(BooleanCallback callback) = 0;
+  // true in the callback for success.  If the accept_languages string is empty,
+  // no "Accept-Language" header is created for the network request.
+  virtual void UpdateCatalogFromNetwork(std::string accept_languages,
+                                        BooleanCallback callback) = 0;
 };
 
 }  // namespace explore_sites
diff --git a/chrome/browser/android/explore_sites/explore_sites_service_impl.cc b/chrome/browser/android/explore_sites/explore_sites_service_impl.cc
index 2b102346..a75d0aef 100644
--- a/chrome/browser/android/explore_sites/explore_sites_service_impl.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_service_impl.cc
@@ -69,6 +69,7 @@
 }
 
 void ExploreSitesServiceImpl::UpdateCatalogFromNetwork(
+    std::string accept_languages,
     BooleanCallback callback) {
   if (!IsExploreSitesEnabled())
     return;
@@ -85,7 +86,7 @@
   explore_sites_fetcher_ = ExploreSitesFetcher::CreateForGetCatalog(
       base::BindOnce(&ExploreSitesServiceImpl::OnCatalogFetched,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
-      catalog_version, country_code, url_loader_factory_);
+      catalog_version, country_code, accept_languages, url_loader_factory_);
 }
 
 void ExploreSitesServiceImpl::OnCatalogFetched(
diff --git a/chrome/browser/android/explore_sites/explore_sites_service_impl.h b/chrome/browser/android/explore_sites/explore_sites_service_impl.h
index b954754..5cab255 100644
--- a/chrome/browser/android/explore_sites/explore_sites_service_impl.h
+++ b/chrome/browser/android/explore_sites/explore_sites_service_impl.h
@@ -34,7 +34,8 @@
   void GetCatalog(CatalogCallback callback) override;
   void GetCategoryImage(int category_id, BitmapCallback callback) override;
   void GetSiteImage(int site_id, BitmapCallback callback) override;
-  void UpdateCatalogFromNetwork(BooleanCallback callback) override;
+  void UpdateCatalogFromNetwork(std::string accept_languages,
+                                BooleanCallback callback) override;
 
  private:
   // KeyedService implementation:
diff --git a/chrome/browser/android/explore_sites/explore_sites_service_impl_unittest.cc b/chrome/browser/android/explore_sites/explore_sites_service_impl_unittest.cc
index e109497..cf2c24c8 100644
--- a/chrome/browser/android/explore_sites/explore_sites_service_impl_unittest.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_service_impl_unittest.cc
@@ -22,6 +22,7 @@
 const char kSite2Url[] = "https://sample.com/";
 const char kSite1Name[] = "example";
 const char kSite2Name[] = "sample";
+const char kAcceptLanguages[] = "en-US,en;q=0.5";
 }  // namespace
 
 namespace explore_sites {
@@ -154,6 +155,7 @@
   scoped_feature_list.InitAndEnableFeature(chrome::android::kExploreSites);
 
   service()->UpdateCatalogFromNetwork(
+      kAcceptLanguages,
       base::BindOnce(&ExploreSitesServiceImplTest::UpdateCatalogDoneCallback,
                      base::Unretained(this)));
 
diff --git a/chrome/browser/android/feed/feed_content_bridge.cc b/chrome/browser/android/feed/feed_content_bridge.cc
index 1b59573..af63ccf5 100644
--- a/chrome/browser/android/feed/feed_content_bridge.cc
+++ b/chrome/browser/android/feed/feed_content_bridge.cc
@@ -38,7 +38,7 @@
 using base::android::ScopedJavaLocalRef;
 using base::android::ToJavaArrayOfByteArray;
 using base::android::ToJavaArrayOfStrings;
-using base::android::JavaByteArrayToByteVector;
+using base::android::JavaByteArrayToString;
 
 namespace {
 
@@ -206,11 +206,10 @@
     const JavaRef<jbyteArray>& j_data) {
   DCHECK(content_mutation_);
   std::string key(ConvertJavaStringToUTF8(j_env, j_key));
-  std::vector<uint8_t> byte_vector;
-  JavaByteArrayToByteVector(j_env, j_data.obj(), &byte_vector);
+  std::string data;
+  JavaByteArrayToString(j_env, j_data.obj(), &data);
 
-  content_mutation_->AppendUpsertOperation(
-      key, std::string(byte_vector.begin(), byte_vector.end()));
+  content_mutation_->AppendUpsertOperation(key, data);
 }
 
 void FeedContentBridge::AppendDeleteAllOperation(
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc
index c4a9b2a8..be61fb32 100644
--- a/chrome/browser/android/preferences/pref_service_bridge.cc
+++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -298,6 +298,12 @@
   return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC);
 }
 
+static jboolean JNI_PrefServiceBridge_GetAutomaticDownloadsEnabled(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
+  return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS);
+}
+
 static jboolean JNI_PrefServiceBridge_GetBlockThirdPartyCookiesEnabled(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
@@ -749,6 +755,17 @@
       allow ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
 }
 
+static void JNI_PrefServiceBridge_SetAutomaticDownloadsEnabled(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    jboolean allow) {
+  HostContentSettingsMap* host_content_settings_map =
+      HostContentSettingsMapFactory::GetForProfile(GetOriginalProfile());
+  host_content_settings_map->SetDefaultContentSetting(
+      CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
+      allow ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK);
+}
+
 static void JNI_PrefServiceBridge_SetBlockThirdPartyCookiesEnabled(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc
index 7ca3663..a6082f3 100644
--- a/chrome/browser/android/provider/chrome_browser_provider.cc
+++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -104,21 +104,21 @@
 
 jlong JNI_ChromeBrowserProvider_ConvertJLongObjectToPrimitive(
     JNIEnv* env,
-    jobject long_obj) {
+    const JavaRef<jobject>& long_obj) {
   ScopedJavaLocalRef<jclass> jlong_clazz = GetClass(env, "java/lang/Long");
   jmethodID long_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
       env, jlong_clazz.obj(), "longValue", "()J");
-  return env->CallLongMethod(long_obj, long_value, NULL);
+  return env->CallLongMethod(long_obj.obj(), long_value, NULL);
 }
 
 jboolean JNI_ChromeBrowserProvider_ConvertJBooleanObjectToPrimitive(
     JNIEnv* env,
-    jobject boolean_object) {
+    const JavaRef<jobject>& boolean_object) {
   ScopedJavaLocalRef<jclass> jboolean_clazz =
       GetClass(env, "java/lang/Boolean");
   jmethodID boolean_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
       env, jboolean_clazz.obj(), "booleanValue", "()Z");
-  return env->CallBooleanMethod(boolean_object, boolean_value, NULL);
+  return env->CallBooleanMethod(boolean_object.obj(), boolean_value, NULL);
 }
 
 base::Time ConvertJlongToTime(jlong value) {
@@ -126,24 +126,26 @@
          base::TimeDelta::FromMilliseconds((int64_t)value);
 }
 
-jint JNI_ChromeBrowserProvider_ConvertJIntegerToJint(JNIEnv* env,
-                                                     jobject integer_obj) {
+jint JNI_ChromeBrowserProvider_ConvertJIntegerToJint(
+    JNIEnv* env,
+    const JavaRef<jobject>& integer_obj) {
   ScopedJavaLocalRef<jclass> jinteger_clazz =
       GetClass(env, "java/lang/Integer");
   jmethodID int_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
       env, jinteger_clazz.obj(), "intValue", "()I");
-  return env->CallIntMethod(integer_obj, int_value, NULL);
+  return env->CallIntMethod(integer_obj.obj(), int_value, NULL);
 }
 
 std::vector<base::string16> ConvertJStringArrayToString16Array(
     JNIEnv* env,
-    jobjectArray array) {
+    const JavaRef<jobjectArray>& array) {
   std::vector<base::string16> results;
-  if (array) {
-    jsize len = env->GetArrayLength(array);
+  if (!array.is_null()) {
+    jsize len = env->GetArrayLength(array.obj());
     for (int i = 0; i < len; i++) {
       ScopedJavaLocalRef<jstring> j_str(
-          env, static_cast<jstring>(env->GetObjectArrayElement(array, i)));
+          env,
+          static_cast<jstring>(env->GetObjectArrayElement(array.obj(), i)));
       results.push_back(ConvertJavaStringToUTF16(env, j_str));
     }
   }
@@ -725,21 +727,21 @@
 // Fills the bookmark |row| with the given java objects.
 void JNI_ChromeBrowserProvider_FillBookmarkRow(
     JNIEnv* env,
-    jobject obj,
-    jstring url,
-    jobject created,
-    jobject isBookmark,
-    jobject date,
-    jbyteArray favicon,
-    jstring title,
-    jobject visits,
+    const JavaRef<jobject>& obj,
+    const JavaRef<jstring>& url,
+    const JavaRef<jobject>& created,
+    const JavaRef<jobject>& isBookmark,
+    const JavaRef<jobject>& date,
+    const JavaRef<jbyteArray>& favicon,
+    const JavaRef<jstring>& title,
+    const JavaRef<jobject>& visits,
     jlong parent_id,
     history::HistoryAndBookmarkRow* row,
     BookmarkModel* model) {
   // Needed because of the internal bookmark model task invocation.
   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (url) {
+  if (!url.is_null()) {
     base::string16 raw_url = ConvertJavaStringToUTF16(env, url);
     // GURL doesn't accept the URL without protocol, but the Android CTS
     // allows it. We are trying to prefix with 'http://' to see whether
@@ -750,29 +752,29 @@
     row->set_raw_url(base::UTF16ToUTF8(raw_url));
   }
 
-  if (created)
+  if (!created.is_null())
     row->set_created(ConvertJlongToTime(
         JNI_ChromeBrowserProvider_ConvertJLongObjectToPrimitive(env, created)));
 
-  if (isBookmark)
+  if (!isBookmark.is_null())
     row->set_is_bookmark(
         JNI_ChromeBrowserProvider_ConvertJBooleanObjectToPrimitive(env,
                                                                    isBookmark));
 
-  if (date)
+  if (!date.is_null())
     row->set_last_visit_time(ConvertJlongToTime(
         JNI_ChromeBrowserProvider_ConvertJLongObjectToPrimitive(env, date)));
 
-  if (favicon) {
+  if (!favicon.is_null()) {
     std::vector<uint8_t> bytes;
-    base::android::JavaByteArrayToByteVector(env, favicon, &bytes);
+    base::android::JavaByteArrayToByteVector(env, favicon.obj(), &bytes);
     row->set_favicon(base::RefCountedBytes::TakeVector(&bytes));
   }
 
-  if (title)
+  if (!title.is_null())
     row->set_title(ConvertJavaStringToUTF16(env, title));
 
-  if (visits)
+  if (!visits.is_null())
     row->set_visit_count(
         JNI_ChromeBrowserProvider_ConvertJIntegerToJint(env, visits));
 
@@ -783,15 +785,16 @@
 }
 
 // Fills the bookmark |row| with the given java objects if it is not null.
-void JNI_ChromeBrowserProvider_FillSearchRow(JNIEnv* env,
-                                             jobject obj,
-                                             jstring search_term,
-                                             jobject date,
-                                             history::SearchRow* row) {
-  if (search_term)
+void JNI_ChromeBrowserProvider_FillSearchRow(
+    JNIEnv* env,
+    const JavaRef<jobject>& obj,
+    const JavaRef<jstring>& search_term,
+    const JavaRef<jobject>& date,
+    history::SearchRow* row) {
+  if (!search_term.is_null())
     row->set_search_term(ConvertJavaStringToUTF16(env, search_term));
 
-  if (date)
+  if (!date.is_null())
     row->set_search_time(ConvertJlongToTime(
         JNI_ChromeBrowserProvider_ConvertJLongObjectToPrimitive(env, date)));
 }
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc
index 623ba72..abb2294 100644
--- a/chrome/browser/android/vr/vr_gl_thread.cc
+++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -518,7 +518,7 @@
 
 void VrGLThread::ReportUiOperationResultForTesting(
     const UiTestOperationType& action_type,
-    const VrUiTestActivityResult& result) {
+    const UiTestOperationResult& result) {
   DCHECK(OnGlThread());
   main_thread_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&VrShell::ReportUiOperationResultForTesting,
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h
index 120bee4..a1f4b211 100644
--- a/chrome/browser/android/vr/vr_gl_thread.h
+++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -78,7 +78,7 @@
   void ForceExitVr() override;
   void ReportUiOperationResultForTesting(
       const UiTestOperationType& action_type,
-      const VrUiTestActivityResult& result) override;
+      const UiTestOperationResult& result) override;
 
   // PlatformInputHandler
   void ForwardEventToPlatformUi(std::unique_ptr<InputEvent> event) override;
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc
index 79b864c..181b8765 100644
--- a/chrome/browser/android/vr/vr_shell.cc
+++ b/chrome/browser/android/vr/vr_shell.cc
@@ -1280,8 +1280,24 @@
           base::android::ConvertJavaStringToUTF8(env, filepath_base)));
 }
 
+void VrShell::WatchElementForVisibilityChangeForTesting(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj,
+    jint element_name,
+    jint timeout_ms) {
+  VisibilityChangeExpectation visibility_expectation;
+  visibility_expectation.element_name =
+      static_cast<UserFriendlyElementName>(element_name);
+  visibility_expectation.timeout_ms = timeout_ms;
+  PostToGlThread(
+      FROM_HERE,
+      base::BindOnce(
+          &BrowserRenderer::WatchElementForVisibilityChangeForTesting,
+          gl_thread_->GetBrowserRenderer(), visibility_expectation));
+}
+
 void VrShell::ReportUiOperationResultForTesting(UiTestOperationType action_type,
-                                                VrUiTestActivityResult result) {
+                                                UiTestOperationResult result) {
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_VrShell_reportUiOperationResultForTesting(env, j_vr_shell_,
                                                  static_cast<int>(action_type),
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h
index 043cbe3..973f634 100644
--- a/chrome/browser/android/vr/vr_shell.h
+++ b/chrome/browser/android/vr/vr_shell.h
@@ -57,7 +57,7 @@
 class VrShellDelegate;
 class VrWebContentsObserver;
 enum class UiTestOperationType;
-enum class VrUiTestActivityResult;
+enum class UiTestOperationResult;
 struct Assets;
 struct AutocompleteRequest;
 
@@ -286,8 +286,14 @@
       const base::android::JavaParamRef<jobject>& obj,
       jstring filepath_base);
 
+  void WatchElementForVisibilityChangeForTesting(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint element_name,
+      jint timeout_ms);
+
   void ReportUiOperationResultForTesting(UiTestOperationType action_type,
-                                         VrUiTestActivityResult result);
+                                         UiTestOperationResult result);
 
   void PerformControllerActionForTesting(
       JNIEnv* env,
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm
index 538ad9b..407cb79 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm
+++ b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/task/post_task.h"
+#include "base/threading/scoped_blocking_call.h"
 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h"
 #include "chrome/browser/apps/app_shim/app_shim_host_mac.h"
 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
@@ -40,7 +41,7 @@
 void DeleteSocketFiles(const base::FilePath& directory_in_tmp,
                        const base::FilePath& symlink_path,
                        const base::FilePath& version_path) {
-  base::AssertBlockingAllowed();
+  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
 
   // Delete in reverse order of creation.
   if (!version_path.empty())
@@ -95,7 +96,7 @@
 }
 
 void AppShimHostManager::InitOnBackgroundThread() {
-  base::AssertBlockingAllowed();
+  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
   base::FilePath user_data_dir;
   if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
     return;
diff --git a/chrome/browser/apps/platform_apps/api/BUILD.gn b/chrome/browser/apps/platform_apps/api/BUILD.gn
index 589307c..bde5f9d 100644
--- a/chrome/browser/apps/platform_apps/api/BUILD.gn
+++ b/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -27,15 +27,28 @@
     "browser/browser_api.h",
     "browser_context_keyed_service_factories.cc",
     "browser_context_keyed_service_factories.h",
+    "media_galleries/blob_data_source_factory.cc",
+    "media_galleries/blob_data_source_factory.h",
+    "media_galleries/media_galleries_api.cc",
+    "media_galleries/media_galleries_api.h",
+    "media_galleries/media_galleries_api_util.cc",
+    "media_galleries/media_galleries_api_util.h",
   ]
 
   deps = [
+    "//chrome/app:generated_resources_grit",
+
     # TODO(https://crbug.com/883570): It'd be nice to have more APIs here
     # extracted into their own BUILD files (so they are easy to audit, add, or
     # remove), but any that depend on //chrome/browser:browser can't.
     "//chrome/browser/apps/platform_apps/api/music_manager_private",
     "//chrome/browser/extensions",
+    "//chrome/browser/ui",
+    "//chrome/common",
     "//chrome/common/apps/platform_apps/api",
+    "//chrome/services/media_gallery_util/public/cpp",
+    "//components/storage_monitor",
+    "//components/web_modal",
     "//extensions/browser",
   ]
 
@@ -52,7 +65,6 @@
     deps += [
       "//chrome:strings",
       "//chrome/browser/chromeos",
-      "//chrome/browser/ui",
       "//chromeos/components/proximity_auth",
       "//chromeos/components/proximity_auth/logging",
       "//components/account_id",
diff --git a/chrome/browser/extensions/api/media_galleries/OWNERS b/chrome/browser/apps/platform_apps/api/media_galleries/OWNERS
similarity index 100%
rename from chrome/browser/extensions/api/media_galleries/OWNERS
rename to chrome/browser/apps/platform_apps/api/media_galleries/OWNERS
diff --git a/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
similarity index 93%
rename from chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc
rename to chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
index 34b2d95..f54bf34b 100644
--- a/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.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/extensions/api/media_galleries/blob_data_source_factory.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/blob_reader.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 namespace {
 
 // Media data source that reads data from a blob in browser process.
@@ -80,4 +81,5 @@
                                                blob_uuid_, media_data_callback);
 }
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h
similarity index 77%
rename from chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h
rename to chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h
index c2ed111..f78e939 100644
--- a/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.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 CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
-#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
+#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
+#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
 
 #include <memory>
 #include <string>
@@ -16,7 +16,8 @@
 class BrowserContext;
 }  // namespace content
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
 // Factory to provide media data source for extension media gallery API.
 // Internally it will read media data from a blob in browser process.
@@ -40,6 +41,7 @@
   DISALLOW_COPY_AND_ASSIGN(BlobDataSourceFactory);
 };
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
 
-#endif  // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
+#endif  // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
similarity index 83%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index 59346949..1fd3b9bf 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -4,7 +4,7 @@
 
 // Implements the Chrome Extensions Media Galleries API.
 
-#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h"
 
 #include <stddef.h>
 
@@ -23,9 +23,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h"
-#include "chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h"
 #include "chrome/browser/extensions/chrome_extension_function_details.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
@@ -36,7 +36,7 @@
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/common/extensions/api/media_galleries.h"
+#include "chrome/common/apps/platform_apps/api/media_galleries.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/services/media_gallery_util/public/cpp/safe_media_metadata_parser.h"
@@ -70,9 +70,10 @@
 using storage_monitor::MediaStorageUtil;
 using storage_monitor::StorageInfo;
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
-namespace MediaGalleries = api::media_galleries;
+namespace MediaGalleries = media_galleries;
 namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
 namespace AddGalleryWatch = MediaGalleries::AddGalleryWatch;
 namespace RemoveGalleryWatch = MediaGalleries::RemoveGalleryWatch;
@@ -112,8 +113,8 @@
 // initializes the MediaGalleriesPreferences
 bool Setup(Profile* profile, std::string* error, base::Closure callback) {
   if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
-    *error = std::string(kDisallowedByPolicy) +
-        prefs::kAllowFileSelectionDialogs;
+    *error =
+        std::string(kDisallowedByPolicy) + prefs::kAllowFileSelectionDialogs;
     return false;
   }
 
@@ -127,7 +128,7 @@
 // |gallery_id| is valid and returns false otherwise.
 bool GetGalleryFilePathAndId(const std::string& gallery_id,
                              Profile* profile,
-                             const Extension* extension,
+                             const extensions::Extension* extension,
                              base::FilePath* gallery_file_path,
                              MediaGalleryPrefId* gallery_pref_id) {
   MediaGalleryPrefId pref_id;
@@ -146,24 +147,25 @@
 
 base::ListValue* ConstructFileSystemList(
     content::RenderFrameHost* rfh,
-    const Extension* extension,
+    const extensions::Extension* extension,
     const std::vector<MediaFileSystemInfo>& filesystems) {
   if (!rfh)
     return NULL;
 
-  MediaGalleriesPermission::CheckParam read_param(
-      MediaGalleriesPermission::kReadPermission);
-  const PermissionsData* permissions_data = extension->permissions_data();
+  extensions::MediaGalleriesPermission::CheckParam read_param(
+      extensions::MediaGalleriesPermission::kReadPermission);
+  const extensions::PermissionsData* permissions_data =
+      extension->permissions_data();
   bool has_read_permission = permissions_data->CheckAPIPermissionWithParam(
-      APIPermission::kMediaGalleries, &read_param);
-  MediaGalleriesPermission::CheckParam copy_to_param(
-      MediaGalleriesPermission::kCopyToPermission);
+      extensions::APIPermission::kMediaGalleries, &read_param);
+  extensions::MediaGalleriesPermission::CheckParam copy_to_param(
+      extensions::MediaGalleriesPermission::kCopyToPermission);
   bool has_copy_to_permission = permissions_data->CheckAPIPermissionWithParam(
-      APIPermission::kMediaGalleries, &copy_to_param);
-  MediaGalleriesPermission::CheckParam delete_param(
-      MediaGalleriesPermission::kDeletePermission);
+      extensions::APIPermission::kMediaGalleries, &copy_to_param);
+  extensions::MediaGalleriesPermission::CheckParam delete_param(
+      extensions::MediaGalleriesPermission::kDeletePermission);
   bool has_delete_permission = permissions_data->CheckAPIPermissionWithParam(
-      APIPermission::kMediaGalleries, &delete_param);
+      extensions::APIPermission::kMediaGalleries, &delete_param);
 
   const int child_id = rfh->GetProcess()->GetID();
   std::unique_ptr<base::ListValue> list(new base::ListValue());
@@ -217,8 +219,7 @@
   typedef base::Callback<void(const base::FilePath&)> Callback;
 
   SelectDirectoryDialog(WebContents* web_contents, const Callback& callback)
-      : web_contents_(web_contents),
-        callback_(callback) {
+      : web_contents_(web_contents), callback_(callback) {
     select_file_dialog_ = ui::SelectFileDialog::Create(
         this, std::make_unique<ChromeSelectFilePolicy>(web_contents));
   }
@@ -226,14 +227,10 @@
   void Show(const base::FilePath& default_path) {
     AddRef();  // Balanced in the two reachable listener outcomes.
     select_file_dialog_->SelectFile(
-      ui::SelectFileDialog::SELECT_FOLDER,
-      l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
-      default_path,
-      NULL,
-      0,
-      base::FilePath::StringType(),
-      platform_util::GetTopLevel(web_contents_->GetNativeView()),
-      NULL);
+        ui::SelectFileDialog::SELECT_FOLDER,
+        l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
+        default_path, NULL, 0, base::FilePath::StringType(),
+        platform_util::GetTopLevel(web_contents_->GetNativeView()), NULL);
   }
 
   // ui::SelectFileDialog::Listener implementation.
@@ -281,8 +278,9 @@
   // Otherwise, check for the current app window for the app (app windows
   // support modal dialogs).
   if (!app_id.empty()) {
-    AppWindow* window = AppWindowRegistry::Get(browser_context)
-                            ->GetCurrentAppWindowForApp(app_id);
+    extensions::AppWindow* window =
+        extensions::AppWindowRegistry::Get(browser_context)
+            ->GetCurrentAppWindowForApp(app_id);
     if (window)
       return window->web_contents();
   }
@@ -297,30 +295,29 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile_);
 
-  EventRouter::Get(profile_)->RegisterObserver(
+  extensions::EventRouter::Get(profile_)->RegisterObserver(
       this, MediaGalleries::OnGalleryChanged::kEventName);
 
   gallery_watch_manager()->AddObserver(profile_, this);
 }
 
-MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {
-}
+MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {}
 
 void MediaGalleriesEventRouter::Shutdown() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   weak_ptr_factory_.InvalidateWeakPtrs();
 
-  EventRouter::Get(profile_)->UnregisterObserver(this);
+  extensions::EventRouter::Get(profile_)->UnregisterObserver(this);
 
   gallery_watch_manager()->RemoveObserver(profile_);
 }
 
-static base::LazyInstance<
-    BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>>::DestructorAtExit
+static base::LazyInstance<extensions::BrowserContextKeyedAPIFactory<
+    MediaGalleriesEventRouter>>::DestructorAtExit
     g_media_galleries_api_factory = LAZY_INSTANCE_INITIALIZER;
 
 // static
-BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
+extensions::BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
 MediaGalleriesEventRouter::GetFactoryInstance() {
   return g_media_galleries_api_factory.Pointer();
 }
@@ -331,23 +328,24 @@
   DCHECK(media_file_system_registry()
              ->GetPreferences(Profile::FromBrowserContext(context))
              ->IsInitialized());
-  return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
+  return extensions::BrowserContextKeyedAPIFactory<
+      MediaGalleriesEventRouter>::Get(context);
 }
 
 bool MediaGalleriesEventRouter::ExtensionHasGalleryChangeListener(
     const std::string& extension_id) const {
-  return EventRouter::Get(profile_)->ExtensionHasEventListener(
+  return extensions::EventRouter::Get(profile_)->ExtensionHasEventListener(
       extension_id, MediaGalleries::OnGalleryChanged::kEventName);
 }
 
 void MediaGalleriesEventRouter::DispatchEventToExtension(
     const std::string& extension_id,
-    events::HistogramValue histogram_value,
+    extensions::events::HistogramValue histogram_value,
     const std::string& event_name,
     std::unique_ptr<base::ListValue> event_args) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  EventRouter* router = EventRouter::Get(profile_);
+  extensions::EventRouter* router = extensions::EventRouter::Get(profile_);
   if (!router->ExtensionHasEventListener(extension_id, event_name))
     return;
 
@@ -357,29 +355,31 @@
 }
 
 void MediaGalleriesEventRouter::OnGalleryChanged(
-    const std::string& extension_id, MediaGalleryPrefId gallery_id) {
+    const std::string& extension_id,
+    MediaGalleryPrefId gallery_id) {
   MediaGalleries::GalleryChangeDetails details;
   details.type = MediaGalleries::GALLERY_CHANGE_TYPE_CONTENTS_CHANGED;
   details.gallery_id = base::NumberToString(gallery_id);
-  DispatchEventToExtension(extension_id,
-                           events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
-                           MediaGalleries::OnGalleryChanged::kEventName,
-                           MediaGalleries::OnGalleryChanged::Create(details));
+  DispatchEventToExtension(
+      extension_id, extensions::events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
+      MediaGalleries::OnGalleryChanged::kEventName,
+      MediaGalleries::OnGalleryChanged::Create(details));
 }
 
 void MediaGalleriesEventRouter::OnGalleryWatchDropped(
-    const std::string& extension_id, MediaGalleryPrefId gallery_id) {
+    const std::string& extension_id,
+    MediaGalleryPrefId gallery_id) {
   MediaGalleries::GalleryChangeDetails details;
   details.type = MediaGalleries::GALLERY_CHANGE_TYPE_WATCH_DROPPED;
   details.gallery_id = gallery_id;
-  DispatchEventToExtension(extension_id,
-                           events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
-                           MediaGalleries::OnGalleryChanged::kEventName,
-                           MediaGalleries::OnGalleryChanged::Create(details));
+  DispatchEventToExtension(
+      extension_id, extensions::events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
+      MediaGalleries::OnGalleryChanged::kEventName,
+      MediaGalleries::OnGalleryChanged::Create(details));
 }
 
 void MediaGalleriesEventRouter::OnListenerRemoved(
-    const EventListenerInfo& details) {
+    const extensions::EventListenerInfo& details) {
   if (details.event_name == MediaGalleries::OnGalleryChanged::kEventName &&
       !ExtensionHasGalleryChangeListener(details.extension_id)) {
     gallery_watch_manager()->RemoveAllWatches(profile_, details.extension_id);
@@ -393,20 +393,22 @@
     ~MediaGalleriesGetMediaFileSystemsFunction() {}
 
 bool MediaGalleriesGetMediaFileSystemsFunction::RunAsync() {
-  media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
+  ::media_galleries::UsageCount(::media_galleries::GET_MEDIA_FILE_SYSTEMS);
   std::unique_ptr<GetMediaFileSystems::Params> params(
       GetMediaFileSystems::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
   MediaGalleries::GetMediaFileSystemsInteractivity interactive =
       MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO;
-  if (params->details.get() && params->details->interactive != MediaGalleries::
-         GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
+  if (params->details.get() &&
+      params->details->interactive !=
+          MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
     interactive = params->details->interactive;
   }
 
-  return Setup(GetProfile(), &error_, base::Bind(
-      &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, this,
-      interactive));
+  return Setup(
+      GetProfile(), &error_,
+      base::Bind(&MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit,
+                 this, interactive));
 }
 
 void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit(
@@ -470,11 +472,9 @@
 }
 
 void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
-  media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
-  WebContents* contents =
-      GetWebContentsForPrompt(GetSenderWebContents(),
-                              browser_context(),
-                              extension()->id());
+  ::media_galleries::UsageCount(::media_galleries::SHOW_DIALOG);
+  WebContents* contents = GetWebContentsForPrompt(
+      GetSenderWebContents(), browser_context(), extension()->id());
   if (!contents) {
     SendResponse(false);
     return;
@@ -505,17 +505,18 @@
     ~MediaGalleriesAddUserSelectedFolderFunction() {}
 
 bool MediaGalleriesAddUserSelectedFolderFunction::RunAsync() {
-  media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER);
-  return Setup(GetProfile(), &error_, base::Bind(
-      &MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, this));
+  ::media_galleries::UsageCount(::media_galleries::ADD_USER_SELECTED_FOLDER);
+  return Setup(
+      GetProfile(), &error_,
+      base::Bind(
+          &MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit,
+          this));
 }
 
 void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
   const std::string& app_id = extension()->id();
-  WebContents* contents =
-      GetWebContentsForPrompt(GetSenderWebContents(),
-                              browser_context(),
-                              app_id);
+  WebContents* contents = GetWebContentsForPrompt(GetSenderWebContents(),
+                                                  browser_context(), app_id);
   if (!contents) {
     SendResponse(false);
     return;
@@ -542,26 +543,22 @@
     // User cancelled case.
     GetMediaFileSystemsForExtension(base::Bind(
         &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
-        this,
-        kInvalidMediaGalleryPrefId));
+        this, kInvalidMediaGalleryPrefId));
     return;
   }
 
   extensions::file_system_api::SetLastChooseEntryDirectory(
-      extensions::ExtensionPrefs::Get(GetProfile()),
-      extension()->id(),
+      extensions::ExtensionPrefs::Get(GetProfile()), extension()->id(),
       selected_directory);
 
   MediaGalleriesPreferences* preferences =
       media_file_system_registry()->GetPreferences(GetProfile());
-  MediaGalleryPrefId pref_id =
-      preferences->AddGalleryByPath(selected_directory,
-                                    MediaGalleryPrefInfo::kUserAdded);
+  MediaGalleryPrefId pref_id = preferences->AddGalleryByPath(
+      selected_directory, MediaGalleryPrefInfo::kUserAdded);
   preferences->SetGalleryPermissionForExtension(*extension(), pref_id, true);
 
   GetMediaFileSystemsForExtension(base::Bind(
-      &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
-      this,
+      &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId, this,
       pref_id));
 }
 
@@ -591,9 +588,8 @@
   SendResponse(true);
 }
 
-void
-MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension(
-    const MediaFileSystemsCallback& cb) {
+void MediaGalleriesAddUserSelectedFolderFunction::
+    GetMediaFileSystemsForExtension(const MediaFileSystemsCallback& cb) {
   if (!render_frame_host()) {
     cb.Run(std::vector<MediaFileSystemInfo>());
     return;
@@ -610,7 +606,7 @@
 MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
 
 bool MediaGalleriesGetMetadataFunction::RunAsync() {
-  media_galleries::UsageCount(media_galleries::GET_METADATA);
+  ::media_galleries::UsageCount(::media_galleries::GET_METADATA);
   std::string blob_uuid;
   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
 
@@ -622,9 +618,9 @@
   if (!options)
     return false;
 
-  return Setup(GetProfile(), &error_, base::Bind(
-      &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this,
-      options->metadata_type, blob_uuid));
+  return Setup(GetProfile(), &error_,
+               base::Bind(&MediaGalleriesGetMetadataFunction::OnPreferencesInit,
+                          this, options->metadata_type, blob_uuid));
 }
 
 void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
@@ -633,11 +629,10 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // BlobReader is self-deleting.
-  BlobReader* reader = new BlobReader(
-      GetProfile(),
-      blob_uuid,
-      base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
-                 metadata_type, blob_uuid));
+  BlobReader* reader =
+      new BlobReader(GetProfile(), blob_uuid,
+                     base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata,
+                                this, metadata_type, blob_uuid));
   reader->SetByteRange(0, net::kMaxBytesToSniff);
   reader->Start();
 }
@@ -791,8 +786,7 @@
 //              MediaGalleriesAddGalleryWatchFunction                        //
 ///////////////////////////////////////////////////////////////////////////////
 MediaGalleriesAddGalleryWatchFunction::
-    ~MediaGalleriesAddGalleryWatchFunction() {
-}
+    ~MediaGalleriesAddGalleryWatchFunction() {}
 
 bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -809,8 +803,7 @@
           GetProfile());
   preferences->EnsureInitialized(
       base::Bind(&MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit,
-                 this,
-                 params->gallery_id));
+                 this, params->gallery_id));
 
   return true;
 }
@@ -819,11 +812,8 @@
     const std::string& pref_id) {
   base::FilePath gallery_file_path;
   MediaGalleryPrefId gallery_pref_id = kInvalidMediaGalleryPrefId;
-  if (!GetGalleryFilePathAndId(pref_id,
-                               GetProfile(),
-                               extension(),
-                               &gallery_file_path,
-                               &gallery_pref_id)) {
+  if (!GetGalleryFilePathAndId(pref_id, GetProfile(), extension(),
+                               &gallery_file_path, &gallery_pref_id)) {
     api::media_galleries::AddGalleryWatchResult result;
     error_ = kInvalidGalleryIdMsg;
     result.gallery_id = kInvalidGalleryId;
@@ -834,11 +824,8 @@
   }
 
   gallery_watch_manager()->AddWatch(
-      GetProfile(),
-      extension(),
-      gallery_pref_id,
-      base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse,
-                 this,
+      GetProfile(), extension(), gallery_pref_id,
+      base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse, this,
                  gallery_pref_id));
 }
 
@@ -876,8 +863,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 MediaGalleriesRemoveGalleryWatchFunction::
-    ~MediaGalleriesRemoveGalleryWatchFunction() {
-}
+    ~MediaGalleriesRemoveGalleryWatchFunction() {}
 
 bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -893,8 +879,7 @@
           GetProfile());
   preferences->EnsureInitialized(
       base::Bind(&MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit,
-                 this,
-                 params->gallery_id));
+                 this, params->gallery_id));
   return true;
 }
 
@@ -902,19 +887,17 @@
     const std::string& pref_id) {
   base::FilePath gallery_file_path;
   MediaGalleryPrefId gallery_pref_id = 0;
-  if (!GetGalleryFilePathAndId(pref_id,
-                               GetProfile(),
-                               extension(),
-                               &gallery_file_path,
-                               &gallery_pref_id)) {
+  if (!GetGalleryFilePathAndId(pref_id, GetProfile(), extension(),
+                               &gallery_file_path, &gallery_pref_id)) {
     error_ = kInvalidGalleryIdMsg;
     SendResponse(false);
     return;
   }
 
-  gallery_watch_manager()->RemoveWatch(
-      GetProfile(), extension_id(), gallery_pref_id);
+  gallery_watch_manager()->RemoveWatch(GetProfile(), extension_id(),
+                                       gallery_pref_id);
   SendResponse(true);
 }
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.h b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
similarity index 84%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_api.h
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
index ebe708a..224ea6d5 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.h
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h
@@ -5,8 +5,8 @@
 // Defines the Chrome Extensions Media Galleries API functions for accessing
 // user's media files, as specified in the extension API IDL.
 
-#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
-#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
+#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
+#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
 
 #include <stdint.h>
 
@@ -20,7 +20,7 @@
 #include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager_observer.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
-#include "chrome/common/extensions/api/media_galleries.h"
+#include "chrome/common/apps/platform_apps/api/media_galleries.h"
 #include "chrome/common/media_galleries/metadata_types.h"
 #include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h"
 #include "components/storage_monitor/media_storage_util.h"
@@ -28,19 +28,18 @@
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_event_histogram_value.h"
 
-namespace MediaGalleries = extensions::api::media_galleries;
-
 namespace content {
 class BlobHandle;
 }
 
 class SafeMediaMetadataParser;
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
 // The profile-keyed service that manages the media galleries extension API.
 // Created at the same time as the Profile. This is also the event router.
-class MediaGalleriesEventRouter : public BrowserContextKeyedAPI,
+class MediaGalleriesEventRouter : public extensions::BrowserContextKeyedAPI,
                                   public GalleryWatchManagerObserver,
                                   public extensions::EventRouter::Observer {
  public:
@@ -48,8 +47,8 @@
   void Shutdown() override;
 
   // BrowserContextKeyedAPI implementation.
-  static BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
-      GetFactoryInstance();
+  static extensions::BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
+  GetFactoryInstance();
 
   // Convenience method to get the MediaGalleriesAPI for a profile.
   static MediaGalleriesEventRouter* Get(content::BrowserContext* context);
@@ -57,20 +56,20 @@
   bool ExtensionHasGalleryChangeListener(const std::string& extension_id) const;
 
  private:
-  friend class BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>;
+  friend class extensions::BrowserContextKeyedAPIFactory<
+      MediaGalleriesEventRouter>;
 
-  void DispatchEventToExtension(const std::string& extension_id,
-                                events::HistogramValue histogram_value,
-                                const std::string& event_name,
-                                std::unique_ptr<base::ListValue> event_args);
+  void DispatchEventToExtension(
+      const std::string& extension_id,
+      extensions::events::HistogramValue histogram_value,
+      const std::string& event_name,
+      std::unique_ptr<base::ListValue> event_args);
 
   explicit MediaGalleriesEventRouter(content::BrowserContext* context);
   ~MediaGalleriesEventRouter() override;
 
   // BrowserContextKeyedAPI implementation.
-  static const char* service_name() {
-    return "MediaGalleriesAPI";
-  }
+  static const char* service_name() { return "MediaGalleriesAPI"; }
   static const bool kServiceIsNULLWhileTesting = true;
 
   // GalleryWatchManagerObserver
@@ -80,7 +79,7 @@
                              MediaGalleryPrefId gallery_id) override;
 
   // extensions::EventRouter::Observer implementation.
-  void OnListenerRemoved(const EventListenerInfo& details) override;
+  void OnListenerRemoved(const extensions::EventListenerInfo& details) override;
 
   // Current profile.
   Profile* profile_;
@@ -103,7 +102,7 @@
  private:
   // Bottom half for RunAsync, invoked after the preferences is initialized.
   void OnPreferencesInit(
-      MediaGalleries::GetMediaFileSystemsInteractivity interactive);
+      media_galleries::GetMediaFileSystemsInteractivity interactive);
 
   // Always show the dialog.
   void AlwaysShowDialog(const std::vector<MediaFileSystemInfo>& filesystems);
@@ -171,10 +170,10 @@
 
  private:
   // Bottom half for RunAsync, invoked after the preferences is initialized.
-  void OnPreferencesInit(MediaGalleries::GetMetadataType metadata_type,
+  void OnPreferencesInit(media_galleries::GetMetadataType metadata_type,
                          const std::string& blob_uuid);
 
-  void GetMetadata(MediaGalleries::GetMetadataType metadata_type,
+  void GetMetadata(media_galleries::GetMetadataType metadata_type,
                    const std::string& blob_uuid,
                    std::unique_ptr<std::string> blob_header,
                    int64_t total_blob_length);
@@ -223,6 +222,7 @@
   void OnPreferencesInit(const std::string& pref_id);
 };
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
 
-#endif  // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
+#endif  // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.cc
similarity index 86%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.cc
index 9a0eda7..5245510 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.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/extensions/api/media_galleries/media_galleries_api_util.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h"
 
 #include "base/logging.h"
-#include "chrome/common/extensions/api/media_galleries.h"
+#include "chrome/common/apps/platform_apps/api/media_galleries.h"
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
 template <class T>
 void SetValueScopedPtr(T value, std::unique_ptr<T>* destination) {
@@ -27,7 +28,7 @@
 std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
     chrome::mojom::MediaMetadataPtr metadata) {
   DCHECK(metadata);
-  extensions::api::media_galleries::MediaMetadata extension_metadata;
+  media_galleries::MediaMetadata extension_metadata;
   extension_metadata.mime_type = std::move(metadata->mime_type);
   if (metadata->height >= 0 && metadata->width >= 0) {
     extension_metadata.height.reset(new int(metadata->height));
@@ -49,7 +50,7 @@
   SetValueScopedPtr(metadata->track, &extension_metadata.track);
 
   for (const chrome::mojom::MediaStreamInfoPtr& info : metadata->raw_tags) {
-    extensions::api::media_galleries::StreamInfo stream_info;
+    media_galleries::StreamInfo stream_info;
     stream_info.type = std::move(info->type);
     base::DictionaryValue* dict_value;
     info->additional_properties.GetAsDictionary(&dict_value);
@@ -60,4 +61,5 @@
   return extension_metadata.ToValue();
 }
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h
similarity index 60%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h
index c768acde..724ead6 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_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 CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
-#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
+#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
+#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
 
 #include <memory>
 
@@ -13,13 +13,15 @@
 class DictionaryValue;
 }  // namespace base
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
 // Converts a mojo media metadata struct into a dictionary. Internally uses
 // extension's auto generated serializer.
 std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
     chrome::mojom::MediaMetadataPtr metadata);
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
 
-#endif  // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
+#endif  // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc
similarity index 93%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc
index 05a4fb4..0bbb5c4 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc
@@ -18,9 +18,9 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
@@ -156,8 +156,7 @@
     MediaGalleriesPreferences* preferences = GetAndInitializePreferences();
 
     // Make a copy, as the iterator would be invalidated otherwise.
-    const MediaGalleriesPrefInfoMap galleries =
-        preferences->known_galleries();
+    const MediaGalleriesPrefInfoMap galleries = preferences->known_galleries();
     for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
          it != galleries.end(); ++it) {
       preferences->ForgetGalleryById(it->first);
@@ -178,15 +177,11 @@
     ASSERT_FALSE(preferences->LookUpGalleryByPath(
         fake_gallery_temp_dir_.GetPath(), &gallery_info));
     MediaGalleryPrefId id = preferences->AddGallery(
-        gallery_info.device_id,
-        gallery_info.path,
-        MediaGalleryPrefInfo::kAutoDetected,
-        gallery_info.volume_label,
-        gallery_info.vendor_name,
-        gallery_info.model_name,
-        gallery_info.total_size_in_bytes,
-        gallery_info.last_attach_time,
-        0, 0, 0);
+        gallery_info.device_id, gallery_info.path,
+        MediaGalleryPrefInfo::kAutoDetected, gallery_info.volume_label,
+        gallery_info.vendor_name, gallery_info.model_name,
+        gallery_info.total_size_in_bytes, gallery_info.last_attach_time, 0, 0,
+        0);
     if (pref_id)
       *pref_id = id;
 
@@ -210,8 +205,8 @@
 
   base::FilePath GetCommonDataDir() const {
     return test_data_dir_.AppendASCII("api_test")
-                         .AppendASCII("media_galleries")
-                         .AppendASCII("common");
+        .AppendASCII("media_galleries")
+        .AppendASCII("common");
   }
 
   int num_galleries() const {
@@ -256,15 +251,13 @@
 
     ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_));
     app_dir_ = app_dir_.AppendASCII("ppapi")
-                       .AppendASCII("tests")
-                       .AppendASCII("extensions")
-                       .AppendASCII("media_galleries")
-                       .AppendASCII("newlib");
+                   .AppendASCII("tests")
+                   .AppendASCII("extensions")
+                   .AppendASCII("media_galleries")
+                   .AppendASCII("newlib");
   }
 
-  const base::FilePath& app_dir() const {
-    return app_dir_;
-  }
+  const base::FilePath& app_dir() const { return app_dir_; }
 
  private:
   base::FilePath app_dir_;
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
similarity index 92%
rename from chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc
rename to chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
index f3a7613f..14824a6 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
@@ -151,18 +151,12 @@
     MediaGalleryPrefInfo gallery_info;
     ASSERT_FALSE(preferences->LookUpGalleryByPath(test_gallery_.GetPath(),
                                                   &gallery_info));
-    MediaGalleryPrefId id =
-        preferences->AddGallery(gallery_info.device_id,
-                                gallery_info.path,
-                                MediaGalleryPrefInfo::kAutoDetected,
-                                gallery_info.volume_label,
-                                gallery_info.vendor_name,
-                                gallery_info.model_name,
-                                gallery_info.total_size_in_bytes,
-                                gallery_info.last_attach_time,
-                                0,
-                                0,
-                                0);
+    MediaGalleryPrefId id = preferences->AddGallery(
+        gallery_info.device_id, gallery_info.path,
+        MediaGalleryPrefInfo::kAutoDetected, gallery_info.volume_label,
+        gallery_info.vendor_name, gallery_info.model_name,
+        gallery_info.total_size_in_bytes, gallery_info.last_attach_time, 0, 0,
+        0);
 
     preferences->SetGalleryPermissionForExtension(*extension_, id, true);
   }
@@ -220,10 +214,9 @@
                           kAddGalleryChangedListenerOK);
   SetupGalleryWatches();
 
-
   // Modify gallery contents; expect correct details.
-  ExtensionTestMessageListener got_correct_details(
-      kOnGalleryChangedCheckingOK, false);
+  ExtensionTestMessageListener got_correct_details(kOnGalleryChangedCheckingOK,
+                                                   false);
   ASSERT_TRUE(AddNewFileInTestGallery());
   EXPECT_TRUE(got_correct_details.WaitUntilSatisfied());
 }
@@ -287,6 +280,6 @@
   ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
                           kAddGalleryChangedListenerOK);
   // Set up a invalid gallery watch.
-  ExecuteCmdAndCheckReply(
-      kSetupWatchOnInvalidGalleryCmd, kAddGalleryWatchRequestFailed);
+  ExecuteCmdAndCheckReply(kSetupWatchOnInvalidGalleryCmd,
+                          kAddGalleryWatchRequestFailed);
 }
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
index 78495fd..dc261373 100644
--- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -223,7 +223,8 @@
     // feature forces input elements on a form to display their autofill type
     // prediction. Test will check this attribute on all the relevant input
     // elements in a form to determine if the form is ready for interaction.
-    feature_list_.InitAndEnableFeature(features::kAutofillShowTypePredictions);
+    feature_list_.InitWithFeatures({features::kAutofillShowTypePredictions},
+                                   {features::kAutofillCacheQueryResponses});
     command_line->AppendSwitch(switches::kShowAutofillTypePredictions);
     captured_sites_test_utils::TestRecipeReplayer::SetUpCommandLine(
         command_line);
diff --git a/chrome/browser/bookmarks/managed_bookmark_service_factory.cc b/chrome/browser/bookmarks/managed_bookmark_service_factory.cc
index edc8110f..9208faae 100644
--- a/chrome/browser/bookmarks/managed_bookmark_service_factory.cc
+++ b/chrome/browser/bookmarks/managed_bookmark_service_factory.cc
@@ -43,9 +43,9 @@
 }
 
 // static
-BrowserContextKeyedServiceFactory::TestingFactoryFunction
+BrowserContextKeyedServiceFactory::TestingFactory
 ManagedBookmarkServiceFactory::GetDefaultFactory() {
-  return &BuildManagedBookmarkService;
+  return base::BindRepeating(&BuildManagedBookmarkService);
 }
 
 // static
diff --git a/chrome/browser/bookmarks/managed_bookmark_service_factory.h b/chrome/browser/bookmarks/managed_bookmark_service_factory.h
index cb13b62..98bb5081 100644
--- a/chrome/browser/bookmarks/managed_bookmark_service_factory.h
+++ b/chrome/browser/bookmarks/managed_bookmark_service_factory.h
@@ -27,7 +27,7 @@
  public:
   static bookmarks::ManagedBookmarkService* GetForProfile(Profile* profile);
   static ManagedBookmarkServiceFactory* GetInstance();
-  static TestingFactoryFunction GetDefaultFactory();
+  static TestingFactory GetDefaultFactory();
 
   static std::string GetManagedBookmarksDomain(Profile* profile);
 
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc
index 6b36ee5..1f67278 100644
--- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc
+++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc
@@ -28,6 +28,11 @@
 #include "chrome/browser/browsing_data/counters/hosted_apps_counter.h"
 #endif
 
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/sync_ui_util.h"
+#endif
+
 // A helper function to display the size of cache in units of MB or higher.
 // We need this, as 1 MB is the lowest nonzero cache size displayed by the
 // counter.
@@ -45,16 +50,14 @@
     auto* signin_manager = SigninManagerFactory::GetForProfile(profile);
     return signin_manager->IsAuthenticated();
   }
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
   if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) {
-    auto* token_service =
-        ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
-    std::vector<std::string> accounts = token_service->GetAccounts();
-    bool has_valid_token = std::any_of(
-        accounts.begin(), accounts.end(), [&](std::string account_id) {
-          return !token_service->RefreshTokenHasError(account_id);
-        });
-    return has_valid_token;
+    sync_ui_util::MessageType sync_status = sync_ui_util::GetStatus(
+        profile, ProfileSyncServiceFactory::GetForProfile(profile),
+        *SigninManagerFactory::GetForProfile(profile));
+    return sync_status == sync_ui_util::SYNCED;
   }
+#endif
   return false;
 }
 
diff --git a/chrome/browser/chromeos/accessibility/dictation_chromeos.cc b/chrome/browser/chromeos/accessibility/dictation_chromeos.cc
index 13eee41..0e6d3c8 100644
--- a/chrome/browser/chromeos/accessibility/dictation_chromeos.cc
+++ b/chrome/browser/chromeos/accessibility/dictation_chromeos.cc
@@ -16,7 +16,7 @@
 #include "media/audio/sounds/sounds_manager.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
-#include "ui/base/ime/chromeos/input_method_util.cc"
+#include "ui/base/ime/chromeos/input_method_util.h"
 #include "ui/base/ime/composition_text.h"
 #include "ui/base/ime/ime_bridge.h"
 #include "ui/base/ime/ime_input_context_handler_interface.h"
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
index c0fc9b2..2b1bb40 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
@@ -111,6 +111,9 @@
     case em::DeviceInitialEnrollmentStateResponse::
         INITIAL_ENROLLMENT_MODE_ENROLLMENT_ENFORCED:
       return kDeviceStateRestoreModeReEnrollmentEnforced;
+    case em::DeviceInitialEnrollmentStateResponse::
+        INITIAL_ENROLLMENT_MODE_ZERO_TOUCH_ENFORCED:
+      return kDeviceStateRestoreModeReEnrollmentZeroTouch;
   }
 }
 
diff --git a/chrome/browser/client_hints/client_hints.cc b/chrome/browser/client_hints/client_hints.cc
index 23a3933..7c916d9 100644
--- a/chrome/browser/client_hints/client_hints.cc
+++ b/chrome/browser/client_hints/client_hints.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/client_hints/client_hints.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
@@ -21,10 +22,12 @@
 #include "components/content_settings/core/common/content_settings_utils.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/origin_util.h"
 #include "net/base/url_util.h"
 #include "net/http/http_request_headers.h"
 #include "net/nqe/effective_connection_type.h"
+#include "net/nqe/network_quality_estimator_params.h"
 #include "net/url_request/url_request.h"
 #include "services/network/public/cpp/network_quality_tracker.h"
 #include "third_party/blink/public/common/client_hints/client_hints.h"
@@ -128,6 +131,30 @@
   return "0" + result;
 }
 
+// Return the effective connection type value overridden for web APIs.
+// If no override value has been set, a null value is returned.
+base::Optional<net::EffectiveConnectionType>
+GetWebHoldbackEffectiveConnectionType() {
+  if (!base::FeatureList::IsEnabled(
+          features::kNetworkQualityEstimatorWebHoldback)) {
+    return base::nullopt;
+  }
+  std::string effective_connection_type_param =
+      base::GetFieldTrialParamValueByFeature(
+          features::kNetworkQualityEstimatorWebHoldback,
+          "web_effective_connection_type_override");
+
+  base::Optional<net::EffectiveConnectionType> effective_connection_type =
+      net::GetEffectiveConnectionTypeForName(effective_connection_type_param);
+  DCHECK(effective_connection_type_param.empty() || effective_connection_type);
+
+  if (!effective_connection_type)
+    return base::nullopt;
+  DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
+            effective_connection_type.value());
+  return effective_connection_type;
+}
+
 }  // namespace
 
 namespace client_hints {
@@ -282,20 +309,42 @@
       g_browser_process->network_quality_tracker();
 
   if (web_client_hints.IsEnabled(blink::mojom::WebClientHintsType::kRtt)) {
+    base::Optional<net::EffectiveConnectionType> web_holdback_ect =
+        GetWebHoldbackEffectiveConnectionType();
+
+    base::TimeDelta http_rtt;
+    if (web_holdback_ect.has_value()) {
+      http_rtt = net::NetworkQualityEstimatorParams::GetDefaultTypicalHttpRtt(
+          web_holdback_ect.value());
+    } else {
+      http_rtt = network_quality_tracker->GetHttpRTT();
+    }
     additional_headers->SetHeader(
         blink::kClientHintsHeaderMapping[static_cast<int>(
             blink::mojom::WebClientHintsType::kRtt)],
-        base::NumberToString(internal::RoundRtt(
-            url.host(), network_quality_tracker->GetHttpRTT())));
+        base::NumberToString(internal::RoundRtt(url.host(), http_rtt)));
   }
 
   if (web_client_hints.IsEnabled(blink::mojom::WebClientHintsType::kDownlink)) {
+    base::Optional<net::EffectiveConnectionType> web_holdback_ect =
+        GetWebHoldbackEffectiveConnectionType();
+
+    int32_t downlink_throughput_kbps;
+
+    if (web_holdback_ect.has_value()) {
+      downlink_throughput_kbps =
+          net::NetworkQualityEstimatorParams::GetDefaultTypicalDownlinkKbps(
+              web_holdback_ect.value());
+    } else {
+      downlink_throughput_kbps =
+          network_quality_tracker->GetDownstreamThroughputKbps();
+    }
+
     additional_headers->SetHeader(
         blink::kClientHintsHeaderMapping[static_cast<int>(
             blink::mojom::WebClientHintsType::kDownlink)],
-        DoubleToSpecCompliantString(internal::RoundKbpsToMbps(
-            url.host(),
-            network_quality_tracker->GetDownstreamThroughputKbps())));
+        DoubleToSpecCompliantString(
+            internal::RoundKbpsToMbps(url.host(), downlink_throughput_kbps)));
   }
 
   if (web_client_hints.IsEnabled(blink::mojom::WebClientHintsType::kEct)) {
@@ -304,8 +353,14 @@
     DCHECK_EQ(blink::kWebEffectiveConnectionTypeMappingCount,
               static_cast<size_t>(net::EFFECTIVE_CONNECTION_TYPE_LAST));
 
+    base::Optional<net::EffectiveConnectionType> web_holdback_ect =
+        GetWebHoldbackEffectiveConnectionType();
+
     int effective_connection_type =
-        static_cast<int>(network_quality_tracker->GetEffectiveConnectionType());
+        web_holdback_ect.has_value()
+            ? web_holdback_ect.value()
+            : static_cast<int>(
+                  network_quality_tracker->GetEffectiveConnectionType());
 
     additional_headers->SetHeader(
         blink::kClientHintsHeaderMapping[static_cast<int>(
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index 4c2738f..b7f089e0 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/metrics/field_trial_param_associator.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -23,6 +24,7 @@
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -262,6 +264,11 @@
                      ->IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT));
   }
 
+  void SetExpectedEffectiveConnectionType(
+      net::EffectiveConnectionType effective_connection_type) {
+    expected_ect = effective_connection_type;
+  }
+
   const GURL& accept_ch_with_lifetime_http_local_url() const {
     return accept_ch_with_lifetime_http_local_url_;
   }
@@ -523,7 +530,8 @@
     EXPECT_TRUE(IsSimilarToIntABNF(request.headers.find("rtt")->second));
     // Verify that RTT value is a multiple of 50 milliseconds.
     EXPECT_EQ(0, rtt_value % 50);
-    EXPECT_GE(3000, rtt_value);
+    EXPECT_GE(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? 3000 : 500,
+              rtt_value);
 
     double mbps_value = 0.0;
     EXPECT_TRUE(base::StringToDouble(request.headers.find("downlink")->second,
@@ -549,14 +557,27 @@
       // Effective connection type is forced to 2G using command line in these
       // tests. RTT is expected to be 1800 msec but leave some gap to account
       // for added noise and randomization.
-      EXPECT_NEAR(1800, rtt_value, 360);
+      if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
+        EXPECT_NEAR(1800, rtt_value, 360);
+      } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
+        EXPECT_NEAR(450, rtt_value, 90);
+      } else {
+        NOTREACHED();
+      }
 
       // Effective connection type is forced to 2G using command line in these
       // tests. downlink is expected to be 0.075 Mbps but leave some gap to
       // account for added noise and randomization.
-      EXPECT_NEAR(0.075, mbps_value, 0.05);
+      if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G) {
+        EXPECT_NEAR(0.075, mbps_value, 0.05);
+      } else if (expected_ect == net::EFFECTIVE_CONNECTION_TYPE_3G) {
+        EXPECT_NEAR(0.4, mbps_value, 0.1);
+      } else {
+        NOTREACHED();
+      }
 
-      EXPECT_EQ("2g", request.headers.find("ect")->second);
+      EXPECT_EQ(expected_ect == net::EFFECTIVE_CONNECTION_TYPE_2G ? "2g" : "3g",
+                request.headers.find("ect")->second);
     }
   }
 
@@ -595,6 +616,9 @@
 
   std::unique_ptr<ThirdPartyURLLoaderInterceptor> request_interceptor_;
 
+  // Set to 2G in SetUpCommandLine().
+  net::EffectiveConnectionType expected_ect = net::EFFECTIVE_CONNECTION_TYPE_2G;
+
   DISALLOW_COPY_AND_ASSIGN(ClientHintsBrowserTest);
 };
 
@@ -1418,3 +1442,75 @@
   // frame request.
   EXPECT_EQ(12u, count_client_hints_headers_seen());
 }
+
+class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {
+ public:
+  ClientHintsWebHoldbackBrowserTest() : ClientHintsBrowserTest() {
+    ConfigureHoldbackExperiment();
+  }
+
+  net::EffectiveConnectionType web_effective_connection_type_override() const {
+    return web_effective_connection_type_override_;
+  }
+
+ private:
+  void ConfigureHoldbackExperiment() {
+    base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+    const std::string kTrialName = "TrialFoo";
+    const std::string kGroupName = "GroupFoo";  // Value not used
+
+    scoped_refptr<base::FieldTrial> trial =
+        base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+
+    std::map<std::string, std::string> params;
+
+    params["web_effective_connection_type_override"] =
+        net::GetNameForEffectiveConnectionType(
+            web_effective_connection_type_override_);
+    ASSERT_TRUE(
+        base::FieldTrialParamAssociator::GetInstance()
+            ->AssociateFieldTrialParams(kTrialName, kGroupName, params));
+
+    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    feature_list->RegisterFieldTrialOverride(
+        features::kNetworkQualityEstimatorWebHoldback.name,
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+    scoped_feature_list_override_.InitWithFeatureList(std::move(feature_list));
+  }
+
+  const net::EffectiveConnectionType web_effective_connection_type_override_ =
+      net::EFFECTIVE_CONNECTION_TYPE_3G;
+
+  base::test::ScopedFeatureList scoped_feature_list_override_;
+};
+
+// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
+// and client hints return the overridden values. Verify that the client hints
+// are overridden on both main frame and subresource requests.
+IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
+                       EffectiveConnectionTypeChangeNotified) {
+  SetExpectedEffectiveConnectionType(web_effective_connection_type_override());
+
+  SetClientHintExpectationsOnMainFrame(false);
+  SetClientHintExpectationsOnSubresources(true);
+
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(embedded_test_server()->Start());
+  ui_test_utils::NavigateToURL(browser(), accept_ch_with_lifetime_url());
+  EXPECT_EQ(0u, count_client_hints_headers_seen());
+  EXPECT_EQ(0u, third_party_request_count_seen());
+  EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  SetClientHintExpectationsOnMainFrame(true);
+  SetClientHintExpectationsOnSubresources(true);
+  ui_test_utils::NavigateToURL(
+      browser(), accept_ch_without_lifetime_with_subresource_url());
+  base::RunLoop().RunUntilIdle();
+  content::FetchHistogramsFromChildProcesses();
+  SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+
+  EXPECT_EQ(12u, count_client_hints_headers_seen());
+  EXPECT_EQ(0u, third_party_request_count_seen());
+  EXPECT_EQ(0u, third_party_client_hints_count_seen());
+}
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 8e96597..8b987f6 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -238,12 +238,6 @@
     "api/language_settings_private/language_settings_private_delegate_factory.h",
     "api/management/chrome_management_api_delegate.cc",
     "api/management/chrome_management_api_delegate.h",
-    "api/media_galleries/blob_data_source_factory.cc",
-    "api/media_galleries/blob_data_source_factory.h",
-    "api/media_galleries/media_galleries_api.cc",
-    "api/media_galleries/media_galleries_api.h",
-    "api/media_galleries/media_galleries_api_util.cc",
-    "api/media_galleries/media_galleries_api_util.h",
     "api/messaging/chrome_messaging_delegate.cc",
     "api/messaging/chrome_messaging_delegate.h",
     "api/messaging/incognito_connectability.cc",
@@ -803,7 +797,6 @@
     "//chrome/common/extensions:mojo_bindings",
     "//chrome/common/extensions/api:extensions_features",
     "//chrome/common/safe_browsing:proto",
-    "//chrome/services/media_gallery_util/public/cpp",
     "//chrome/services/removable_storage_writer/public/mojom",
     "//components/app_modal",
     "//components/autofill/content/browser",
diff --git a/chrome/browser/google/google_url_tracker_factory.cc b/chrome/browser/google/google_url_tracker_factory.cc
index 76f2784..25a3461 100644
--- a/chrome/browser/google/google_url_tracker_factory.cc
+++ b/chrome/browser/google/google_url_tracker_factory.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind.h"
 #include "base/feature_list.h"
 #include "chrome/browser/google/chrome_google_url_tracker_client.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
@@ -49,9 +50,9 @@
 }  // namespace
 
 // static
-BrowserContextKeyedServiceFactory::TestingFactoryFunction
+BrowserContextKeyedServiceFactory::TestingFactory
 GoogleURLTrackerFactory::GetDefaultFactory() {
-  return &BuildGoogleURLTracker;
+  return base::BindRepeating(&BuildGoogleURLTracker);
 }
 
 GoogleURLTrackerFactory::GoogleURLTrackerFactory()
diff --git a/chrome/browser/google/google_url_tracker_factory.h b/chrome/browser/google/google_url_tracker_factory.h
index 448c557..cd71b7e3 100644
--- a/chrome/browser/google/google_url_tracker_factory.h
+++ b/chrome/browser/google/google_url_tracker_factory.h
@@ -24,7 +24,7 @@
   // Returns the default factory used to build GoogleURLTracker. Can be
   // registered with SetTestingFactory to use a real GoogleURLTracker instance
   // for testing.
-  static TestingFactoryFunction GetDefaultFactory();
+  static TestingFactory GetDefaultFactory();
 
  private:
   friend struct base::DefaultSingletonTraits<GoogleURLTrackerFactory>;
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index 5993012..ac8c8b7 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -58,7 +58,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/service_manager/sandbox/switches.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_features.h"
 
 #if !defined(OS_CHROMEOS)
 #include "chrome/browser/ui/startup/default_browser_infobar_delegate.h"
@@ -68,10 +67,6 @@
 #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h"
 #endif
 
-#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/startup/session_crashed_infobar_delegate.h"
-#endif
-
 #if !defined(USE_AURA)
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "components/translate/core/browser/translate_infobar_delegate.h"
diff --git a/chrome/browser/media/android/remote/flinging_controller_bridge.cc b/chrome/browser/media/android/remote/flinging_controller_bridge.cc
index abd04f5c..3e3154b 100644
--- a/chrome/browser/media/android/remote/flinging_controller_bridge.cc
+++ b/chrome/browser/media/android/remote/flinging_controller_bridge.cc
@@ -4,10 +4,22 @@
 
 #include "chrome/browser/media/android/remote/flinging_controller_bridge.h"
 
+#include "base/android/jni_string.h"
+#include "base/time/time.h"
 #include "jni/FlingingControllerBridge_jni.h"
+#include "jni/MediaStatusBridge_jni.h"
 
 namespace media_router {
 
+// From Android MediaStatus documentation.
+// https://developers.google.com/android/reference/com/google/android/gms/cast/MediaStatus.html
+const int PLAYER_STATE_UNKOWN = 0;
+const int PLAYER_STATE_IDLE = 1;
+const int PLAYER_STATE_PLAYING = 2;
+const int PLAYER_STATE_PAUSED = 3;
+const int PLAYER_STATE_BUFFERING = 4;
+const int IDLE_REASON_FINISHED = 1;
+
 FlingingControllerBridge::FlingingControllerBridge(
     base::android::ScopedJavaGlobalRef<jobject> controller)
     : j_flinging_controller_bridge_(controller) {}
@@ -84,7 +96,47 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& j_bridge,
     const base::android::JavaParamRef<jobject>& j_status) {
-  // TODO(tguilbert): convert j_status to media::MediaStatus.
+  if (!observer_)
+    return;
+
+  media::MediaStatus status;
+
+  int player_state = Java_MediaStatusBridge_playerState(env, j_status);
+
+  switch (player_state) {
+    case PLAYER_STATE_UNKOWN:
+      status.state = media::MediaStatus::State::UNKNOWN;
+      break;
+    case PLAYER_STATE_PLAYING:
+      status.state = media::MediaStatus::State::PLAYING;
+      break;
+    case PLAYER_STATE_PAUSED:
+      status.state = media::MediaStatus::State::PAUSED;
+      break;
+    case PLAYER_STATE_BUFFERING:
+      status.state = media::MediaStatus::State::BUFFERING;
+      break;
+    case PLAYER_STATE_IDLE:
+      status.state = media::MediaStatus::State::STOPPED;
+      int idle_reason = Java_MediaStatusBridge_idleReason(env, j_status);
+      status.reached_end_of_stream = (idle_reason == IDLE_REASON_FINISHED);
+      break;
+  }
+
+  status.title = base::android::ConvertJavaStringToUTF8(
+      env, Java_MediaStatusBridge_title(env, j_status));
+  status.can_play_pause = Java_MediaStatusBridge_canPlayPause(env, j_status);
+  status.can_mute = Java_MediaStatusBridge_canMute(env, j_status);
+  status.can_set_volume = Java_MediaStatusBridge_canSetVolume(env, j_status);
+  status.can_seek = Java_MediaStatusBridge_canSeek(env, j_status);
+  status.is_muted = Java_MediaStatusBridge_isMuted(env, j_status);
+  status.volume = Java_MediaStatusBridge_volume(env, j_status);
+  status.duration = base::TimeDelta::FromMilliseconds(
+      Java_MediaStatusBridge_duration(env, j_status));
+  status.current_time = base::TimeDelta::FromMilliseconds(
+      Java_MediaStatusBridge_currentTime(env, j_status));
+
+  observer_->OnMediaStatusUpdated(status);
 }
 
 base::TimeDelta FlingingControllerBridge::GetApproximateCurrentTime() {
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc
index 827fd482..b95f2f4 100644
--- a/chrome/browser/media/cast_mirroring_service_host.cc
+++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/media/cast_mirroring_service_host.h"
 
-#include "base/callback.h"
+#include <algorithm>
+#include <utility>
+
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
@@ -131,7 +133,7 @@
     const content::DesktopMediaID media_id =
         BuildMediaIdForWebContents(target_contents);
     mojo::MakeStrongBinding(
-        std::make_unique<mirroring::CastMirroringServiceHost>(media_id),
+        std::make_unique<CastMirroringServiceHost>(media_id),
         std::move(request));
   }
 }
@@ -152,7 +154,7 @@
             initiator_contents->GetVisibleURL().GetOrigin(),
             &original_extension_name, content::kRegistryStreamTypeDesktop);
     mojo::MakeStrongBinding(
-        std::make_unique<mirroring::CastMirroringServiceHost>(media_id),
+        std::make_unique<CastMirroringServiceHost>(media_id),
         std::move(request));
   }
 }
@@ -164,8 +166,8 @@
     const std::string& presentation_id,
     mojom::MirroringServiceHostRequest request) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-  auto host = std::make_unique<mirroring::CastMirroringServiceHost>(
-      content::DesktopMediaID());
+  auto host =
+      std::make_unique<CastMirroringServiceHost>(content::DesktopMediaID());
   host->OpenOffscreenTab(context, presentation_url, presentation_id);
   mojo::MakeStrongBinding(std::move(host), std::move(request));
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
@@ -261,7 +263,7 @@
     media::mojom::RemoterPtr remoter,
     media::mojom::RemotingSourceRequest request) {
   if (source_media_id_.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) {
-    content::WebContents* const source_contents = web_contents();
+    content::WebContents* source_contents = web_contents();
     if (source_contents) {
       CastRemotingConnector::Get(source_contents)
           ->ConnectWithMediaRemoter(std::move(remoter), std::move(request));
diff --git a/chrome/browser/media/cast_mirroring_service_host.h b/chrome/browser/media/cast_mirroring_service_host.h
index 027c464b..2a07ef3 100644
--- a/chrome/browser/media/cast_mirroring_service_host.h
+++ b/chrome/browser/media/cast_mirroring_service_host.h
@@ -5,8 +5,10 @@
 #ifndef CHROME_BROWSER_MEDIA_CAST_MIRRORING_SERVICE_HOST_H_
 #define CHROME_BROWSER_MEDIA_CAST_MIRRORING_SERVICE_HOST_H_
 
+#include <memory>
+#include <string>
+
 #include "base/macros.h"
-#include "build/build_config.h"
 #include "components/mirroring/mojom/mirroring_service.mojom.h"
 #include "components/mirroring/mojom/mirroring_service_host.mojom.h"
 #include "components/mirroring/mojom/resource_provider.mojom.h"
diff --git a/chrome/browser/net/dns_probe_runner_unittest.cc b/chrome/browser/net/dns_probe_runner_unittest.cc
index 45dcd40..dc5ab531 100644
--- a/chrome/browser/net/dns_probe_runner_unittest.cc
+++ b/chrome/browser/net/dns_probe_runner_unittest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/net/dns_probe_test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "net/dns/dns_client.h"
+#include "net/dns/dns_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::RunLoop;
diff --git a/chrome/browser/net/dns_probe_service.cc b/chrome/browser/net/dns_probe_service.cc
index 8e0021decc..3288a35 100644
--- a/chrome/browser/net/dns_probe_service.cc
+++ b/chrome/browser/net/dns_probe_service.cc
@@ -14,7 +14,7 @@
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 
 using base::FieldTrialList;
diff --git a/chrome/browser/net/dns_probe_test_util.cc b/chrome/browser/net/dns_probe_test_util.cc
index 773445c..da36830 100644
--- a/chrome/browser/net/dns_probe_test_util.cc
+++ b/chrome/browser/net/dns_probe_test_util.cc
@@ -8,7 +8,7 @@
 
 #include "chrome/browser/net/dns_probe_runner.h"
 #include "net/base/ip_address.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 
 using net::DnsClient;
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index 0336c8303..694a8ff 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -3535,6 +3535,31 @@
   EXPECT_FALSE(prompt_observer->IsSavePromptAvailable());
 }
 
+// Verify that there is no renderer kill when filling out a password on a
+// blob: URL.
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest,
+                       NoRendererKillWithBlobURLFrames) {
+  // Start from a page without a password form.
+  NavigateToFile("/password/other.html");
+
+  GURL submit_url(embedded_test_server()->GetURL("/password/done.html"));
+  std::string form_html = GeneratePasswordFormForAction(submit_url);
+  std::string navigate_to_blob_url =
+      "location.href = URL.createObjectURL(new Blob([\"" + form_html +
+      "\"], { type: 'text/html' }));";
+  NavigationObserver observer(WebContents());
+  ASSERT_TRUE(content::ExecuteScript(WebContents(), navigate_to_blob_url));
+  observer.Wait();
+
+  // Fill in the password and submit the form.  This shouldn't bring up a save
+  // password prompt and shouldn't result in a renderer kill.
+  std::string fill_and_submit =
+      "document.getElementById('password_field').value = 'random';"
+      "document.getElementById('testform').submit();";
+  ASSERT_TRUE(content::ExecuteScript(WebContents(), fill_and_submit));
+  EXPECT_FALSE(BubbleObserver(WebContents()).IsSavePromptAvailable());
+}
+
 // Test that for HTTP auth (i.e., credentials not put through web forms) the
 // password manager works even though it should be disabled on the previous
 // page.
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.cc b/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.cc
index 13814e76d..1e17467 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.cc
+++ b/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.cc
@@ -74,7 +74,7 @@
     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
   UserCloudPolicyManagerFactory* factory = GetInstance();
   // If there's a testing factory set, don't bother creating a new one.
-  if (factory->testing_factory_ != NULL)
+  if (factory->testing_factory_)
     return std::unique_ptr<UserCloudPolicyManager>();
   return factory->CreateManagerForOriginalBrowserContext(
       context, force_immediate_load, background_task_runner);
@@ -90,24 +90,23 @@
 }
 
 void UserCloudPolicyManagerFactory::RegisterTestingFactory(
-    TestingFactoryFunction factory) {
+    TestingFactory factory) {
   // Can't set a testing factory when a testing factory has already been
   // created, or after UCPMs have already been built.
   DCHECK(!testing_factory_);
   DCHECK(factory);
   DCHECK(manager_wrappers_.empty());
-  testing_factory_ = factory;
+  testing_factory_ = std::move(factory);
 }
 
 void UserCloudPolicyManagerFactory::ClearTestingFactory() {
-  testing_factory_ = NULL;
+  testing_factory_ = TestingFactory();
 }
 
 UserCloudPolicyManagerFactory::UserCloudPolicyManagerFactory()
     : BrowserContextKeyedBaseFactory(
-        "UserCloudPolicyManager",
-        BrowserContextDependencyManager::GetInstance()),
-      testing_factory_(NULL) {
+          "UserCloudPolicyManager",
+          BrowserContextDependencyManager::GetInstance()) {
   DependsOn(SchemaRegistryServiceFactory::GetInstance());
 }
 
@@ -191,19 +190,20 @@
 
 bool UserCloudPolicyManagerFactory::HasTestingFactory(
     content::BrowserContext* context) {
-  return testing_factory_ != NULL;
+  return !testing_factory_.is_null();
 }
 
 // If there's a TestingFactory set, then create a service during BrowserContext
 // initialization.
 bool UserCloudPolicyManagerFactory::ServiceIsCreatedWithBrowserContext() const {
-  return testing_factory_ != NULL;
+  return !testing_factory_.is_null();
 }
 
 void UserCloudPolicyManagerFactory::CreateServiceNow(
     content::BrowserContext* context) {
   DCHECK(testing_factory_);
-  manager_wrappers_[context] = new ManagerWrapper(testing_factory_(context));
+  manager_wrappers_[context] =
+      new ManagerWrapper(testing_factory_.Run(context));
 }
 
 }  // namespace policy
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h b/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h
index 2634889a..524e25a 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h
+++ b/chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <memory>
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
@@ -68,15 +69,15 @@
       content::BrowserContext* original_context,
       content::BrowserContext* off_the_record_context);
 
-  typedef UserCloudPolicyManager*
-      (*TestingFactoryFunction)(content::BrowserContext* context);
+  using TestingFactory = base::RepeatingCallback<UserCloudPolicyManager*(
+      content::BrowserContext* context)>;
 
   // Allows testing code to inject UserCloudPolicyManager objects for tests.
   // The factory function will be invoked for every Profile created. Because
   // this class does not free the UserCloudPolicyManager objects it manages,
   // it is up to the tests themselves to free the objects after the profile is
   // shut down.
-  void RegisterTestingFactory(TestingFactoryFunction factory);
+  void RegisterTestingFactory(TestingFactory factory);
   void ClearTestingFactory();
 
  private:
@@ -111,7 +112,7 @@
   typedef std::map<content::BrowserContext*, ManagerWrapper*> ManagerWrapperMap;
 
   ManagerWrapperMap manager_wrappers_;
-  TestingFactoryFunction testing_factory_;
+  TestingFactory testing_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerFactory);
 };
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 0d64cfc..47b4520 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
@@ -169,7 +170,7 @@
     // instances) so we have to inject our testing factory via a special
     // API before creating the profile.
     UserCloudPolicyManagerFactory::GetInstance()->RegisterTestingFactory(
-        BuildCloudPolicyManager);
+        base::BindRepeating(&BuildCloudPolicyManager));
     TestingProfile::Builder builder;
     builder.SetPrefService(
         std::unique_ptr<sync_preferences::PrefServiceSyncable>(
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index df749362..bc61fad5 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/policy/javascript_policy_handler.h"
 #include "chrome/browser/policy/managed_bookmarks_policy_handler.h"
 #include "chrome/browser/policy/network_prediction_policy_handler.h"
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
 #include "chrome/browser/profiles/force_safe_search_policy_handler.h"
 #include "chrome/browser/profiles/force_youtube_safety_mode_policy_handler.h"
 #include "chrome/browser/profiles/guest_mode_policy_handler.h"
@@ -994,6 +995,8 @@
       SCHEMA_STRICT,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
+  handlers->AddHandler(
+      std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema));
 
 // On most platforms, there is a legacy policy
 // kUnsafelyTreatInsecureOriginAsSecure which has been replaced by
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
new file mode 100644
index 0000000..a68ee11
--- /dev/null
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
@@ -0,0 +1,130 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/policy/core/browser/policy_error_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_value_map.h"
+
+namespace policy {
+
+namespace {
+
+constexpr char kDevicesKey[] = "devices";
+constexpr char kVendorIdKey[] = "vendor_id";
+constexpr char kProductIdKey[] = "product_id";
+constexpr char kErrorPathTemplate[] = "items[%d].devices.items[%d]";
+constexpr char kInvalidUnsignedShortIntErrorTemplate[] =
+    "The %s must be an unsigned short integer";
+constexpr char kMissingVendorIdError[] = "A vendor_id must also be specified";
+
+}  // namespace
+
+WebUsbAllowDevicesForUrlsPolicyHandler::WebUsbAllowDevicesForUrlsPolicyHandler(
+    Schema schema)
+    : SchemaValidatingPolicyHandler(
+          key::kWebUsbAllowDevicesForUrls,
+          schema.GetKnownProperty(key::kWebUsbAllowDevicesForUrls),
+          SchemaOnErrorStrategy::SCHEMA_STRICT) {}
+
+WebUsbAllowDevicesForUrlsPolicyHandler::
+    ~WebUsbAllowDevicesForUrlsPolicyHandler() {}
+
+bool WebUsbAllowDevicesForUrlsPolicyHandler::CheckPolicySettings(
+    const PolicyMap& policies,
+    PolicyErrorMap* errors) {
+  const base::Value* value = policies.GetValue(policy_name());
+  if (!value)
+    return true;
+
+  bool result =
+      SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors);
+
+  std::string error_path;
+  std::string error;
+  if (result) {
+    // The vendor and product ID descriptors of a USB devices should be
+    // unsigned short integers.
+    int item_index = 0;
+    int device_index = 0;
+    for (const auto& item : value->GetList()) {
+      DCHECK(item.FindKey(kDevicesKey));
+
+      for (const auto& device : item.FindKey(kDevicesKey)->GetList()) {
+        if (device.FindKey(kVendorIdKey)) {
+          DCHECK(device.FindKey(kVendorIdKey)->is_int());
+
+          const int vendor_id = device.FindKey(kVendorIdKey)->GetInt();
+          if (vendor_id > 0xFFFF || vendor_id < 0) {
+            error_path = base::StringPrintf(kErrorPathTemplate, item_index,
+                                            device_index);
+            error = base::StringPrintf(kInvalidUnsignedShortIntErrorTemplate,
+                                       kVendorIdKey);
+            result = false;
+            break;
+          }
+        }
+
+        if (device.FindKey(kProductIdKey)) {
+          // If a |product_id| is specified, then a |vendor_id| must also be
+          // specified. Otherwise, the device policy is invalid.
+          if (device.FindKey(kVendorIdKey)) {
+            DCHECK(device.FindKey(kProductIdKey)->is_int());
+
+            const int product_id = device.FindKey(kProductIdKey)->GetInt();
+            if (product_id > 0xFFFF || product_id < 0) {
+              error_path = base::StringPrintf(kErrorPathTemplate, item_index,
+                                              device_index);
+              error = base::StringPrintf(kInvalidUnsignedShortIntErrorTemplate,
+                                         kProductIdKey);
+              result = false;
+              break;
+            }
+          } else {
+            error_path = base::StringPrintf(kErrorPathTemplate, item_index,
+                                            device_index);
+            error = kMissingVendorIdError;
+            result = false;
+            break;
+          }
+        }
+        ++device_index;
+      }
+
+      if (!error_path.empty() || error.empty())
+        break;
+
+      ++item_index;
+    }
+
+    if (errors && !error.empty()) {
+      if (error_path.empty())
+        error_path = "(ROOT)";
+      errors->AddError(policy_name(), error_path, error);
+    }
+  }
+
+  return result;
+}
+
+void WebUsbAllowDevicesForUrlsPolicyHandler::ApplyPolicySettings(
+    const PolicyMap& policies,
+    PrefValueMap* prefs) {
+  std::unique_ptr<base::Value> value;
+  if (!CheckAndGetValue(policies, nullptr, &value))
+    return;
+
+  if (!value || !value->is_list())
+    return;
+
+  prefs->SetValue(prefs::kManagedWebUsbAllowDevicesForUrls, std::move(value));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
new file mode 100644
index 0000000..9580c4c
--- /dev/null
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
+#define CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
+
+#include "base/macros.h"
+#include "components/policy/core/browser/configuration_policy_handler.h"
+
+class PrefValueMap;
+
+namespace policy {
+
+class PolicyMap;
+
+// Handles the WebUsbAllowDevicesForUrls policy.
+class WebUsbAllowDevicesForUrlsPolicyHandler
+    : public SchemaValidatingPolicyHandler {
+ public:
+  explicit WebUsbAllowDevicesForUrlsPolicyHandler(Schema schema);
+  ~WebUsbAllowDevicesForUrlsPolicyHandler() override;
+
+  // ConfigurationPolicyHandler implementation:
+  bool CheckPolicySettings(const PolicyMap& policies,
+                           PolicyErrorMap* error) override;
+  void ApplyPolicySettings(const PolicyMap& policies,
+                           PrefValueMap* prefs) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebUsbAllowDevicesForUrlsPolicyHandler);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
new file mode 100644
index 0000000..53d0693
--- /dev/null
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
@@ -0,0 +1,539 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
+
+#include <memory>
+
+#include "base/json/json_reader.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/policy/core/browser/configuration_policy_pref_store.h"
+#include "components/policy/core/browser/configuration_policy_pref_store_test.h"
+#include "components/policy/core/browser/policy_error_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/core/common/schema.h"
+#include "components/policy/policy_constants.h"
+
+namespace policy {
+
+namespace {
+
+const char kDevicesKey[] = "devices";
+const char kUrlPatternsKey[] = "url_patterns";
+const char kVendorIdKey[] = "vendor_id";
+const char kProductIdKey[] = "product_id";
+const char kValidPolicy[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    // Ensure that a device can have both IDs.
+    "      {"
+    "        \"vendor_id\": 1234,"
+    "        \"product_id\": 5678"
+    // Ensure that a device can have only a
+    // |vendor_id|.
+    "      }, {"
+    "        \"vendor_id\": 4321"
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }, {"
+    // Ensure that a device can have neither IDs.
+    "    \"devices\": [{ }],"
+    "    \"url_patterns\": [\"[*.]crbug.com\"]"
+    "  }"
+    "]";
+// An invalid entry invalidates the entire policy.
+const char kInvalidPolicyInvalidTopLevelEntry[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"vendor_id\": 1234,"
+    "        \"product_id\": 5678"
+    "      }, {"
+    "        \"vendor_id\": 4321"
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }, {"
+    "    \"url_patterns\": [\"[*.]crbug.com\"]"
+    "  }"
+    "]";
+// A list item must have both |devices| and
+// |url_patterns| specified.
+const char kInvalidPolicyMissingDevicesProperty[] =
+    "["
+    "  {"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }"
+    "]";
+const char kInvalidPolicyMissingUrlPatternsProperty[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"vendor_id\": 1234,"
+    "        \"product_id\": 5678"
+    "      }"
+    "    ]"
+    "  }"
+    "]";
+// The |vendor_id| and |product_id| values should fit into an unsigned short.
+const char kInvalidPolicyMismatchedVendorIdType[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"vendor_id\": 70000,"
+    "        \"product_id\": 5678"
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }"
+    "]";
+const char kInvalidPolicyMismatchedProductIdType[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"vendor_id\": 1234,"
+    "        \"product_id\": 70000"
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }"
+    "]";
+// Unknown properties invalidate the policy.
+const char kInvalidPolicyUnknownProperty[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"vendor_id\": 1234,"
+    "        \"product_id\": 5678,"
+    "        \"serialNumber\": \"1234ABCD\""
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }"
+    "]";
+// A device containing a |product_id| must also have a |vendor_id|.
+const char kInvalidPolicyProductIdWithoutVendorId[] =
+    "["
+    "  {"
+    "    \"devices\": ["
+    "      {"
+    "        \"product_id\": 5678"
+    "      }"
+    "    ],"
+    "    \"url_patterns\": ["
+    "      \"[*.]google.com\","
+    "      \"youtube.com\""
+    "    ]"
+    "  }"
+    "]";
+
+}  // namespace
+
+class WebUsbAllowDevicesForUrlsPolicyHandlerTest
+    : public ConfigurationPolicyPrefStoreTest {
+ public:
+  WebUsbAllowDevicesForUrlsPolicyHandler* handler() { return handler_; }
+
+ private:
+  void SetUp() override {
+    Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
+    auto handler =
+        std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema);
+    handler_ = handler.get();
+    handler_list_.AddHandler(std::move(handler));
+  }
+
+  WebUsbAllowDevicesForUrlsPolicyHandler* handler_;
+};
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, CheckPolicySettings) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kValidPolicy), nullptr);
+  ASSERT_TRUE(errors.empty());
+  EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_TRUE(errors.empty());
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithInvalidTopLevelEntry) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[1]\": Missing or invalid required "
+      "property: devices");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithMissingDevicesProperty) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMissingDevicesProperty), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0]\": Missing or invalid required "
+      "property: devices");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithMissingUrlPatternsProperty) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMissingUrlPatternsProperty),
+      nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0]\": Missing or invalid required "
+      "property: url_patterns");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsUnknownProperty) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyUnknownProperty), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0].devices.items[0]\": Unknown "
+      "property: serialNumber");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithMismatchedVendorIdType) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMismatchedVendorIdType), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0].devices.items[0]\": The vendor_id "
+      "must be an unsigned short integer");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithMismatchedProductIdType) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMismatchedProductIdType), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0].devices.items[0]\": The "
+      "product_id must be an unsigned short integer");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       CheckPolicySettingsWithProductIdWithoutVendorId) {
+  PolicyMap policy;
+  PolicyErrorMap errors;
+
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+
+  ASSERT_TRUE(errors.empty());
+  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_FALSE(errors.empty());
+  ASSERT_EQ(errors.size(), 1ul);
+
+  const base::string16 kExpected = base::ASCIIToUTF16(
+      "Schema validation error at \"items[0].devices.items[0]\": A vendor_id "
+      "must also be specified");
+  EXPECT_EQ(errors.GetErrors(key::kWebUsbAllowDevicesForUrls), kExpected);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettings) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kValidPolicy), nullptr);
+  UpdateProviderPolicy(policy);
+
+  const base::Value* pref_value = nullptr;
+  EXPECT_TRUE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  ASSERT_TRUE(pref_value);
+  ASSERT_TRUE(pref_value->is_list());
+
+  // Ensure that the kManagedWebUsbAllowDevicesForUrls pref is set correctly.
+  const base::Value::ListStorage& list = pref_value->GetList();
+  ASSERT_EQ(list.size(), 2ul);
+
+  // Check the first item's devices list.
+  const base::Value* devices = list[0].FindKey(kDevicesKey);
+  ASSERT_TRUE(devices);
+
+  const base::Value::ListStorage& first_devices_list = devices->GetList();
+  ASSERT_EQ(first_devices_list.size(), 2ul);
+
+  const base::Value* vendor_id = first_devices_list[0].FindKey(kVendorIdKey);
+  ASSERT_TRUE(vendor_id);
+  EXPECT_EQ(vendor_id->GetInt(), 1234);
+
+  const base::Value* product_id = first_devices_list[0].FindKey(kProductIdKey);
+  ASSERT_TRUE(product_id);
+  EXPECT_EQ(product_id->GetInt(), 5678);
+
+  vendor_id = first_devices_list[1].FindKey(kVendorIdKey);
+  ASSERT_TRUE(vendor_id);
+  EXPECT_EQ(vendor_id->GetInt(), 4321);
+
+  product_id = first_devices_list[1].FindKey(kProductIdKey);
+  EXPECT_FALSE(product_id);
+
+  // Check the first item's url_patterns list.
+  const base::Value* url_patterns = list[0].FindKey(kUrlPatternsKey);
+  ASSERT_TRUE(url_patterns);
+
+  const base::Value::ListStorage& first_url_patterns_list =
+      url_patterns->GetList();
+  ASSERT_EQ(first_url_patterns_list.size(), 2ul);
+  ASSERT_TRUE(first_url_patterns_list[0].is_string());
+  ASSERT_TRUE(first_url_patterns_list[1].is_string());
+  EXPECT_EQ(first_url_patterns_list[0].GetString(), "[*.]google.com");
+  EXPECT_EQ(first_url_patterns_list[1].GetString(), "youtube.com");
+
+  // Check the second item's devices list.
+  devices = list[1].FindKey(kDevicesKey);
+  ASSERT_TRUE(devices);
+
+  const base::Value::ListStorage& second_devices_list = devices->GetList();
+  ASSERT_EQ(second_devices_list.size(), 1ul);
+
+  vendor_id = second_devices_list[0].FindKey(kVendorIdKey);
+  EXPECT_FALSE(vendor_id);
+
+  product_id = second_devices_list[0].FindKey(kProductIdKey);
+  EXPECT_FALSE(product_id);
+
+  // Check the second item's url_patterns list.
+  url_patterns = list[1].FindKey(kUrlPatternsKey);
+  ASSERT_TRUE(url_patterns);
+
+  const base::Value::ListStorage& second_url_patterns_list =
+      url_patterns->GetList();
+  ASSERT_EQ(second_url_patterns_list.size(), 1ul);
+  ASSERT_TRUE(second_url_patterns_list[0].is_string());
+  EXPECT_EQ(second_url_patterns_list[0].GetString(), "[*.]crbug.com");
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithInvalidTopLevelEntry) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+  UpdateProviderPolicy(policy);
+
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithMissingDevicesProperty) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMissingDevicesProperty), nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithMissingUrlPatternsProperty) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMissingUrlPatternsProperty),
+      nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithUnknownProperty) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyUnknownProperty), nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithMismatchedVendorIdType) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMismatchedVendorIdType), nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsWithMismatchedProductIdType) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyMismatchedProductIdType), nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+       ApplyPolicySettingsProductIdWithoutVendorId) {
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+
+  PolicyMap policy;
+  policy.Set(
+      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+      base::JSONReader::Read(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+  UpdateProviderPolicy(policy);
+  const base::Value* pref_value = nullptr;
+  EXPECT_FALSE(
+      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(pref_value);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/prefs/OWNERS b/chrome/browser/prefs/OWNERS
index c4c2187..7f75ebc 100644
--- a/chrome/browser/prefs/OWNERS
+++ b/chrome/browser/prefs/OWNERS
@@ -1,6 +1,5 @@
 battre@chromium.org
 gab@chromium.org
-pam@chromium.org
 
 per-file pref_service_incognito_whitelist.cc=rhalavati@chromium.org
 
diff --git a/chrome/browser/previews/previews_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
index 5893136..36b760f 100644
--- a/chrome/browser/previews/previews_infobar_delegate_unittest.cc
+++ b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
@@ -61,7 +61,7 @@
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/web_contents_tester.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
@@ -186,7 +186,7 @@
     data_reduction_proxy_settings->InitDataReductionProxySettings(
         drp_test_context_->io_data(), drp_test_context_->pref_service(),
         drp_test_context_->request_context_getter(),
-        nullptr /* url_loader_factory */,
+        base::MakeRefCounted<network::TestSharedURLLoaderFactory>(),
         base::WrapUnique(new data_reduction_proxy::DataStore()),
         base::ThreadTaskRunnerHandle::Get(),
         base::ThreadTaskRunnerHandle::Get());
diff --git a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
index 3876c39..a82e3f54e 100644
--- a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
+++ b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
@@ -37,7 +37,7 @@
 #include "content/public/common/previews_state.h"
 #include "content/public/test/web_contents_tester.h"
 #include "net/http/http_util.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
 
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
 #include "chrome/browser/offline_pages/offline_page_tab_helper.h"
@@ -81,7 +81,7 @@
     data_reduction_proxy_settings->InitDataReductionProxySettings(
         drp_test_context_->io_data(), drp_test_context_->pref_service(),
         drp_test_context_->request_context_getter(),
-        nullptr /* url_loader_factory */,
+        base::MakeRefCounted<network::TestSharedURLLoaderFactory>(),
         base::WrapUnique(new data_reduction_proxy::DataStore()),
         base::ThreadTaskRunnerHandle::Get(),
         base::ThreadTaskRunnerHandle::Get());
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
index ad5fef1d..d83c432 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
@@ -1416,6 +1416,39 @@
   CheckClientDownloadReportCorruptArchive(DMG);
 }
 
+TEST_F(DownloadProtectionServiceTest, CheckClientDownloadReportValidDmg) {
+  PrepareResponse(ClientDownloadResponse::SAFE, net::HTTP_OK,
+                  net::URLRequestStatus::SUCCESS);
+
+  base::FilePath test_dmg;
+  EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dmg));
+  test_dmg = test_dmg.AppendASCII("safe_browsing")
+                 .AppendASCII("mach_o")
+                 .AppendASCII("signed-archive.dmg");
+
+  NiceMockDownloadItem item;
+  PrepareBasicDownloadItemWithFullPaths(
+      &item, {"http://www.evil.com/a.dmg"},                     // url_chain
+      "http://www.google.com/",                                 // referrer
+      test_dmg,                                                 // tmp_path
+      temp_dir_.GetPath().Append(FILE_PATH_LITERAL("a.dmg")));  // final_path
+
+  RunLoop run_loop;
+  download_service_->CheckClientDownload(
+      &item,
+      base::BindRepeating(&DownloadProtectionServiceTest::CheckDoneCallback,
+                          base::Unretained(this), run_loop.QuitClosure()));
+  run_loop.Run();
+
+  ASSERT_TRUE(HasClientDownloadRequest());
+  EXPECT_TRUE(GetClientDownloadRequest()->archive_valid());
+
+  ClearClientDownloadRequest();
+
+  Mock::VerifyAndClearExpectations(sb_service_.get());
+  Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
+}
+
 // Tests that signatures get recorded and uploaded for signed DMGs.
 TEST_F(DownloadProtectionServiceTest,
        CheckClientDownloadReportDmgWithSignature) {
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
index 2ac593f..1361ac6 100644
--- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
@@ -51,8 +51,7 @@
 
 namespace {
 
-// A BrowserContextKeyedServiceFactory::TestingFactoryFunction that creates a
-// HistoryService for a TestingProfile.
+// A testing factory that creates a HistoryService for a TestingProfile.
 std::unique_ptr<KeyedService> BuildHistoryService(
     content::BrowserContext* context) {
   TestingProfile* profile = static_cast<TestingProfile*>(context);
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index f17acca..7852db5a 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -56,8 +56,8 @@
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/consent_auditor/consent_auditor.h"
 #include "components/dom_distiller/core/dom_distiller_service.h"
-#include "components/history/core/browser/history_model_worker.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/sync/history_model_worker.h"
 #include "components/invalidation/impl/invalidation_switches.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/password_manager/core/browser/password_model_worker.h"
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index 9f19613..cbe9721 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -496,51 +496,13 @@
   // Make sure the card is in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
-
-  // Turn off sync, the card should be gone.
-  GetSyncService(0)->RequestStop(syncer::SyncService::CLEAR_DATA);
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
-
-  ASSERT_EQ(0uL, pdm->GetCreditCards().size());
-
-  // Turn sync on again, the card should come back.
-  GetSyncService(0)->RequestStart();
-  // RequestStop(CLEAR_DATA) also clears the "first setup complete" flag, so
-  // set it again.
-  GetSyncService(0)->SetFirstSetupComplete();
-  // Wait until Sync restores the card and it arrives at PDM.
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
-
-  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
-}
-
-// Wallet data should get cleared from the database when sync is (temporarily)
-// stopped, e.g. due to the Sync feature toggle in Android settings.
-IN_PROC_BROWSER_TEST_P(SingleClientWalletSyncTest, ClearOnStopSync) {
-  InitWithDefaultFeatures();
-  GetFakeServer()->SetWalletData(
-      {CreateDefaultSyncWalletAddress(), CreateDefaultSyncWalletCard()});
-  ASSERT_TRUE(SetupSync());
-
-  // Make sure the card is in the DB.
-  autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
-  ASSERT_NE(nullptr, pdm);
   std::vector<CreditCard*> cards = pdm->GetCreditCards();
   ASSERT_EQ(1uL, cards.size());
 
   // Turn off sync, the card should be gone.
-  GetSyncService(0)->RequestStop(syncer::SyncService::KEEP_DATA);
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
-
-  ASSERT_EQ(0uL, pdm->GetCreditCards().size());
-
-  // Turn sync on again, the card should come back.
-  GetSyncService(0)->RequestStart();
-  // Wait until Sync restores the card and it arrives at PDM.
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
-
-  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_TRUE(GetClient(0)->DisableSyncForAllDatatypes());
+  cards = pdm->GetCreditCards();
+  ASSERT_EQ(0uL, cards.size());
 }
 
 // ChromeOS does not sign out, so the test below does not apply.
@@ -559,7 +521,6 @@
 
   // Turn off sync, the card should be gone.
   GetClient(0)->SignOutPrimaryAccount();
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
 
   ASSERT_EQ(0uL, pdm->GetCreditCards().size());
 }
@@ -675,8 +636,6 @@
 
   // Turn off autofill sync, the card should be gone.
   ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL));
-  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
-
   cards = pdm->GetCreditCards();
   ASSERT_EQ(0uL, cards.size());
 }
diff --git a/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc b/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
index 6eb0bb51..f39f62f 100644
--- a/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/sync/test/integration/sessions_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/webui_url_constants.h"
-#include "components/autofill/core/common/autofill_prefs.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/sync/base/sync_prefs.h"
 #include "components/sync/engine/polling_constants.h"
@@ -78,39 +77,18 @@
 
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
-  // Disable syncing of AUTOFILL_WALLET_DATA: That type is special-cased to
-  // clear its data even with KEEP_DATA, which means we'd always send a regular
-  // GetUpdates request on starting Sync again, and so we'd have no need for a
-  // poll.
-  GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL);
-  GetClient(1)->DisableSyncForDatatype(syncer::AUTOFILL);
-  // TODO(crbug.com/890737): Once AUTOFILL_WALLET_DATA gets properly disabled
-  // based on the pref, we can just disable that instead of all of AUTOFILL:
-  // autofill::prefs::SetPaymentsIntegrationEnabled(GetProfile(0)->GetPrefs(),
-  //                                                false);
-  // autofill::prefs::SetPaymentsIntegrationEnabled(GetProfile(1)->GetPrefs(),
-  //                                                false);
-
   // Phase 1.
   ASSERT_TRUE(CheckInitialState(0));
   ASSERT_TRUE(CheckInitialState(1));
   ASSERT_TRUE(OpenTab(0, GURL(chrome::kChromeUIHistoryURL)));
   GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1));
 
-  ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(
-      syncer::AUTOFILL_WALLET_DATA));
-  ASSERT_FALSE(GetSyncService(1)->GetActiveDataTypes().Has(
-      syncer::AUTOFILL_WALLET_DATA));
-
   // Phase 2.
   // Disconnect client 1 from sync and write another change from client 0.
   // Disconnnect the remote client from the invalidation service.
   DisableNotificationsForClient(1);
   // Make sure no extra sync cycles get triggered by test infrastructure.
   StopConfigurationRefresher();
-  // Note: It's important to specify KEEP_DATA here - if we CLEAR_DATA, then
-  // we'll do a regular GetUpdates at the next startup, so there'd be no need
-  // for a poll.
   GetClient(1)->StopSyncService(syncer::SyncService::KEEP_DATA);
 
   ASSERT_TRUE(OpenTab(0, GURL(kURL1)));
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 3cf5bda..8d42b00 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -146,7 +146,6 @@
       # See crbug.com/590850
       "content_settings/content_setting_media_menu_model.cc",
       "content_settings/content_setting_media_menu_model.h",
-      "proximity_auth/proximity_auth_error_bubble_stub.cc",
     ]
   }
 
@@ -1942,12 +1941,7 @@
       "webui/signin/sync_confirmation_ui.h",
       "webui/signin/user_manager_screen_handler.cc",
       "webui/signin/user_manager_screen_handler.h",
-      "webui/welcome/nux_helper.cc",
-      "webui/welcome/nux_helper.h",
-      "webui/welcome/welcome_handler.cc",
-      "webui/welcome/welcome_handler.h",
-      "webui/welcome/welcome_ui.cc",
-      "webui/welcome/welcome_ui.h",
+
       # TODO(scottchen): nux/set_as_default_handler is here because it depends
       #     on settings_default_browser_handler, but that deps currently can't
       #     be added in nux/BUILD.gn due to circular dependency.
@@ -1955,6 +1949,12 @@
       #     a shareable location (e.g. ui/webui/settings/BUILD.gn).
       "webui/welcome/nux/set_as_default_handler.cc",
       "webui/welcome/nux/set_as_default_handler.h",
+      "webui/welcome/nux_helper.cc",
+      "webui/welcome/nux_helper.h",
+      "webui/welcome/welcome_handler.cc",
+      "webui/welcome/welcome_handler.h",
+      "webui/welcome/welcome_ui.cc",
+      "webui/welcome/welcome_ui.h",
     ]
 
     # TODO(scottchen): Remove if-check once nux files are non-exclusive
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 0204245b..441f8473 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2640,15 +2640,16 @@
   CheckDisplayModeMQ(ASCIIToUTF16("fullscreen"), app_contents);
 }
 
+#if defined(OS_MACOSX)
+// The size computation on popups is wrong in MacViews, https://crbug.com/834908
+#define MAYBE_TestPopupBounds DISABLED_TestPopupBounds
+#else
+#define MAYBE_TestPopupBounds TestPopupBounds
+#endif
+
 // Test to ensure the bounds of popup, devtool, and app windows are properly
 // restored.
-IN_PROC_BROWSER_TEST_F(BrowserTest, TestPopupBounds) {
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
-  // The size computation on popups is wrong in MacViews:
-  // https://crbug.com/834908.
-  if (!views_mode_controller::IsViewsBrowserCocoa())
-    return;
-#endif
+IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_TestPopupBounds) {
   // TODO(tdanderson|pkasting): Change this to verify that the contents bounds
   // set by params.initial_bounds are the same as the contents bounds in the
   // initialized window. See crbug.com/585856.
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
index 921a178..c7e7737 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
@@ -108,18 +108,6 @@
   [selector displayForWebContents:contents clientCerts:std::move(client_certs)];
 }
 
-#if !BUILDFLAG(MAC_VIEWS_BROWSER)
-void ShowSSLClientCertificateSelector(
-    content::WebContents* contents,
-    net::SSLCertRequestInfo* cert_request_info,
-    net::ClientCertIdentityList client_certs,
-    std::unique_ptr<content::ClientCertificateDelegate> delegate) {
-  return ShowSSLClientCertificateSelectorCocoa(contents, cert_request_info,
-                                               std::move(client_certs),
-                                               std::move(delegate));
-}
-#endif
-
 }  // namespace chrome
 
 namespace {
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc
index 6a047d6..c32fcb2 100644
--- a/chrome/browser/ui/content_settings/content_setting_image_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -726,9 +726,6 @@
 
 gfx::Image ContentSettingImageModel::GetIcon(SkColor icon_color) const {
   int icon_size = GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
-#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER)
-  icon_size = gfx::kFaviconSize;
-#endif
   return gfx::Image(gfx::CreateVectorIconWithBadge(*icon_, icon_size,
                                                    icon_color, *icon_badge_));
 }
diff --git a/chrome/browser/ui/prefs/OWNERS b/chrome/browser/ui/prefs/OWNERS
index 03760ae..4f94811 100644
--- a/chrome/browser/ui/prefs/OWNERS
+++ b/chrome/browser/ui/prefs/OWNERS
@@ -1,4 +1,3 @@
 battre@chromium.org
-pam@chromium.org
 
 # COMPONENT: UI>Browser>Preferences
diff --git a/chrome/browser/ui/proximity_auth/proximity_auth_error_bubble_stub.cc b/chrome/browser/ui/proximity_auth/proximity_auth_error_bubble_stub.cc
deleted file mode 100644
index 1bd02ff4..0000000
--- a/chrome/browser/ui/proximity_auth/proximity_auth_error_bubble_stub.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h"
-
-#include "base/logging.h"
-#include "ui/base/ui_features.h"
-
-#if !BUILDFLAG(MAC_VIEWS_BROWSER)
-void ShowProximityAuthErrorBubble(const base::string16& message,
-                                  const gfx::Range& link_range,
-                                  const GURL& link_url,
-                                  const gfx::Rect& anchor_rect,
-                                  content::WebContents* web_contents) {
-  NOTIMPLEMENTED();
-}
-
-void HideProximityAuthErrorBubble() {
-  NOTIMPLEMENTED();
-}
-#endif
diff --git a/chrome/browser/ui/views/frame/OWNERS b/chrome/browser/ui/views/frame/OWNERS
index a03d7983..ceae6b94 100644
--- a/chrome/browser/ui/views/frame/OWNERS
+++ b/chrome/browser/ui/views/frame/OWNERS
@@ -5,5 +5,6 @@
 per-file immersive_mode_controller*=pkotwicz@chromium.org
 per-file *x11*=thomasanderson@chromium.org
 per-file desktop_linux_browser_frame_view*=thomasanderson@chromium.org
+per-file top_controls_slide_controller*=afakhry@chromium.org
 
 # COMPONENT: UI>Browser
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index a9bf0ff..6ab12e73 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -55,6 +55,7 @@
 #include "ui/base/layout.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/display/screen.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/scoped_canvas.h"
@@ -471,6 +472,80 @@
   }
 }
 
+bool BrowserNonClientFrameViewAsh::OnMousePressed(const ui::MouseEvent& event) {
+  if (!features::IsUsingWindowService())
+    return false;
+
+  if (event.IsOnlyLeftMouseButton()) {
+    if (event.flags() & ui::EF_IS_DOUBLE_CLICK) {
+      ash_window_manager_->MaximizeWindowByCaptionClick(
+          GetServerWindowId(), ui::mojom::PointerKind::MOUSE);
+    }
+
+    // Return true for single clicks to receive subsequent drag events.
+    return true;
+  }
+
+  return false;
+}
+
+bool BrowserNonClientFrameViewAsh::OnMouseDragged(const ui::MouseEvent& event) {
+  if (!features::IsUsingWindowService())
+    return false;
+
+  // The client may receive multiple drag events before Ash has taken over the
+  // window move. In this case, ignore the extras.
+  if (performing_window_move_)
+    return true;
+
+  aura::WindowTreeHostMus* window_tree_host_mus =
+      static_cast<aura::WindowTreeHostMus*>(
+          GetWidget()->GetNativeWindow()->GetHost());
+  performing_window_move_ = true;
+  window_tree_host_mus->PerformWindowMove(
+      ws::mojom::MoveLoopSource::MOUSE,
+      display::Screen::GetScreen()->GetCursorScreenPoint(),
+      base::BindRepeating(&BrowserNonClientFrameViewAsh::OnWindowMoveDone,
+                          weak_ptr_factory_.GetWeakPtr()));
+  return true;
+}
+
+void BrowserNonClientFrameViewAsh::OnMouseReleased(
+    const ui::MouseEvent& event) {
+  // If a window move has already been triggered and OnMouseReleased() is
+  // called, it means the mouse was released before the Ash asserted mouse
+  // capture, and the move should be cancelled. Note that if something else
+  // grabs mouse capture right after PerformWindowMove(), Ash may re-assert that
+  // capture instead of cancelling the move.
+  if (performing_window_move_) {
+    aura::WindowTreeHostMus* window_tree_host_mus =
+        static_cast<aura::WindowTreeHostMus*>(
+            GetWidget()->GetNativeWindow()->GetHost());
+    window_tree_host_mus->CancelWindowMove();
+  }
+}
+
+void BrowserNonClientFrameViewAsh::OnGestureEvent(ui::GestureEvent* event) {
+  if (!features::IsUsingWindowService())
+    return;
+
+  switch (event->type()) {
+    case ui::ET_GESTURE_TAP:
+      if (event->details().tap_count() == 2) {
+        // TODO(estade): need to log TouchUMA for GESTURE_MAXIMIZE_DOUBLETAP and
+        // GESTURE_FRAMEVIEW_TAP, as in WorkspaceEventHandler.
+        ash_window_manager_->MaximizeWindowByCaptionClick(
+            GetServerWindowId(), ui::mojom::PointerKind::TOUCH);
+        event->StopPropagation();
+      }
+      break;
+
+    // TODO(estade): handle gestures that trigger drags.
+    default:
+      break;
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // ash::BrowserFrameHeaderAsh::AppearanceProvider:
 
@@ -877,6 +952,10 @@
   return GetFrameWindow()->GetProperty(ash::kIsShowingInOverviewKey);
 }
 
+void BrowserNonClientFrameViewAsh::OnWindowMoveDone(bool success) {
+  performing_window_move_ = false;
+}
+
 const aura::Window* BrowserNonClientFrameViewAsh::GetFrameWindow() const {
   return const_cast<BrowserNonClientFrameViewAsh*>(this)->GetFrameWindow();
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index a238d122..9774913a 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -11,6 +11,7 @@
 #include "ash/public/interfaces/split_view.mojom.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/command_observer.h"
 #include "chrome/browser/ui/ash/tablet_mode_client_observer.h"
@@ -87,6 +88,10 @@
   gfx::Size GetMinimumSize() const override;
   void OnThemeChanged() override;
   void ChildPreferredSizeChanged(views::View* child) override;
+  bool OnMousePressed(const ui::MouseEvent& event) override;
+  bool OnMouseDragged(const ui::MouseEvent& event) override;
+  void OnMouseReleased(const ui::MouseEvent& event) override;
+  void OnGestureEvent(ui::GestureEvent* event) override;
 
   // BrowserFrameHeaderAsh::AppearanceProvider:
   SkColor GetTitleColor() override;
@@ -216,6 +221,8 @@
   // Returns whether this window is currently in the overview list.
   bool IsInOverviewMode() const;
 
+  void OnWindowMoveDone(bool success);
+
   // Returns the top level aura::Window for this browser window.
   const aura::Window* GetFrameWindow() const;
   aura::Window* GetFrameWindow();
@@ -254,6 +261,8 @@
 
   ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
 
+  bool performing_window_move_ = false;
+
   // Maintains the current split view state.
   ash::mojom::SplitViewState split_view_state_ =
       ash::mojom::SplitViewState::NO_SNAP;
@@ -261,6 +270,8 @@
   // Only used in mash.
   ash::mojom::AshWindowManagerAssociatedPtr ash_window_manager_;
 
+  base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh);
 };
 
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller.h b/chrome/browser/ui/views/frame/top_controls_slide_controller.h
index dfa72ed..e243e65 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller.h
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller.h
@@ -52,6 +52,9 @@
   // changed state.
   virtual void SetTopControlsGestureScrollInProgress(bool in_progress) = 0;
 
+  // Returns true while gesture scrolls are in progress.
+  virtual bool IsTopControlsGestureScrollInProgress() const = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(TopControlsSlideController);
 };
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
index c1b0b08..dfd23d4 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.cc
@@ -163,9 +163,9 @@
   float shown_ratio() const { return shown_ratio_; }
   bool shrink_renderer_size() const { return shrink_renderer_size_; }
 
-  void SetShownRatio(float ratio, bool sliding_in_progress) {
+  void SetShownRatio(float ratio, bool sliding_or_scrolling_in_progress) {
     shown_ratio_ = ratio;
-    if (!sliding_in_progress)
+    if (!sliding_or_scrolling_in_progress)
       UpdateDoBrowserControlsShrinkRendererSize();
   }
 
@@ -248,8 +248,8 @@
 
   // Indicates whether the renderer's viewport size should be shrunk by the
   // height of the browser's top controls. This value should only be updated at
-  // the end of sliding, and should never change while sliding is in progress.
-  // https://crbug.com/885223.
+  // the end of sliding, and should never change while sliding or scrolling are
+  // in progress. https://crbug.com/885223.
   bool shrink_renderer_size_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(TopControlsSlideTabObserver);
@@ -303,7 +303,22 @@
   // Make sure the value tracked per tab is always updated even when sliding is
   // disabled, so that we're always synchronized with the renderer.
   DCHECK(observed_tabs_.count(contents));
-  observed_tabs_[contents]->SetShownRatio(ratio, is_sliding_in_progress_);
+
+  // Note that there are two small windows of intervals between:
+  // 1- When |is_gesture_scrolling_in_progress_| is set to true (i.e. received
+  //    ET_GESTURE_SCROLL_BEGIN) and when |is_sliding_in_progress_| is set to
+  //    true (i.e. top-chrome actually starts moving), and
+  // 2- When |is_gesture_scrolling_in_progress_| is set to false (i.e.
+  //    ET_GESTURE_SCROLL_END was received) and when |is_sliding_in_progress_|
+  //    is set to false (i.e. top-chrome stopped moving) which can happen as the
+  //    renderer continues to animate top-chrome towards fully-shown or
+  //    fully-hidden after the user had lifted their fingers while the
+  //    shown_ratio is still a fractional value.
+  // Even during those two small windows, the
+  // `DoBrowserControlsShrinkRendererSize` bit should remain unchanged from its
+  // current value until sliding reaches a steady state.
+  observed_tabs_[contents]->SetShownRatio(
+      ratio, is_gesture_scrolling_in_progress_ || is_sliding_in_progress_);
 
   if (!IsEnabled()) {
     // However, if sliding is disabled, we don't update |shown_ratio_|, which is
@@ -369,6 +384,11 @@
   Refresh();
 }
 
+bool TopControlsSlideControllerChromeOS::IsTopControlsGestureScrollInProgress()
+    const {
+  return is_gesture_scrolling_in_progress_;
+}
+
 void TopControlsSlideControllerChromeOS::OnTabletModeToggled(
     bool tablet_mode_enabled) {
   OnEnabledStateChanged(tablet_mode_enabled && !browser_view_->IsFullscreen());
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h
index 0c0b11b..ff1a1262 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h
@@ -51,6 +51,7 @@
   bool DoBrowserControlsShrinkRendererSize(
       const content::WebContents* contents) const override;
   void SetTopControlsGestureScrollInProgress(bool in_progress) override;
+  bool IsTopControlsGestureScrollInProgress() const override;
 
   // TabletModeClientObserver:
   void OnTabletModeToggled(bool tablet_mode_enabled) override;
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
index c104d14..9cb880a 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -54,11 +54,24 @@
                                         const gfx::Point& start_point,
                                         const gfx::Point& end_point) {
   DCHECK(generator);
-  generator->GestureScrollSequence(
+  generator->GestureScrollSequenceWithCallback(
       start_point, end_point,
       generator->CalculateScrollDurationForFlingVelocity(
           start_point, end_point, 100 /* velocity */, 2 /* steps */),
-      2 /* steps */);
+      2 /* steps */,
+      base::BindRepeating([](ui::EventType, const gfx::Vector2dF&) {
+        // Give the event a chance to propagate to renderer before sending the
+        // next one.
+        base::RunLoop().RunUntilIdle();
+      }));
+}
+
+// Checks that the translation part of the two given transforms are equal.
+void CompareTranslations(const gfx::Transform& t1, const gfx::Transform& t2) {
+  const gfx::Vector2dF t1_translation = t1.To2dTranslation();
+  const gfx::Vector2dF t2_translation = t2.To2dTranslation();
+  EXPECT_FLOAT_EQ(t1_translation.x(), t2_translation.x());
+  EXPECT_FLOAT_EQ(t1_translation.y(), t2_translation.y());
 }
 
 // Waits for the first non-empty paint for a given WebContents. To be able to
@@ -87,7 +100,8 @@
   DISALLOW_COPY_AND_ASSIGN(TabNonEmptyPaintWaiter);
 };
 
-// Waits for a given browser top controls shown ratio on a given browser window.
+// Waits for a given terminal value (1.f or 0.f) of the browser top controls
+// shown ratio on a given browser window.
 class TopControlsShownRatioWaiter {
  public:
   explicit TopControlsShownRatioWaiter(
@@ -95,6 +109,10 @@
       : controller_(controller) {}
 
   void WaitForRatio(float ratio) {
+    DCHECK(ratio == 1.f || ratio == 0.f) << "Should only be used to wait for "
+                                            "terminal values of the shown "
+                                            "ratio.";
+
     waiting_for_shown_ratio_ = ratio;
     if (CheckRatio())
       return;
@@ -105,7 +123,11 @@
 
  private:
   bool CheckRatio() {
-    if (cc::MathUtil::IsWithinEpsilon(controller_->GetShownRatio(),
+    // To avoid flakes, we also check that gesture scrolling is not in progress
+    // which means for a terminal value of the shown ratio (that we're waiting
+    // for) sliding is also not in progress and we reached a steady state.
+    if (!controller_->IsTopControlsGestureScrollInProgress() &&
+        cc::MathUtil::IsWithinEpsilon(controller_->GetShownRatio(),
                                       waiting_for_shown_ratio_)) {
       if (run_loop_)
         run_loop_->Quit();
@@ -272,15 +294,76 @@
     }
   }
 
- private:
-  void CompareTranslations(const gfx::Transform& t1,
-                           const gfx::Transform& t2) const {
-    const gfx::Vector2dF t1_translation = t1.To2dTranslation();
-    const gfx::Vector2dF t2_translation = t2.To2dTranslation();
-    EXPECT_FLOAT_EQ(t1_translation.x(), t2_translation.x());
-    EXPECT_FLOAT_EQ(t1_translation.y(), t2_translation.y());
+  // This is used as a callback of type |ScrollStepCallback| of the function
+  // EventGenerator::GestureScrollSequenceWithCallback() that will be called at
+  // the scroll steps of ET_GESTURE_SCROLL_BEGIN, ET_GESTURE_SCROLL_UPDATE, and
+  // ET_GESTURE_SCROLL_END.
+  //
+  // It verifies the state of the browser window when the active page is being
+  // scrolled by touch gestures in such a way that will result in the top
+  // controls shown ratio becoming a fractional value (i.e. sliding top-chrome
+  // is in progress).
+  // The |expected_shrink_renderer_size| will be checked against the
+  // `DoBrowserControlsShrinkRendererSize` bit while sliding.
+  // |out_seen_fractional_shown_ratio| will be set to true if a fractional value
+  // of the shown_ratio has been seen.
+  // |event_type| and |delta| are callback parameters of |ScrollStepCallback|.
+  void CheckIntermediateScrollStep(bool expected_shrink_renderer_size,
+                                   bool* out_seen_fractional_shown_ratio,
+                                   ui::EventType event_type,
+                                   const gfx::Vector2dF& delta) {
+    // Give the event a chance to propagate to renderer before sending the
+    // next one.
+    base::RunLoop().RunUntilIdle();
+
+    if (event_type != ui::ET_GESTURE_SCROLL_UPDATE)
+      return;
+
+    const float shown_ratio = top_controls_slide_controller()->GetShownRatio();
+    if (shown_ratio == 1.f || shown_ratio == 0.f) {
+      // Test only intermediate values.
+      return;
+    }
+
+    *out_seen_fractional_shown_ratio = true;
+
+    const int top_controls_height = browser_view()->GetTopControlsHeight();
+    EXPECT_NE(top_controls_height, 0);
+
+    ui::Layer* root_view_layer =
+        browser_view()->frame()->GetRootView()->layer();
+
+    // While sliding is in progress, the root view paints to a layer.
+    ASSERT_TRUE(root_view_layer);
+
+    // This will be called repeatedly while scrolling is in progress. The
+    // `DoBrowserControlsShrinkRendererSize` bit should remain the same as the
+    // expected value.
+    EXPECT_EQ(expected_shrink_renderer_size,
+              browser_view()->DoBrowserControlsShrinkRendererSize(
+                  browser_view()->GetActiveWebContents()));
+
+    // Check intermediate transforms.
+    gfx::Transform expected_transform;
+    const float y_translation = top_controls_height * (shown_ratio - 1.f);
+    expected_transform.Translate(0, y_translation);
+
+    ASSERT_TRUE(browser_view()
+                    ->contents_web_view()
+                    ->holder()
+                    ->GetNativeViewContainer());
+    ui::Layer* contents_container_layer = browser_view()
+                                              ->contents_web_view()
+                                              ->holder()
+                                              ->GetNativeViewContainer()
+                                              ->layer();
+    ASSERT_TRUE(contents_container_layer);
+    CompareTranslations(expected_transform,
+                        contents_container_layer->transform());
+    CompareTranslations(expected_transform, root_view_layer->transform());
   }
 
+ private:
   base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(TopControlsSlideControllerTest);
@@ -801,4 +884,73 @@
   CheckBrowserLayout(browser_view(), TopChromeShownState::kFullyHidden);
 }
 
+IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest,
+                       TestIntermediateSliding) {
+  ToggleTabletMode();
+  ASSERT_TRUE(GetTabletModeEnabled());
+  EXPECT_TRUE(top_controls_slide_controller()->IsEnabled());
+  EXPECT_FLOAT_EQ(top_controls_slide_controller()->GetShownRatio(), 1.f);
+
+  // Navigate to our test page that has a long vertical content which we can use
+  // to test page scrolling.
+  OpenUrlAtIndex(embedded_test_server()->GetURL("/top_controls_scroll.html"),
+                 0);
+  EXPECT_TRUE(browser_view()->DoBrowserControlsShrinkRendererSize(
+      browser_view()->GetActiveWebContents()));
+
+  aura::Window* browser_window = browser()->window()->GetNativeWindow();
+  ui::test::EventGenerator event_generator(browser_window->GetRootWindow(),
+                                           browser_window);
+  const gfx::Point start_point = event_generator.current_location();
+  const gfx::Point end_point = start_point + gfx::Vector2d(0, -100);
+
+  // Large number of ET_GESTURE_SCROLL_UPDATE steps that we can see fractional
+  // shown ratios while scrolling is in progress.
+  const int scroll_steps = 1000;
+  const base::TimeDelta scroll_step_delay =
+      event_generator.CalculateScrollDurationForFlingVelocity(
+          start_point, end_point, 1000 /* velocity */, scroll_steps);
+
+  // We need to verify that a fractional value of the shown ratio has been seen,
+  // otherwise the test is useless, since we want to verify the state while
+  // sliding in in progress.
+  bool seen_fractional_shown_ratio = false;
+
+  // We will start scrolling while top-chrome is fully shown, in which case the
+  // `DoBrowserControlsShrinkRendererSize` bit is true. It should remain true
+  // while sliding is in progress.
+  bool expected_shrink_renderer_size = true;
+  event_generator.GestureScrollSequenceWithCallback(
+      start_point, end_point, scroll_step_delay, scroll_steps,
+      base::BindRepeating(
+          &TopControlsSlideControllerTest::CheckIntermediateScrollStep,
+          base::Unretained(this), expected_shrink_renderer_size,
+          &seen_fractional_shown_ratio));
+  EXPECT_TRUE(seen_fractional_shown_ratio);
+  TopControlsShownRatioWaiter waiter(top_controls_slide_controller());
+  waiter.WaitForRatio(0.f);
+  EXPECT_FLOAT_EQ(top_controls_slide_controller()->GetShownRatio(), 0);
+  CheckBrowserLayout(browser_view(), TopChromeShownState::kFullyHidden);
+
+  // Now that sliding ended, and top-chrome is fully hidden, the
+  // `DoBrowserControlsShrinkRendererSize` bit should be false ...
+  EXPECT_FALSE(browser_view()->DoBrowserControlsShrinkRendererSize(
+      browser_view()->GetActiveWebContents()));
+
+  // ... and when scrolling in the other direction towards a fully shown
+  // top-chrome, it should remain false while sliding is in progress.
+  expected_shrink_renderer_size = false;
+  seen_fractional_shown_ratio = false;
+  event_generator.GestureScrollSequenceWithCallback(
+      end_point, start_point, scroll_step_delay, scroll_steps,
+      base::BindRepeating(
+          &TopControlsSlideControllerTest::CheckIntermediateScrollStep,
+          base::Unretained(this), expected_shrink_renderer_size,
+          &seen_fractional_shown_ratio));
+  EXPECT_TRUE(seen_fractional_shown_ratio);
+  waiter.WaitForRatio(1.f);
+  EXPECT_FLOAT_EQ(top_controls_slide_controller()->GetShownRatio(), 1.f);
+  CheckBrowserLayout(browser_view(), TopChromeShownState::kFullyShown);
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
index 62113e1..acaa3ac 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -11,18 +11,14 @@
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/zoom/zoom_controller.h"
 #include "extensions/browser/extension_zoom_request_client.h"
 #include "extensions/common/extension_builder.h"
-#include "ui/base/ui_features.h"
 #include "ui/views/test/test_widget_observer.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
-#endif
-
 #if defined(OS_CHROMEOS)
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
diff --git a/chrome/browser/ui/views/passwords/password_bubble_interactive_uitest.cc b/chrome/browser/ui/views/passwords/password_bubble_interactive_uitest.cc
index 2031e19..53e950d 100644
--- a/chrome/browser/ui/views/passwords/password_bubble_interactive_uitest.cc
+++ b/chrome/browser/ui/views/passwords/password_bubble_interactive_uitest.cc
@@ -31,7 +31,6 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "ui/base/ui_features.h"
 #include "ui/views/window/dialog_client_view.h"
 
 using net::test_server::BasicHttpResponse;
@@ -380,12 +379,5 @@
   ui_test_utils::BrowserActivationWaiter waiter(browser());
   waiter.WaitForActivation();
 
-// Sign-in dialogs opened for inactive browser windows do not auto-close on
-// MacOS. This matches existing Cocoa bubble behavior.
-// TODO(varkha): Remove the limitation as part of http://crbug/671916 .
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   EXPECT_FALSE(IsBubbleShowing());
-#else
-  EXPECT_TRUE(IsBubbleShowing());
-#endif
 }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
index baff434..28940f0 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/browser/ui/user_manager.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/profiles/user_manager_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/common/chrome_paths.h"
@@ -45,10 +46,6 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/webview/webview.h"
 
-#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#endif
-
 namespace {
 
 Profile* CreateTestingProfile(const base::FilePath& path) {
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 c09a674..1261f6ff 100644
--- a/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/constrained_web_dialog_ui_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "build/buildflag.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -24,7 +23,6 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
-#include "ui/base/ui_features.h"
 #include "ui/web_dialogs/test/test_web_dialog_delegate.h"
 
 using content::WebContents;
@@ -198,11 +196,6 @@
   gfx::Size max_size = gfx::Size(200, 200);
   gfx::Size initial_dialog_size;
 
-// When using Cocoa windows, the initial dimensions must be nonzero.
-#if defined(OS_MACOSX) && !BUILDFLAG(MAC_VIEWS_BROWSER)
-  initial_dialog_size = gfx::Size(1, 1);
-#endif
-
   delegate->GetDialogSize(&initial_dialog_size);
 
   ConstrainedWebDialogDelegate* dialog_delegate =
diff --git a/chrome/browser/vr/browser_renderer.cc b/chrome/browser/vr/browser_renderer.cc
index e81b8c6..cd9fcc76 100644
--- a/chrome/browser/vr/browser_renderer.cc
+++ b/chrome/browser/vr/browser_renderer.cc
@@ -256,6 +256,19 @@
   frame_buffer_dump_filepath_base_ = filepath_base;
 }
 
+void BrowserRenderer::WatchElementForVisibilityChangeForTesting(
+    VisibilityChangeExpectation visibility_expectation) {
+  DCHECK(ui_visibility_state_ == nullptr) << "Attempted to watch a UI element "
+                                             "for visibility changes with one "
+                                             "in progress";
+  ui_visibility_state_ = std::make_unique<UiVisibilityState>();
+  ui_visibility_state_->timeout_ms =
+      base::TimeDelta::FromMilliseconds(visibility_expectation.timeout_ms);
+  ui_visibility_state_->element_to_watch = visibility_expectation.element_name;
+  ui_visibility_state_->initially_visible = ui_->GetElementVisibilityForTesting(
+      ui_visibility_state_->element_to_watch);
+}
+
 void BrowserRenderer::AcceptDoffPromptForTesting() {
   ui_->AcceptDoffPromptForTesting();
 }
@@ -283,6 +296,7 @@
     ui_updated = true;
   }
   ReportUiStatusForTesting(timing_start, ui_updated);
+  ReportElementVisibilityStatusForTesting(timing_start);
 
   base::TimeDelta scene_time = base::TimeTicks::Now() - timing_start;
   // Don't double-count the controller time that was part of the scene time.
@@ -374,16 +388,16 @@
     if (time_since_start > ui_test_state_->quiescence_timeout_ms) {
       // The UI is being updated, but hasn't reached a stable state in the
       // given time -> report timeout.
-      ReportUiActivityResultForTesting(VrUiTestActivityResult::kTimeoutNoEnd);
+      ReportUiActivityResultForTesting(UiTestOperationResult::kTimeoutNoEnd);
     }
   } else {
     if (ui_test_state_->activity_started) {
       // The UI has been updated since the test requested notification of
       // quiescence, but wasn't this frame -> report that the UI is quiescent.
-      ReportUiActivityResultForTesting(VrUiTestActivityResult::kQuiescent);
+      ReportUiActivityResultForTesting(UiTestOperationResult::kQuiescent);
     } else if (time_since_start > ui_test_state_->quiescence_timeout_ms) {
       // The UI has never been updated and we've reached the timeout.
-      ReportUiActivityResultForTesting(VrUiTestActivityResult::kTimeoutNoStart);
+      ReportUiActivityResultForTesting(UiTestOperationResult::kTimeoutNoStart);
     }
   }
 }
@@ -393,7 +407,7 @@
 }
 
 void BrowserRenderer::ReportUiActivityResultForTesting(
-    VrUiTestActivityResult result) {
+    UiTestOperationResult result) {
   ui_test_state_ = nullptr;
   browser_->ReportUiOperationResultForTesting(
       UiTestOperationType::kUiActivityResult, result);
@@ -406,7 +420,31 @@
   frame_buffer_dump_filepath_base_.clear();
   browser_->ReportUiOperationResultForTesting(
       UiTestOperationType::kFrameBufferDumped,
-      VrUiTestActivityResult::kQuiescent /* unused */);
+      UiTestOperationResult::kQuiescent /* unused */);
+}
+
+void BrowserRenderer::ReportElementVisibilityStatusForTesting(
+    const base::TimeTicks& current_time) {
+  if (ui_visibility_state_ == nullptr)
+    return;
+  base::TimeDelta time_since_start =
+      current_time - ui_visibility_state_->start_time;
+  if (ui_->GetElementVisibilityForTesting(
+          ui_visibility_state_->element_to_watch) !=
+      ui_visibility_state_->initially_visible) {
+    ReportElementVisibilityResultForTesting(
+        UiTestOperationResult::kVisibilityChange);
+  } else if (time_since_start > ui_visibility_state_->timeout_ms) {
+    ReportElementVisibilityResultForTesting(
+        UiTestOperationResult::kTimeoutNoChange);
+  }
+}
+
+void BrowserRenderer::ReportElementVisibilityResultForTesting(
+    UiTestOperationResult result) {
+  ui_visibility_state_ = nullptr;
+  browser_->ReportUiOperationResultForTesting(
+      UiTestOperationType::kElementVisibilityChange, result);
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/browser_renderer.h b/chrome/browser/vr/browser_renderer.h
index a53539d..ab3bafc 100644
--- a/chrome/browser/vr/browser_renderer.h
+++ b/chrome/browser/vr/browser_renderer.h
@@ -24,7 +24,7 @@
 
 namespace vr {
 
-enum class VrUiTestActivityResult;
+enum class UiTestOperationResult;
 class BrowserUiInterface;
 class InputDelegate;
 class PlatformInputHandler;
@@ -35,7 +35,9 @@
 struct ControllerTestInput;
 struct RenderInfo;
 struct UiTestActivityExpectation;
+struct VisibilityChangeExpectation;
 struct UiTestState;
+struct UiVisibilityState;
 
 // The BrowserRenderer handles all input/output activities during a frame.
 // This includes head movement, controller movement and input, audio output and
@@ -78,6 +80,8 @@
   void SetUiExpectingActivityForTesting(
       UiTestActivityExpectation ui_expectation);
   void SaveNextFrameBufferToDiskForTesting(std::string filepath_base);
+  void WatchElementForVisibilityChangeForTesting(
+      VisibilityChangeExpectation visibility_expectation);
   void AcceptDoffPromptForTesting();
   void ConnectPresentingService(
       device::mojom::VRDisplayInfoPtr display_info,
@@ -108,8 +112,11 @@
 
   void ReportUiStatusForTesting(const base::TimeTicks& current_time,
                                 bool ui_updated);
-  void ReportUiActivityResultForTesting(VrUiTestActivityResult result);
+  void ReportUiActivityResultForTesting(UiTestOperationResult result);
   void ReportFrameBufferDumpForTesting();
+  void ReportElementVisibilityStatusForTesting(
+      const base::TimeTicks& current_time);
+  void ReportElementVisibilityResultForTesting(UiTestOperationResult result);
 
   std::unique_ptr<UiInterface> ui_;
   std::unique_ptr<SchedulerDelegate> scheduler_delegate_;
@@ -124,6 +131,7 @@
   BrowserRendererBrowserInterface* browser_;
 
   std::unique_ptr<UiTestState> ui_test_state_;
+  std::unique_ptr<UiVisibilityState> ui_visibility_state_;
   SlidingTimeDeltaAverage ui_processing_time_;
   SlidingTimeDeltaAverage ui_controller_update_time_;
 
diff --git a/chrome/browser/vr/browser_renderer_browser_interface.h b/chrome/browser/vr/browser_renderer_browser_interface.h
index 8ce4826..f2103bf 100644
--- a/chrome/browser/vr/browser_renderer_browser_interface.h
+++ b/chrome/browser/vr/browser_renderer_browser_interface.h
@@ -17,7 +17,7 @@
   virtual void ForceExitVr() = 0;
   virtual void ReportUiOperationResultForTesting(
       const UiTestOperationType& action_type,
-      const VrUiTestActivityResult& result) = 0;
+      const UiTestOperationResult& result) = 0;
 };
 
 }  // namespace vr
diff --git a/chrome/browser/vr/browser_renderer_unittest.cc b/chrome/browser/vr/browser_renderer_unittest.cc
index 47bc5de..797df89 100644
--- a/chrome/browser/vr/browser_renderer_unittest.cc
+++ b/chrome/browser/vr/browser_renderer_unittest.cc
@@ -52,6 +52,7 @@
   MOCK_METHOD2(GetTargetPointForTesting,
                gfx::Point3F(UserFriendlyElementName,
                             const gfx::PointF& position));
+  MOCK_METHOD1(GetElementVisibilityForTesting, bool(UserFriendlyElementName));
   MOCK_METHOD0(IsContentVisibleAndOpaque, bool());
   MOCK_METHOD1(SetContentUsesQuadLayer, void(bool));
   gfx::Transform GetContentWorldSpaceTransform() override { return {}; }
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc
index ce47c6b..8f66e5db 100644
--- a/chrome/browser/vr/ui.cc
+++ b/chrome/browser/vr/ui.cc
@@ -67,6 +67,8 @@
       return kOverflowMenuNewIncognitoTabItem;
     case UserFriendlyElementName::kCloseIncognitoTabs:
       return kOverflowMenuCloseAllIncognitoTabsItem;
+    case UserFriendlyElementName::kExitPrompt:
+      return kExitPrompt;
     default:
       NOTREACHED();
       return kNone;
@@ -547,6 +549,13 @@
   InitializeModel(ui_initial_state);
 }
 
+bool Ui::GetElementVisibilityForTesting(UserFriendlyElementName element_name) {
+  auto* target_element = scene()->GetUiElementByName(
+      UserFriendlyElementNameToUiElementName(element_name));
+  DCHECK(target_element) << "Unsupported test element";
+  return target_element->IsVisible();
+}
+
 void Ui::InitializeModel(const UiInitialState& ui_initial_state) {
   model_->speech.has_or_can_request_audio_permission =
       ui_initial_state.has_or_can_request_audio_permission;
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h
index 9694c41d..8627fa22 100644
--- a/chrome/browser/vr/ui.h
+++ b/chrome/browser/vr/ui.h
@@ -74,6 +74,8 @@
   ContentInputDelegate* GetContentInputDelegateForTest() {
     return content_input_delegate_.get();
   }
+  bool GetElementVisibilityForTesting(
+      UserFriendlyElementName element_name) override;
 
   void Dump(bool include_bindings);
   // TODO(crbug.com/767957): Refactor to hide these behind the UI interface.
diff --git a/chrome/browser/vr/ui_interface.h b/chrome/browser/vr/ui_interface.h
index a5d8551..e30e57f5 100644
--- a/chrome/browser/vr/ui_interface.h
+++ b/chrome/browser/vr/ui_interface.h
@@ -79,6 +79,8 @@
   virtual gfx::Point3F GetTargetPointForTesting(
       UserFriendlyElementName element_name,
       const gfx::PointF& position) = 0;
+  virtual bool GetElementVisibilityForTesting(
+      UserFriendlyElementName element_name) = 0;
   virtual bool IsContentVisibleAndOpaque() = 0;
   virtual void SetContentUsesQuadLayer(bool uses_quad_buffers) = 0;
   virtual gfx::Transform GetContentWorldSpaceTransform() = 0;
diff --git a/chrome/browser/vr/ui_test_input.h b/chrome/browser/vr/ui_test_input.h
index 05171cec9..8de91465f 100644
--- a/chrome/browser/vr/ui_test_input.h
+++ b/chrome/browser/vr/ui_test_input.h
@@ -25,6 +25,7 @@
   kNewIncognitoTab,  // Button to open a new Incognito tab in the overflow menu
   kCloseIncognitoTabs,  // Button to close all Incognito tabs in the overflow
                         // menu
+  kExitPrompt,          // DOFF prompt/request to exit VR
 };
 
 // These are the types of actions that Java can request callbacks for once
@@ -33,17 +34,21 @@
 enum class UiTestOperationType : int {
   kUiActivityResult = 0,     // Result after being told to wait for quiescence
   kFrameBufferDumped,        // Signal that the frame buffer was dumped to disk
+  kElementVisibilityChange,  // Signal that a watched element changed visibility
   kNumUiTestOperationTypes,  // Must be last
 };
 
-// These are used to report the current state of the UI after performing an
-// action
+// These are used to report the result of a UI test operation.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.vr
-enum class VrUiTestActivityResult : int {
-  kUnreported,
-  kQuiescent,
-  kTimeoutNoStart,
-  kTimeoutNoEnd,
+enum class UiTestOperationResult : int {
+  kUnreported,      // The result has not yet been reported
+  kQuiescent,       // The UI reached quiescence (kUiActivityResult)
+  kTimeoutNoStart,  // Timed out, UI activity never started (kUiActivityResult)
+  kTimeoutNoEnd,    // Timed out, UI activity never finished (kUiActivityResult)
+  kVisibilityChange,  // The watched element's visibility changed
+                      // (kElementVisibilityChange)
+  kTimeoutNoChange,   // Timed out, visibility never changed
+                      // (kElementVisibilityChange)
 };
 
 // These are used to specify what type of action should be performed on a UI
@@ -71,6 +76,11 @@
   int quiescence_timeout_ms;
 };
 
+struct VisibilityChangeExpectation {
+  UserFriendlyElementName element_name;
+  int timeout_ms;
+};
+
 // Holds all the information necessary to keep track of and report whether the
 // UI reacted to test input.
 struct UiTestState {
@@ -83,6 +93,19 @@
   base::TimeTicks start_time = base::TimeTicks::Now();
 };
 
+// Holds all the information necessary to keep track of and report whether a
+// UI element changed visibility in the allotted time.
+struct UiVisibilityState {
+  // The UI element being watched.
+  UserFriendlyElementName element_to_watch = UserFriendlyElementName::kUrl;
+  // The initial visibility state of the element.
+  bool initially_visible = false;
+  // How long to wait for a visibility change before timing out.
+  base::TimeDelta timeout_ms = base::TimeDelta::Min();
+  // The point in time that we started watching for visibility changes.
+  base::TimeTicks start_time = base::TimeTicks::Now();
+};
+
 }  // namespace vr
 
 #endif  // CHROME_BROWSER_VR_UI_TEST_INPUT_H_
diff --git a/chrome/common/apps/platform_apps/api/_api_features.json b/chrome/common/apps/platform_apps/api/_api_features.json
index 5878b6e..6f710e8 100644
--- a/chrome/common/apps/platform_apps/api/_api_features.json
+++ b/chrome/common/apps/platform_apps/api/_api_features.json
@@ -15,6 +15,10 @@
     "dependencies": ["permission:easyUnlockPrivate"],
     "contexts": ["blessed_extension"]
   },
+  "mediaGalleries": {
+    "dependencies": ["permission:mediaGalleries"],
+    "contexts": ["blessed_extension"]
+  },
   "musicManagerPrivate": {
     "dependencies": ["permission:musicManagerPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/apps/platform_apps/api/_permission_features.json b/chrome/common/apps/platform_apps/api/_permission_features.json
index 1b54c437..81ffcf5 100644
--- a/chrome/common/apps/platform_apps/api/_permission_features.json
+++ b/chrome/common/apps/platform_apps/api/_permission_features.json
@@ -17,6 +17,32 @@
     "location": "component",
     "platforms": ["chromeos"]
   },
+  "mediaGalleries": {
+    "channel": "stable",
+    "extension_types": [ "platform_app" ]
+  },
+  // TODO(devlin): These all specify the same permissions. There's no need for
+  // child features.
+  "mediaGalleries.allAutoDetected": {
+    "channel": "stable",
+    "extension_types": [ "platform_app" ]
+  },
+  "mediaGalleries.scan": {
+    "channel": "dev",
+    "extension_types": [ "platform_app" ]
+  },
+  "mediaGalleries.read": {
+    "channel": "stable",
+    "extension_types": [ "platform_app" ]
+  },
+  "mediaGalleries.copyTo": {
+    "channel": "stable",
+    "extension_types": [ "platform_app" ]
+  },
+  "mediaGalleries.delete": {
+    "channel": "stable",
+    "extension_types": [ "platform_app" ]
+  },
   "musicManagerPrivate": {
     "channel": "stable",
     "extension_types": ["platform_app"],
diff --git a/chrome/common/apps/platform_apps/api/api_sources.gni b/chrome/common/apps/platform_apps/api/api_sources.gni
index dd1b8472..f4ea71d 100644
--- a/chrome/common/apps/platform_apps/api/api_sources.gni
+++ b/chrome/common/apps/platform_apps/api/api_sources.gni
@@ -7,7 +7,10 @@
 
 assert(enable_extensions)
 
-chrome_apps_api_schema_files_ = [ "browser.idl" ]
+chrome_apps_api_schema_files_ = [
+  "browser.idl",
+  "media_galleries.idl",
+]
 
 if (is_chromeos) {
   chrome_apps_api_schema_files_ += [ "easy_unlock_private.idl" ]
diff --git a/chrome/common/extensions/api/media_galleries.idl b/chrome/common/apps/platform_apps/api/media_galleries.idl
similarity index 100%
rename from chrome/common/extensions/api/media_galleries.idl
rename to chrome/common/apps/platform_apps/api/media_galleries.idl
diff --git a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
index 493be62a..9380f85b 100644
--- a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
+++ b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
@@ -4,9 +4,17 @@
 
 #include "chrome/common/apps/platform_apps/chrome_apps_api_permissions.h"
 
+#include "extensions/common/permissions/media_galleries_permission.h"
+
 namespace chrome_apps_api_permissions {
 namespace {
 
+template <typename T>
+extensions::APIPermission* CreateAPIPermission(
+    const extensions::APIPermissionInfo* permission) {
+  return new T(permission);
+}
+
 // WARNING: If you are modifying a permission message in this list, be sure to
 // add the corresponding permission message rule to
 // ChromePermissionMessageProvider::GetPermissionMessages as well.
@@ -15,6 +23,9 @@
     {extensions::APIPermission::kEasyUnlockPrivate, "easyUnlockPrivate"},
     {extensions::APIPermission::kMusicManagerPrivate, "musicManagerPrivate",
      extensions::APIPermissionInfo::kFlagCannotBeOptional},
+    {extensions::APIPermission::kMediaGalleries, "mediaGalleries",
+     extensions::APIPermissionInfo::kFlagNone,
+     &CreateAPIPermission<extensions::MediaGalleriesPermission>},
 };
 
 }  // namespace
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 355496c..9a061546 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -124,7 +124,7 @@
 // accessing https://support.google.com/chrome/answer/6098869 to local
 // connection help content.
 const base::Feature kBundledConnectionHelpFeature{
-    "BundledConnectionHelp", base::FEATURE_DISABLED_BY_DEFAULT};
+    "BundledConnectionHelp", base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if defined(OS_MACOSX)
 // Enables or disables keyboard focus for the tab strip.
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index 6095648..895aa3a 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -570,10 +570,6 @@
     "channel": "stable",
     "contexts": ["blessed_extension"]
   },
-  "mediaGalleries": {
-    "dependencies": ["permission:mediaGalleries"],
-    "contexts": ["blessed_extension"]
-  },
   "mediaPlayerPrivate": {
     "dependencies": ["permission:mediaPlayerPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 010832c4..4c419358 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -515,30 +515,6 @@
       "session_types": ["kiosk"]
     }
   ],
-  "mediaGalleries": {
-    "channel": "stable",
-    "extension_types": [ "platform_app" ]
-  },
-  "mediaGalleries.allAutoDetected": {
-    "channel": "stable",
-    "extension_types": [ "platform_app" ]
-  },
-  "mediaGalleries.scan": {
-    "channel": "dev",
-    "extension_types": [ "platform_app" ]
-  },
-  "mediaGalleries.read": {
-    "channel": "stable",
-    "extension_types": [ "platform_app" ]
-  },
-  "mediaGalleries.copyTo": {
-    "channel": "stable",
-    "extension_types": [ "platform_app" ]
-  },
-  "mediaGalleries.delete": {
-    "channel": "stable",
-    "extension_types": [ "platform_app" ]
-  },
   "mediaPlayerPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni
index 97f8b43e..0e6f9be8 100644
--- a/chrome/common/extensions/api/api_sources.gni
+++ b/chrome/common/extensions/api/api_sources.gni
@@ -48,7 +48,6 @@
   "instance_id.json",
   "language_settings_private.idl",
   "manifest_types.json",
-  "media_galleries.idl",
   "notifications.idl",
   "omnibox.json",
   "page_capture.json",
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index d9bbc2f..b0398fd 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -12,7 +12,6 @@
 #include "base/memory/ptr_util.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/api_permission_set.h"
-#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permissions_info.h"
 #include "extensions/common/permissions/settings_override_permission.h"
 
@@ -205,9 +204,6 @@
     // Platform-app permissions.
 
     {APIPermission::kFileSystemProvider, "fileSystemProvider"},
-    {APIPermission::kMediaGalleries, "mediaGalleries",
-     APIPermissionInfo::kFlagNone,
-     &CreateAPIPermission<MediaGalleriesPermission>},
     {APIPermission::kPointerLock, "pointerLock"},
     {APIPermission::kCastStreaming, "cast.streaming"},
     {APIPermission::kLauncherSearchProvider, "launcherSearchProvider"},
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ae2c859..ddb534d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1203,6 +1203,8 @@
       sources += [
         "../browser/accessibility/accessibility_extension_api_browsertest.cc",
         "../browser/apps/platform_apps/api/browser/browser_apitest.cc",
+        "../browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc",
+        "../browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc",
         "../browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc",
         "../browser/apps/platform_apps/app_browsertest_util.cc",
         "../browser/apps/platform_apps/app_browsertest_util.h",
@@ -1261,8 +1263,6 @@
         "../browser/extensions/api/management/management_api_browsertest.cc",
         "../browser/extensions/api/management/management_apitest.cc",
         "../browser/extensions/api/management/management_browsertest.cc",
-        "../browser/extensions/api/media_galleries/media_galleries_apitest.cc",
-        "../browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc",
         "../browser/extensions/api/messaging/native_messaging_apitest.cc",
         "../browser/extensions/api/metrics_private/metrics_apitest.cc",
         "../browser/extensions/api/module/module_apitest.cc",
@@ -2586,6 +2586,7 @@
     "../browser/policy/javascript_policy_handler_unittest.cc",
     "../browser/policy/managed_bookmarks_policy_handler_unittest.cc",
     "../browser/policy/profile_policy_connector_unittest.cc",
+    "../browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc",
     "../browser/predictors/autocomplete_action_predictor_table_unittest.cc",
     "../browser/predictors/autocomplete_action_predictor_unittest.cc",
     "../browser/predictors/loading_data_collector_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
index 2846f6f..9e2b10e6 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -30,6 +30,7 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.DeferredStartupHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
@@ -115,6 +116,10 @@
                 // https://crbug.com/577185
                 Calendar.getInstance();
 
+                // Disable offline indicator UI to prevent it from popping up to obstruct other UI
+                // views that may make tests flaky.
+                Features.getInstance().disable(ChromeFeatureList.OFFLINE_INDICATOR);
+
                 base.evaluate();
             }
         }, description);
diff --git a/chrome/test/data/autofill/captured_sites/amazon.sha1 b/chrome/test/data/autofill/captured_sites/amazon.sha1
index a4166972..c27c5f0 100644
--- a/chrome/test/data/autofill/captured_sites/amazon.sha1
+++ b/chrome/test/data/autofill/captured_sites/amazon.sha1
@@ -1 +1 @@
-61e535c75e11548909b662d8cea3ea450121ea74
\ No newline at end of file
+cfc8a5a43fec7aab7bd3466bcc33548813d38906
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/amazon.test b/chrome/test/data/autofill/captured_sites/amazon.test
index a4459ef..2b8d893 100644
--- a/chrome/test/data/autofill/captured_sites/amazon.test
+++ b/chrome/test/data/autofill/captured_sites/amazon.test
@@ -1,6 +1,5 @@
 {
-  "name": "Amazon.com: The Path to Power (The Years of Lyndon Johnson, Volume 1) (9780679729457): Robert A. Caro: Books",
-  "startingURL": "https://www.amazon.com/Path-Power-Years-Lyndon-Johnson/dp/0679729453/ref=sr_1_1?_encoding=UTF8&ref_=nav_ya_signin&",
+  "startingURL": "https://www.amazon.com/gp/cart/view.html?ref=nav_cart",
   "autofillProfile": [
     {
       "type": "ADDRESS_HOME_CITY",
@@ -23,26 +22,22 @@
       "value": "78744"
     },
     {
-      "type": "EMAIL_ADDRESS",
-      "value": "red.swingline@initech.com"
-    },
-    {
-      "type": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
-      "value": "05"
-    },
-    {
-      "type": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
-      "value": "2027"
-    },
-    {
       "type": "CREDIT_CARD_NAME_FULL",
       "value": "Milton Waddams"
     },
     {
-      "type": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "type": "CREDIT_CARD_NUMBER",
       "value": "9621327911759602"
     },
     {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
       "type": "NAME_FULL",
       "value": "Milton C. Waddams"
     },
@@ -51,153 +46,187 @@
       "value": "5125551234"
     }
   ],
+  "passwordManagerProfiles": [],
   "actions": [
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"add-to-cart-button\"]",
+      "selector": "//input[@name=\"proceedToCheckout\"]",
+      "visibility": 3,
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "click",
+      "action_index": 1
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"hlb-ptc-btn-native\"]",
+      "url": "https://www.amazon.com/gp/buy/addressselect/handlers/display.html?hasWorkingJavascript=1",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "loadPage",
+      "action_index": 2
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"enterAddressFullName\"]",
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressFullName\"]",
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 3
     },
     {
-      "selector": "//*[@id=\"enterAddressFullName\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "NAME_FULL",
-      "expectedValue": "Milton C. Waddams",
-      "type": "validateField"
-    },
-    {
-      "selector": "//*[@id=\"enterAddressAddressLine1\"]",
-      "context": {
-        "isIframe": false
-      },
-      "expectedAutofillType": "ADDRESS_HOME_LINE1",
       "expectedValue": "4120 Freidrich Lane",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressAddressLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 4
     },
     {
-      "selector": "//*[@id=\"enterAddressAddressLine2\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_LINE2",
       "expectedValue": "Apt 8",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressAddressLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 5
     },
     {
-      "selector": "//*[@id=\"enterAddressCity\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_CITY",
       "expectedValue": "Austin",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressCity\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 6
     },
     {
-      "selector": "//*[@id=\"enterAddressStateOrRegion\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_STATE",
       "expectedValue": "Texas",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressStateOrRegion\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 7
     },
     {
-      "selector": "//*[@id=\"enterAddressPostalCode\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_ZIP",
       "expectedValue": "78744",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressPostalCode\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 8
     },
     {
-      "selector": "//*[@id=\"enterAddressPhoneNumber\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "PHONE_HOME_WHOLE_NUMBER",
       "expectedValue": "5125551234",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressPhoneNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 9
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='submit' and @value='Deliver to this address']",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @name=\"enterAddressFullName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 10
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"shippingOptionFormId\"]/div[1]/div[2]/div/span[contains(., '')]/span[contains(., '')]/input[@type='submit' and @value='Continue']",
+      "selector": "//input[@type=\"submit\"]",
+      "visibility": 3,
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "click",
+      "action_index": 11
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"ccName\"]",
+      "url": "https://www.amazon.com/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1",
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "type": "loadPage",
+      "action_index": 12
     },
     {
-      "selector": "//*[@id=\"addCreditCardNumber\"]",
+      "selector": "//form/div[3]/div/div/span[normalize-space(text())=\"\"][1]/span[normalize-space(text())=\"\"]/input[@type=\"submit\" and @data-testid]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "type": "click",
+      "action_index": 13
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"ccName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
       "expectedValue": "9621327911759602",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @id=\"addCreditCardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 15
     },
     {
-      "selector": "//*[@id=\"ccName\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
-      "expectedValue": "Milton Waddams",
-      "type": "validateField"
-    },
-    {
-      "selector": "//*[@id=\"ccMonth\"]",
-      "context": {
-        "isIframe": false
-      },
-      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
       "expectedValue": "5",
-      "type": "validateField"
+      "selector": "//select[@id=\"ccMonth\"]",
+      "type": "validateField",
+      "visibility": 2,
+      "action_index": 16
     },
     {
-      "selector": "//*[@id=\"ccYear\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
       "expectedValue": "2027",
-      "type": "validateField"
+      "selector": "//select[@id=\"ccYear\"]",
+      "type": "validateField",
+      "visibility": 2,
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"ccName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
+      "action_index": 18
     }
   ]
 }
diff --git a/chrome/test/data/autofill/captured_sites/bestbuy.sha1 b/chrome/test/data/autofill/captured_sites/bestbuy.sha1
new file mode 100644
index 0000000..0c644e2
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/bestbuy.sha1
@@ -0,0 +1 @@
+c1ea3854179193556b26641ed30a1f3de0fa3a61
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/bestbuy.test b/chrome/test/data/autofill/captured_sites/bestbuy.test
new file mode 100644
index 0000000..595662c71
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/bestbuy.test
@@ -0,0 +1,323 @@
+{
+  "startingURL": "https://www.bestbuy.com/identity/signin?token=tid%3A93cbbf86-c1f2-11e8-bafc-005056ae9ec3",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "TX"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "value": "9621 3279 1175 9602"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "512 555 1234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//a[@href=\"/identity/guest?token=tid%3A93cbbf86-c1f2-11e8-bafc-005056ae9ec3\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 1
+    },
+    {
+      "url": "https://www.bestbuy.com/checkout/r/fulfillment",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 2
+    },
+    {
+      "url": "https://www.bestbuy.com/checkout/r/fulfillment",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 1
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"consolidatedAddresses.ui_address_2.firstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"consolidatedAddresses.ui_address_2.lastName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"off\" and @maxlength=\"35\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"consolidatedAddresses.ui_address_2.street2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"consolidatedAddresses.ui_address_2.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"tel\" and @id=\"consolidatedAddresses.ui_address_2.zipcode\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @id=\"consolidatedAddresses.ui_address_2.firstName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 9
+    },
+    {
+      "selector": "//input[@id=\"user.emailAddress\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "512 555 1234",
+      "selector": "//input[@type=\"tel\" and @id=\"user.phone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@id=\"user.emailAddress\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@type=\"checkbox\" and @id=\"save-for-billing-address-ui_address_2\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 13
+    },
+    {
+      "selector": "//div/div[2]/div/button[normalize-space(text())=\"\"]/span[normalize-space(text())=\"\"]/p",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 14
+    },
+    {
+      "selector": "//div/div[2]/div/button[normalize-space(text())=\"\"]/span[normalize-space(text())=\"\"]/p",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 15
+    },
+    {
+      "selector": "//input[@type=\"tel\" and @id=\"optimized-cc-card-number\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621 3279 1175 9602",
+      "selector": "//input[@type=\"tel\" and @id=\"optimized-cc-card-number\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "action_index": 17
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"payment.billingAddress.firstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"payment.billingAddress.lastName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"off\" and @maxlength=\"35\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"payment.billingAddress.street2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 21
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"payment.billingAddress.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 23
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"tel\" and @id=\"payment.billingAddress.zipcode\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 24
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @id=\"payment.billingAddress.firstName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 25
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/etsy.sha1 b/chrome/test/data/autofill/captured_sites/etsy.sha1
new file mode 100644
index 0000000..970aa67
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/etsy.sha1
@@ -0,0 +1 @@
+db98c661d7688e8977057674ef026394f4f0919f
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/etsy.test b/chrome/test/data/autofill/captured_sites/etsy.test
new file mode 100644
index 0000000..ab12ce8
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/etsy.test
@@ -0,0 +1,206 @@
+{
+  "originalURL": "https://www.etsy.com/listing/184374778/spoon-bookmark-with-tassel-drink-tea?ref=hp_prn&ep_click=1",
+  "startingURL": "https://www.etsy.com/cart/1927887938/review",
+  "dismissBeforeUnload": true,
+  "autofillProfile": [
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL1",
+      "value": "TX"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL2",
+      "value": "Austin"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_NAME_FULL",
+      "value": "Milton Waddams"
+    },
+    {
+      "type": "HTML_TYPE_NAME",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "HTML_TYPE_POSTAL_CODE",
+      "value": "78744"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "url": "https://www.etsy.com/cart/1927887938/review",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 5
+    },
+    {
+      "selector": "//div[@id=\"address-form-email-group\"]/div/input[@value and @type=\"email\" and @aria-label=\"Email\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//div[@id=\"shipping-address-form\"]//input[@type=\"text\" and @data-field=\"name\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_NAME",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//div[@id=\"shipping-address-form\"]//input[@type=\"text\" and @data-field=\"first_line\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE1",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//div[@id=\"shipping-address-form\"]//input[@type=\"text\" and @data-field=\"second_line\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2",
+      "action_index": 9
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//div[@id=\"shipping-address-form\"]//input[@data-field=\"zip\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//div[@id=\"shipping-address-form\"]//input[@type=\"text\" and @data-field=\"city\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//div[@id=\"shipping-address-form\"]//select[@data-field=\"state\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 12
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//div[@id=\"address-form-email-group\"]/div/input[@value and @type=\"email\" and @aria-label=\"Email\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 13
+    },
+    {
+      "selector": "//div[@id=\"shipping-address-form\"]/div[2]/button[normalize-space(text())=\"\"]/span[@data-button-cta and text()=\"Continue to payment\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 14
+    },
+    {
+      "selector": "//div/div[2]/input[@type=\"tel\" and @name=\"card[number]\" and @aria-label=\"Credit card number\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5",
+      "selector": "//div[@role=\"group\"]/div/select[@name=\"card[exp_mon]\" and @aria-label=\"Credit card expiration month\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//div[@role=\"group\"]/div/select[@name=\"card[exp_year]\" and @aria-label=\"Credit card expiration year\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//div/div[3]/div[@id=\"new-cc-name-group\"]/input[@type=\"text\" and @name=\"card[name]\" and @value]",
+      "type": "validateField",
+      "visibility": 7,
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//div/div[2]/input[@type=\"tel\" and @name=\"card[number]\" and @aria-label=\"Credit card number\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "action_index": 19
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/groupon.sha1 b/chrome/test/data/autofill/captured_sites/groupon.sha1
new file mode 100644
index 0000000..f4d0c58
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/groupon.sha1
@@ -0,0 +1 @@
+389e629b42482b27b30c384531e3314d8bd530cf
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/groupon.test b/chrome/test/data/autofill/captured_sites/groupon.test
new file mode 100644
index 0000000..33d5247
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/groupon.test
@@ -0,0 +1,139 @@
+{
+  "startingURL": "https://www.groupon.com/deals/n-splash-wines-fall-wines-of-the-world/confirmation?pledge_id=80378309",
+  "autofillProfile": [
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL1",
+      "value": "TX"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL2",
+      "value": "Austin"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_EXP",
+      "value": "05/2027"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "HTML_TYPE_NAME",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "HTML_TYPE_POSTAL_CODE",
+      "value": "78744"
+    },
+    {
+      "type": "HTML_TYPE_STREET_ADDRESS",
+      "value": "4120 Freidrich Lane, Apt 8"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "url": "https://www.groupon.com/deals/n-splash-wines-fall-wines-of-the-world/confirmation?pledge_id=80378309",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 2
+    },
+    {
+      "selector": "//input[@id=\"full_name\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane, Apt 8",
+      "selector": "//input[@id=\"billing_ad\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_STREET_ADDRESS",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@id=\"cc_city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select[@id=\"cc_state\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@id=\"cc_zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@id=\"full_name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_NAME",
+      "action_index": 8
+    },
+    {
+      "selector": "//input[@id=\"cc_number\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 9
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05/2027",
+      "selector": "//input[@id=\"cc_expiration\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP",
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@id=\"cc_number\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "action_index": 13
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/home_depot.sha1 b/chrome/test/data/autofill/captured_sites/home_depot.sha1
new file mode 100644
index 0000000..d08498b
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/home_depot.sha1
@@ -0,0 +1 @@
+cbc60634578fee02cbc0560fd2abd77b28720066
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/home_depot.test b/chrome/test/data/autofill/captured_sites/home_depot.test
new file mode 100644
index 0000000..df5ac44
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/home_depot.test
@@ -0,0 +1,212 @@
+{
+  "startingURL": "https://secure2.homedepot.com/mycheckout/checkout#/checkout",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_STREET_ADDRESS",
+      "value": "4120 Freidrich Lane, Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621 3279 1175 9602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "(512) 555-1234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@type=\"text\" and @id=\"firstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"lastName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@id=\"emailInput\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "(512) 555-1234",
+      "selector": "//input[@id=\"phone\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "(512) 555-1234",
+      "selector": "//input[@id=\"phone\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane, Apt 8",
+      "selector": "//input[@id=\"shippingAddress\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STREET_ADDRESS",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@ng-if=\"item && item.isSTH && !showReadOnlyZipCode() || !user.deliveryZipCode && !showReadOnlyZipCode() && type==='shipping' || type==='billing' || type ==='newbilling'\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @id=\"firstName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 8
+    },
+    {
+      "selector": "//label[@for=\"hdCheckBox_1\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "selector": "//input[@id=\"shippingAddress\" and @aria-required=\"true\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//billing-address//input[@name=\"zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane, Apt 8",
+      "selector": "//input[@id=\"shippingAddress\" and @aria-required=\"true\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STREET_ADDRESS",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@id=\"cardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//input[@name=\"expiryYear\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621 3279 1175 9602",
+      "selector": "//input[@id=\"cardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05",
+      "selector": "//input[@name=\"expiryMonth\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "action_index": 16
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/jet.sha1 b/chrome/test/data/autofill/captured_sites/jet.sha1
new file mode 100644
index 0000000..9188b7d
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/jet.sha1
@@ -0,0 +1 @@
+eff6574b7962109ee05e626b8580668e1b445bf7
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/jet.test b/chrome/test/data/autofill/captured_sites/jet.test
new file mode 100644
index 0000000..71853ed
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/jet.test
@@ -0,0 +1,275 @@
+{
+  "startingURL": "https://jet.com/checkout",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "CREDIT_CARD_NAME_FULL",
+      "value": "Milton Waddams"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@id=\"address-first_name\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@id=\"address-last_name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@id=\"address-street_1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@id=\"address-street_2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@id=\"address-zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@id=\"address-phone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@id=\"address-first_name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 7
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 8
+    },
+    {
+      "selector": "//a[text()=\"Yes, save & continue\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "url": "https://jet.com/checkout",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 10
+    },
+    {
+      "selector": "//input[@id=\"payment-number\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//input[@id=\"payment-name\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
+      "action_index": 12
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05 / 27",
+      "selector": "//input[@id=\"payment-expiration\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR",
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@id=\"payment-number\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 14
+    },
+    {
+      "selector": "//span[text()=\"Billing address is same as shipping\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 16
+    },
+    {
+      "selector": "//input[@id=\"payment-first_name\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@id=\"payment-last_name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@id=\"payment-street_1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@id=\"payment-street_2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@id=\"payment-zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 21
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@id=\"payment-phone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@id=\"payment-first_name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 23
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/macys.sha1 b/chrome/test/data/autofill/captured_sites/macys.sha1
new file mode 100644
index 0000000..05b00f6
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/macys.sha1
@@ -0,0 +1 @@
+1328f834cf9976cdbae4c18e4ed48200d2da77f8
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/macys.test b/chrome/test/data/autofill/captured_sites/macys.test
new file mode 100644
index 0000000..696f555
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/macys.test
@@ -0,0 +1,342 @@
+{
+  "startingURL": "https://www.macys.com/chkout/rc?perfectProxy=true",
+  "autofillProfile": [
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL1",
+      "value": "TX"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL2",
+      "value": "Austin"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "HTML_TYPE_EMAIL",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "HTML_TYPE_FAMILY_NAME",
+      "value": "Waddams"
+    },
+    {
+      "type": "HTML_TYPE_GIVEN_NAME",
+      "value": "Milton"
+    },
+    {
+      "type": "HTML_TYPE_POSTAL_CODE",
+      "value": "78744"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "(512) 555-1234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@type=\"text\" and @name=\"contact.firstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @name=\"contact.lastName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_FAMILY_NAME",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @name=\"address.addressLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE1",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @name=\"address.addressLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @name=\"address.addressLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @name=\"address.addressLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"text\" and @name=\"address.phone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @name=\"contact.firstName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_GIVEN_NAME",
+      "action_index": 9
+    },
+    {
+      "selector": "//button[@type=\"submit\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 10
+    },
+    {
+      "assertions": [
+        "return automation_helper.isElementWithXpathReady(`//button[@id=\"rc-gift-card\"]`);",
+        "return automation_helper.isElementWithXpathReady(`//select[@name=\"creditCard.expMonth\"]`, automation_helper.DomElementReadyState.present);"
+      ],
+      "context": {
+        "isIframe": false
+      },
+      "type": "waitFor",
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "index": 4,
+      "selector": "//select[@name=\"creditCard.cardType.code\"]",
+      "type": "select",
+      "visibility": 7,
+      "action_index": 11
+    },
+    {
+      "selector": "//input[@type=\"text\" and @name=\"creditCard.cardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 12
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05",
+      "selector": "//select[@name=\"creditCard.expMonth\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"creditCard.expYear\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"text\" and @name=\"creditCard.cardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 15
+    },
+    {
+      "selector": "//input[@type=\"checkbox\" and @id=\"rc-use-shipping\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 16
+    },
+    {
+      "selector": "//input[@type=\"text\" and @name=\"billingContact.firstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @name=\"billingContact.lastName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_FAMILY_NAME",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @name=\"billingAddress.addressLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE1",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @name=\"billingAddress.addressLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @name=\"billingAddress.zipCode\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 21
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select[@name=\"billingAddress.state\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @name=\"billingAddress.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 23
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"text\" and @name=\"billingAddress.phone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 24
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@type=\"email\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_EMAIL",
+      "action_index": 25
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @name=\"billingContact.firstName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_GIVEN_NAME",
+      "action_index": 26
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/newegg.sha1 b/chrome/test/data/autofill/captured_sites/newegg.sha1
new file mode 100644
index 0000000..bb6854d
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/newegg.sha1
@@ -0,0 +1 @@
+125dee5046edf35883f025c2700cf30a47706993
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/newegg.test b/chrome/test/data/autofill/captured_sites/newegg.test
new file mode 100644
index 0000000..c1421e2
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/newegg.test
@@ -0,0 +1,258 @@
+{
+  "startingURL": "https://secure.newegg.com/GlobalShopping/CheckoutStep1.aspx?CartID=639%2bFRMFKUSESAKWH8A&IsCombineGuest=1",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "TX"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "CREDIT_CARD_NAME_FULL",
+      "value": "Milton Waddams"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "(512) 555-1234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@validgroup=\"g1\" and @name=\"SFirstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@validgroup=\"g1\" and @name=\"SLastName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @name=\"SAddress1\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @name=\"SAddress2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @name=\"SCity\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select[@selectstate]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@maxlength=\"20\" and @name=\"SZip\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "(512) 555-1234",
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @name=\"ShippingPhone\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//li/ul/li[4]/input[@data-msg-required=\"This field is required.\" and @data-msg-emailvalidate=\"Please enter a valid email address.\" and @maxlength=\"128\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 9
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@validgroup=\"g1\" and @name=\"SFirstName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 10
+    },
+    {
+      "selector": "//a[@href=\"javascript:Biz.GlobalShopping.CheckOut.continueToBilling();\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 11
+    },
+    {
+      "url": "https://secure.newegg.com/GlobalShopping/CheckoutStep2.aspx?CartID=335%2bFRMFKUSESAKWH8A&IsCombineGuest=1",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@type=\"checkbox\" and @id=\"billingsameaddress\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 13
+    },
+    {
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @data-msg-validateisnumeric=\"Please enter a valid cardholder name.\" and @name=\"Card_HolderNameNew\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @data-msg-validateisnumeric=\"Please enter a valid cardholder name.\" and @name=\"Card_HolderNameNew\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9 6 2 1   3 2 7 9   1 1 7 5   9 6 0 2",
+      "selector": "//input[@data-msg-required=\"This field is required.\" and @data-msg-cacreditcard=\"We are temporarily unable to accept Discover cards.\" and @id=\"Card_CCNUMBERNEW\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05",
+      "selector": "//select[@name=\"Card_exp_monthNew\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"Card_exp_yearNew\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"text\" and @name=\"GiftCode\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 19
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/pottery_barn.sha1 b/chrome/test/data/autofill/captured_sites/pottery_barn.sha1
new file mode 100644
index 0000000..57faf62
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/pottery_barn.sha1
@@ -0,0 +1 @@
+00ee205e0408f4be88dcaf2039703899f8f91b42
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/pottery_barn.test b/chrome/test/data/autofill/captured_sites/pottery_barn.test
new file mode 100644
index 0000000..86d8d67
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/pottery_barn.test
@@ -0,0 +1,338 @@
+{
+  "startingURL": "https://www.potterybarn.com/checkout/shipping.html",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "TX"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "5"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "NAME_FULL",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.city\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.zip\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 8
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "url": "https://www.potterybarn.com/checkout/deliveryoptions.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 10
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 11
+    },
+    {
+      "url": "https://www.potterybarn.com/checkout/billing.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"address.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"address.zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@type=\"email\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 20
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 21
+    },
+    {
+      "url": "https://www.potterybarn.com/checkout/payment.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "index": 2,
+      "selector": "//select[@name=\"creditCard.cardId\"]",
+      "type": "select",
+      "visibility": 3,
+      "action_index": 23
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 24
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5",
+      "selector": "//select[@name=\"creditCard.cardExpMonth\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 25
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"creditCard.cardExpYear\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 26
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 27
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/qvc.sha1 b/chrome/test/data/autofill/captured_sites/qvc.sha1
new file mode 100644
index 0000000..2eb3dd6d
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/qvc.sha1
@@ -0,0 +1 @@
+8e8a2d748fdbf465e14361fa04a91e87a82eef91
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/qvc.test b/chrome/test/data/autofill/captured_sites/qvc.test
new file mode 100644
index 0000000..900b6a7e
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/qvc.test
@@ -0,0 +1,187 @@
+{
+  "name": "QVC | Online Shopping from Anywhere | Official Site",
+  "startingURL": "https://www.qvc.com/webapp/wcs/stores/servlet/LogonForm?storeId=10251&langId=-1&catalogId=10151&krypto=FUZE9vPtg2ObxpUegC5H%2Bs3qS3FqI%2BL9dfK0%2FOmRoDrAiT6S5Gdi737fz8h%2FfJ36L99%2BzFahYk9D%0A59%2B0tE0J4T%2BZajVow28zFlmeCCrNUTMHXxOz4ZiA%2FsSrPg2IdQsRoV4AUy2a5DyutEI893UfWpRH%0AVKflo3N9HtUpd97wGHjo33jMWifHBwyGqaPD1Ho50C4yjdu2w0a79Swvgd7j601kKADZwJ97y7Df%0AMh1dOOy1Y9lXtmSe0fNOJtIP147rJ27FEHXjczIIfNU3cOYLa%2B5Ru38tFrdbAt08fYCO%2FLqFHOeI%0ASrTw%2FB5iJpbZJHNbSOygk28evEzR4AllXqDSqCSJocmozGNk%2B97Vzsk5cZCrIvYtGAA%2FkElswxtz%0A%2BexVO4CgjFnC0%2F3SFVOmzwu3Z4MduFW%2BXKlFnInAIViXcYlgkSaeNp3tLtyKvuEeoMxLKbGW2IiH%0AuqIhxUzPlHZBfmmwa4bKQwy3BQ%2FeoQ8wp0U%3D&ddkey=http%3AOrderItemDisplay",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR",
+      "value": "05/2027"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//*[@id=\"txtEmailAddress\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "type",
+      "value": "chromeguyforever@gmail.com"
+    },
+    {
+      "selector": "//span[@id=\"continueButtonSpan\"]//*[@id=\"btnSignIn\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "click"
+    },
+    {
+      "selector": "//*[@id=\"txtFirstName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "fields" : [
+        {
+          "selector": "//*[@id=\"txtEmailAddressConf\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "EMAIL_ADDRESS",
+          "expectedValue": "red.swingline@initech.com"
+        },
+        {
+          "selector": "//*[@id=\"txtFirstName\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "NAME_FIRST",
+          "expectedValue": "Milton"
+        },
+        {
+          "selector": "//*[@id=\"txtLastName\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "NAME_LAST",
+          "expectedValue": "Waddams"
+        },
+        {
+          "selector": "//*[@id=\"txtAddress1\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "ADDRESS_HOME_LINE1",
+          "expectedValue": "4120 Freidrich Lane"
+        },
+        {
+          "selector": "//*[@id=\"txtAddress2\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "ADDRESS_HOME_LINE2",
+          "expectedValue": "Apt 8"
+        },
+        {
+          "selector": "//*[@id=\"txtZipPostalCode\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "ADDRESS_HOME_ZIP",
+          "expectedValue": "78744"
+        },
+        {
+          "selector": "//*[@id=\"txtphone1\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "PHONE_HOME_WHOLE_NUMBER",
+          "expectedValue": "5125551234"
+        }
+      ]
+    },
+    {
+      "selector": "//*[@id=\"btnContinueCheckout\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "click"
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "type": "waitFor",
+      "assertions": [
+        "return automation_helper.isElementWithXpathReady(`//*[@id=\"errConsole\"]`);"
+      ]
+    },
+    {
+      "selector": "//*[@id=\"btnContinueCheckout\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "click"
+    },
+    {
+      "selector": "//*[@id=\"divButtons\"]/span[contains(., 'Continue Checkout')]/input[@type='button']",
+      "context": {
+        "isIframe": false
+      },
+      "type": "click"
+    },
+    {
+      "selector": "//*[@id=\"fldExpireDateNewCard\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "click"
+    },
+    {
+      "selector": "//*[@id=\"txtNewCardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "fields" : [
+        {
+          "selector": "//*[@id=\"txtNewCardNumber\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "CREDIT_CARD_NUMBER",
+          "expectedValue": "9621327911759602"
+        },
+        {
+          "selector": "//*[@id=\"selNewCard\"]",
+          "context": {
+        "isIframe": false
+      },
+          "expectedAutofillType": "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR",
+          "expectedValue": "05/2027"
+        }
+      ]
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/walmart.sha1 b/chrome/test/data/autofill/captured_sites/walmart.sha1
index b22d535..5ef4dfe 100644
--- a/chrome/test/data/autofill/captured_sites/walmart.sha1
+++ b/chrome/test/data/autofill/captured_sites/walmart.sha1
@@ -1 +1 @@
-404748495d4285c869c78058b55bf73c2ed0221e
\ No newline at end of file
+d043fad87b37885a6638ace58ea7db744caffcd2
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/walmart.test b/chrome/test/data/autofill/captured_sites/walmart.test
index 739e041..06de629 100644
--- a/chrome/test/data/autofill/captured_sites/walmart.test
+++ b/chrome/test/data/autofill/captured_sites/walmart.test
@@ -1,5 +1,5 @@
 {
-  "name": "Sign In",
+  "originalURL": "https://www.walmart.com/ip/Zyrtec-24-Hour-Allergy-Relief-Tablets-with-10-mg-Cetirizine-HCl-70-ct/14971994",
   "startingURL": "https://www.walmart.com/checkout/#/sign-in",
   "autofillProfile": [
     {
@@ -51,174 +51,248 @@
       "value": "5125551234"
     }
   ],
+  "passwordManagerProfiles": [],
+  "pruned_actions": [
+    {
+      "selector": "//span[text()=\"Add to Cart\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 1
+    },
+    {
+      "selector": "//button[@data-automation-id=\"pac-pos-proceed-to-checkout\" and text()=\"Check Out\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 2
+    }
+  ],
   "actions": [
     {
-      "selectorType": "xpath",
-      "selector": "//button[@data-automation-id='new-guest-continue-button']",
+      "url": "https://www.walmart.com/checkout/#/sign-in",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "loadPage",
+      "action_index": 3
     },
     {
-      "selectorType": "xpath",
-      "selector": "//button[@aria-label='Continue to Shipping Address']",
+      "selector": "//button[@type=\"button\" and @aria-label=\"Continue to checkout without an account.\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "click",
+      "action_index": 4
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='firstName']",
+      "selector": "//span[text()=\"Continue\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "type": "click",
+      "action_index": 5
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='firstName']",
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrFirstName\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "NAME_FIRST",
-      "expectedValue": "Milton",
-      "type": "validateField"
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 6
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='lastName']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "NAME_LAST",
       "expectedValue": "Waddams",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrLastName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 7
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='phone']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "PHONE_HOME_WHOLE_NUMBER",
       "expectedValue": "5125551234",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrPhone\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 8
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='email']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "EMAIL_ADDRESS",
       "expectedValue": "red.swingline@initech.com",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrEmail\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 9
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='addressLineOne']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_LINE1",
       "expectedValue": "4120 Freidrich Lane",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrAddress1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 10
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='addressLineTwo']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_LINE2",
       "expectedValue": "Apt 8",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrAddress2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 11
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='city']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_CITY",
       "expectedValue": "Austin",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrCity\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 12
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@name='state']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_STATE",
       "expectedValue": "TX",
-      "type": "validateField"
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 13
     },
     {
-      "selectorType": "xpath",
-      "selector": "//input[@type='text' and @name='postalCode']",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_ZIP",
       "expectedValue": "78744",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrZip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 14
     },
     {
-      "selectorType": "xpath",
-      "selector": "//button[contains(., 'Continue')]",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @data-tl-id=\"COAC2ShpAddrFirstName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 15
     },
     {
-      "selectorType": "xpath",
-      "selector": "//button[contains(., 'Use Address Provided')]",
+      "selector": "//label[@for=\"4\"]",
+      "visibility": 3,
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "click",
+      "action_index": 16
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"creditCard\"]",
+      "selector": "//span[text()=\"Continue\"]",
+      "visibility": 3,
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "type": "click",
+      "action_index": 17
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"creditCard\"]",
+      "selector": "//button[@type=\"button\" and @aria-disabled=\"false\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER",
-      "expectedValue": "9621327911759602",
-      "type": "validateField"
+      "type": "click",
+      "action_index": 18
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"month-chooser\"]",
+      "selector": "//span[text()=\"Continue\"]",
+      "visibility": 3,
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "type": "click",
+      "action_index": 17
+    },
+    {
+      "selector": "//button[@type=\"button\" and @aria-disabled=\"false\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 18
+    },
+    {
+      "selector": "//input[@value and @pattern=\"[0-9]*\" and @name=\"creditCard\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
       "expectedValue": "05",
-      "type": "validateField"
+      "selector": "//select[@id=\"month-chooser\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "action_index": 21
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"year-chooser\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
       "expectedValue": "2027",
-      "type": "validateField"
+      "selector": "//select[@id=\"year-chooser\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@value=\"9621327911759602\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "action_index": 23
     }
   ]
 }
diff --git a/chrome/test/data/autofill/captured_sites/wayfair.sha1 b/chrome/test/data/autofill/captured_sites/wayfair.sha1
new file mode 100644
index 0000000..3d9fb09b
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/wayfair.sha1
@@ -0,0 +1 @@
+73027b12cff676fea62d3f3d1a6929484272c88d
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/wayfair.test b/chrome/test/data/autofill/captured_sites/wayfair.test
new file mode 100644
index 0000000..27adcbe
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/wayfair.test
@@ -0,0 +1,251 @@
+{
+  "startingURL": "https://secure.wayfair.com/v/checkout/onepage/view#billing",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "5"
+    },
+    {
+      "type": "CREDIT_CARD_NAME_FULL",
+      "value": "Milton Waddams"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL1",
+      "value": "44"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL2",
+      "value": "Austin"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "HTML_TYPE_NAME",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "HTML_TYPE_POSTAL_CODE",
+      "value": "78744"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//span[text()=\"Change\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 1
+    },
+    {
+      "selector": "//div/div[2]/div/button[normalize-space(text())=\"\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 2
+    },
+    {
+      "selector": "//div[@tabindex=\"0\"]/div/div/button[normalize-space(text())=\"\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 3
+    },
+    {
+      "selector": "//input[@autocomplete=\"name\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"off\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@autocomplete=\"address-line2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@autocomplete=\"address-level2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "44",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@autocomplete=\"postal-code\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 9
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@maxlength=\"30\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@autocomplete=\"name\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_NAME",
+      "action_index": 11
+    },
+    {
+      "selector": "//button[@data-codeception-id=\"address_entry_submit\"]",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 12
+    },
+    {
+      "selector": "//div/div[2]/div/label/div",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 13
+    },
+    {
+      "selector": "//input[@type=\"tel\" and @name=\"c-cn\"]",
+      "context": {
+        "isIframe": true,
+        "browserTest": {
+          "name": "credit_card_iframe"
+        }
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": true,
+        "browserTest": {
+          "name": "credit_card_iframe"
+        }
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"tel\" and @name=\"c-cn\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": true,
+        "browserTest": {
+          "name": "credit_card_iframe"
+        }
+      },
+      "expectedValue": "5",
+      "selector": "//select[@name=\"c-exmth\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": true,
+        "browserTest": {
+          "name": "credit_card_iframe"
+        }
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"c-exyr\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": true,
+        "browserTest": {
+          "name": "credit_card_iframe"
+        }
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//input[@type=\"text\" and @name=\"c-chn\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
+      "action_index": 18
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/west_elm.sha1 b/chrome/test/data/autofill/captured_sites/west_elm.sha1
new file mode 100644
index 0000000..209d2ce
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/west_elm.sha1
@@ -0,0 +1 @@
+f1b179cbc0c854346b33ef27934735f2889c7786
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/west_elm.test b/chrome/test/data/autofill/captured_sites/west_elm.test
new file mode 100644
index 0000000..87dcd36b
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/west_elm.test
@@ -0,0 +1,355 @@
+{
+  "startingURL": "https://www.westelm.com/checkout/shipping.html",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "TX"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "5"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "NAME_FULL",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.city\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.zip\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 8
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "url": "https://www.westelm.com/checkout/deliveryoptions.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 10
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 11
+    },
+    {
+      "url": "https://www.westelm.com/checkout/billing.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"address.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"address.zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@type=\"email\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 21
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 22
+    },
+    {
+      "url": "https://www.westelm.com/checkout/issue/ordererror.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 23
+    },
+    {
+      "selector": "//button",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 24
+    },
+    {
+      "url": "https://www.westelm.com/checkout/payment.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 25
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "index": 2,
+      "selector": "//select[@name=\"creditCard.cardId\"]",
+      "type": "select",
+      "visibility": 3,
+      "action_index": 26
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 27
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5",
+      "selector": "//select[@name=\"creditCard.cardExpMonth\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 28
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"creditCard.cardExpYear\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 29
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 30
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/williams_sonoma.sha1 b/chrome/test/data/autofill/captured_sites/williams_sonoma.sha1
new file mode 100644
index 0000000..9e376b7
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/williams_sonoma.sha1
@@ -0,0 +1 @@
+ef250ee028101b6768364b11a090040fc6e3186e
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/williams_sonoma.test b/chrome/test/data/autofill/captured_sites/williams_sonoma.test
new file mode 100644
index 0000000..36c90d05
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/williams_sonoma.test
@@ -0,0 +1,346 @@
+{
+  "startingURL": "https://www.williams-sonoma.com/checkout/shipping.html",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "TX"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "5"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "EMAIL_ADDRESS",
+      "value": "red.swingline@initech.com"
+    },
+    {
+      "type": "NAME_FULL",
+      "value": "Milton C. Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 1
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 2
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 3
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 4
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"shipTo.address.fullName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 8
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "url": "https://www.williams-sonoma.com/checkout/deliveryoptions.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 10
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 11
+    },
+    {
+      "url": "https://www.williams-sonoma.com/checkout/billing.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 12
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine1\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 14
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @id=\"address.addrLine2\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 15
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @id=\"address.city\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 16
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "TX",
+      "selector": "//select",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 17
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @id=\"address.zip\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"tel\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "red.swingline@initech.com",
+      "selector": "//input[@type=\"email\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "EMAIL_ADDRESS",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @id=\"address.fullName\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "NAME_FULL",
+      "action_index": 21
+    },
+    {
+      "selector": "//button",
+      "visibility": 3,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 22
+    },
+    {
+      "url": "https://www.williams-sonoma.com/checkout/payment.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 23
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "index": 3,
+      "selector": "//select[@name=\"creditCard.cardId\"]",
+      "type": "select",
+      "visibility": 3,
+      "action_index": 24
+    },
+    {
+      "url": "https://www.williams-sonoma.com/checkout/payment.html",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 25
+    },
+    {
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 26
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5",
+      "selector": "//select[@name=\"creditCard.cardExpMonth\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 27
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@name=\"creditCard.cardExpYear\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 28
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@type=\"text\" and @id=\"creditCard.cardNumber\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 29
+    }
+  ]
+}
diff --git a/chrome/test/data/autofill/captured_sites/zappos.sha1 b/chrome/test/data/autofill/captured_sites/zappos.sha1
index e586d78..f0731079 100644
--- a/chrome/test/data/autofill/captured_sites/zappos.sha1
+++ b/chrome/test/data/autofill/captured_sites/zappos.sha1
@@ -1 +1 @@
-7ec3cde9ef88336c2e087c53d408f1308153a87b
\ No newline at end of file
+412e970039114f2e67df45df8347db155015155d
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/zappos.test b/chrome/test/data/autofill/captured_sites/zappos.test
index 0138724..c512292 100644
--- a/chrome/test/data/autofill/captured_sites/zappos.test
+++ b/chrome/test/data/autofill/captured_sites/zappos.test
@@ -1,32 +1,23 @@
 {
-  "name": "Online Shoes, Clothing, Always Shipped FREE | Zappos.com",
-  "startingURL": "https://www.zappos.com/marty/cart",
+  "startingURL": "https://www.zappos.com/cart",
   "autofillProfile": [
     {
-      "type": "ADDRESS_HOME_CITY",
+      "type": "HTML_TYPE_ADDRESS_LEVEL1",
+      "value": "Texas"
+    },
+    {
+      "type": "HTML_TYPE_ADDRESS_LEVEL2",
       "value": "Austin"
     },
     {
-      "type": "ADDRESS_HOME_LINE1",
+      "type": "HTML_TYPE_ADDRESS_LINE1",
       "value": "4120 Freidrich Lane"
     },
     {
-      "type": "ADDRESS_HOME_LINE2",
+      "type": "HTML_TYPE_ADDRESS_LINE2",
       "value": "Apt 8"
     },
     {
-      "type": "ADDRESS_HOME_STATE",
-      "value": "TX"
-    },
-    {
-      "type": "ADDRESS_HOME_ZIP",
-      "value": "78744"
-    },
-    {
-      "type": "EMAIL_ADDRESS",
-      "value": "red.swingline@initech.com"
-    },
-    {
       "type": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
       "value": "05"
     },
@@ -35,157 +26,256 @@
       "value": "2027"
     },
     {
+      "type": "HTML_TYPE_CREDIT_CARD_NAME_FULL",
+      "value": "Milton Waddams"
+    },
+    {
       "type": "HTML_TYPE_CREDIT_CARD_NUMBER",
       "value": "9621327911759602"
     },
     {
-      "type": "NAME_FULL",
+      "type": "HTML_TYPE_NAME",
       "value": "Milton C. Waddams"
     },
     {
-      "type": "PHONE_HOME_WHOLE_NUMBER",
+      "type": "HTML_TYPE_POSTAL_CODE",
+      "value": "78744"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
       "value": "5125551234"
     }
   ],
+  "passwordManagerProfiles": [],
   "actions": [
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"root\"]/div/div/main/div/div/div[2]/div[2]/div/div[2]/form/button[contains(., 'Proceed to CheckoutCart')]",
+      "selector": "//a[@href=\"/login\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "click",
+      "action_index": 1
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"address\"]/div[1]/div/div[2]/div[2]/div[2]/div/div/div/div/div/div[2]/div/span[contains(., 'Ship to a new address')]/div/div/div/img",
+      "url": "https://auth.zappos.com/ap/signin?openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.zappos.com%2Fzap%2FloginComplete&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.assoc_handle=zappos_us_desktop&openid.oa2.response_type=code&openid.mode=checkid_setup&openid.ns.oa2=http%3A%2F%2Fwww.amazon.com%2Fap%2Fext%2Foauth%2F2&siteState=495d018f-e7ed-486c-ae9d-070dbf58d134%3AZ%2FgdL319Kfc2SASy4VTkg1djVR8X0%2BvYZB480IJsWUg%3D%3Anull&openid.oa2.scope=auth_code&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.oa2.client_id=iba%3Aamzn1.application-oa2-client.ce5075dead7c4aa7ae316059988839d5&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "type": "loadPage",
+      "action_index": 2
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"AddressForm_NAME\"]",
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "selector": "//input[@type=\"email\"]",
+      "type": "type",
+      "value": "chromeguyforever@gmail.com",
+      "visibility": 7,
+      "action_index": 3
     },
     {
-      "selector": "//*[@id=\"AddressForm_NAME\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "NAME_FULL",
-      "expectedValue": "Milton C. Waddams",
-      "type": "validateField"
+      "selector": "//input[@type=\"password\"]",
+      "type": "typePassword",
+      "value": "chrome1969",
+      "visibility": 7,
+      "action_index": 4
     },
     {
-      "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_1\"]",
+      "selector": "//input[@id=\"signInSubmit\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "type": "click",
+      "action_index": 5
+    },
+    {
+      "url": "https://www.zappos.com/?ln=true",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 6
+    },
+    {
+      "selector": "//a[@id=\"cartCountNumber\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 7
+    },
+    {
+      "selector": "//div/div[2]/form[@method=\"post\"]/button[normalize-space(text())=\"Proceed to Checkout\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 8
+    },
+    {
+      "selector": "//img[@src=\"https://images-na.ssl-images-amazon.com/images/G/01/checkout/assets/addAddress._CB340499364_.png\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 9
+    },
+    {
+      "selector": "//input[@type=\"text\" and @autocomplete=\"name\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
       "expectedValue": "4120 Freidrich Lane",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"address-line1\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE1",
+      "action_index": 11
     },
     {
-      "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_2\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_LINE2",
       "expectedValue": "Apt 8",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"address-line2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2",
+      "action_index": 12
     },
     {
-      "selector": "//*[@id=\"AddressForm_CITY\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_CITY",
       "expectedValue": "Austin",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"address-level2\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2",
+      "action_index": 13
     },
     {
-      "selector": "//*[@id=\"AddressForm_STATE_OR_REGION\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_STATE",
       "expectedValue": "Texas",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"address-level1\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1",
+      "action_index": 14
     },
     {
-      "selector": "//*[@id=\"AddressForm_ZIP_CODE\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "ADDRESS_HOME_ZIP",
       "expectedValue": "78744",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"postal-code\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_POSTAL_CODE",
+      "action_index": 15
     },
     {
-      "selector": "//*[@id=\"AddressForm_PHONE_NUMBER\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "PHONE_HOME_WHOLE_NUMBER",
       "expectedValue": "5125551234",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"tel-national\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 16
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"saveAndShipToThisAddress\"]",
       "context": {
         "isIframe": false
       },
-      "type": "click"
+      "expectedValue": "Milton C. Waddams",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"name\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "HTML_TYPE_NAME",
+      "action_index": 17
     },
     {
-      "selectorType": "xpath",
-      "selector": "//*[@id=\"ccNumber\"]",
+      "selector": "//button[@id=\"add-ship-address\"]",
+      "visibility": 7,
       "context": {
         "isIframe": false
       },
-      "type": "autofill"
+      "type": "click",
+      "action_index": 18
     },
     {
-      "selector": "//*[@id=\"ccNumber\"]",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"cc-name\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "type": "autofill",
+      "visibility": 3,
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
       "expectedValue": "9621327911759602",
-      "type": "validateField"
+      "selector": "//input[@type=\"text\" and @autocomplete=\"cc-number\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER",
+      "action_index": 20
     },
     {
-      "selector": "//*[@id=\"ccName\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_NAME_FULL",
-      "expectedValue": "Milton Waddams",
-      "type": "validateField"
+      "expectedValue": "05",
+      "selector": "//select[@autocomplete=\"cc-exp-month\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH",
+      "action_index": 21
     },
     {
-      "selector": "//*[@id=\"ccMonth\"]",
       "context": {
         "isIframe": false
       },
-      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
-      "expectedValue": "5",
-      "type": "validateField"
-    },
-    {
-      "selector": "//*[@id=\"ccYear\"]",
-      "context": {
-        "isIframe": false
-      },
-      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
       "expectedValue": "2027",
-      "type": "validateField"
+      "selector": "//select[@autocomplete=\"cc-exp-year\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton Waddams",
+      "selector": "//input[@type=\"text\" and @autocomplete=\"cc-name\"]",
+      "type": "validateField",
+      "visibility": 3,
+      "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NAME_FULL",
+      "action_index": 23
     }
   ]
 }
diff --git a/chrome/test/data/autofill/captured_sites/zulily.sha1 b/chrome/test/data/autofill/captured_sites/zulily.sha1
new file mode 100644
index 0000000..57f3a62d
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/zulily.sha1
@@ -0,0 +1 @@
+03ed4cac54e35961385a8d4570f2dcad3e8b72aa
\ No newline at end of file
diff --git a/chrome/test/data/autofill/captured_sites/zulily.test b/chrome/test/data/autofill/captured_sites/zulily.test
new file mode 100644
index 0000000..b7107919
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/zulily.test
@@ -0,0 +1,360 @@
+{
+  "startingURL": "https://www.zulily.com/2/cart",
+  "autofillProfile": [
+    {
+      "type": "ADDRESS_HOME_CITY",
+      "value": "Austin"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE1",
+      "value": "4120 Freidrich Lane"
+    },
+    {
+      "type": "ADDRESS_HOME_LINE2",
+      "value": "Apt 8"
+    },
+    {
+      "type": "ADDRESS_HOME_STATE",
+      "value": "57"
+    },
+    {
+      "type": "ADDRESS_HOME_ZIP",
+      "value": "78744"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "value": "2027"
+    },
+    {
+      "type": "CREDIT_CARD_EXP_MONTH",
+      "value": "05"
+    },
+    {
+      "type": "CREDIT_CARD_NUMBER",
+      "value": "9621327911759602"
+    },
+    {
+      "type": "NAME_FIRST",
+      "value": "Milton"
+    },
+    {
+      "type": "NAME_LAST",
+      "value": "Waddams"
+    },
+    {
+      "type": "PHONE_HOME_CITY_AND_NUMBER",
+      "value": "5125551234"
+    }
+  ],
+  "passwordManagerProfiles": [],
+  "actions": [
+    {
+      "selector": "//li/a[normalize-space(text())=\"\"]/span[text()=\"proceed to checkout\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 1
+    },
+    {
+      "url": "https://www.zulily.com/2/checkout",
+      "context": {
+        "isIframe": false
+      },
+      "type": "loadPage",
+      "action_index": 2
+    },
+    {
+      "selector": "//button/i[@aria-hidden=\"true\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 3
+    },
+    {
+      "selector": "//input[@tabindex=\"0\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 4
+    },
+    {
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[80793][firstname]\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 5
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[80793][lastname]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 6
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[80793][street1]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 7
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[80793][street2]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 8
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @data-min-length=\"2\" and @id=\"address[80793][city]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 9
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "57",
+      "selector": "//select[@id=\"address[80793][region_id][us]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 10
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @maxlength=\"10\" and @id=\"address[80793][postcode]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 11
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"text\" and @name=\"address[telephone]\" and @id=\"address[80793][telephone]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 12
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[80793][firstname]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 13
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "selector": "//input[@type=\"text\" and @name=\"address[telephone]\" and @id=\"address[80793][telephone]\"]",
+      "type": "type",
+      "value": "5125161234",
+      "visibility": 7,
+      "action_index": 14
+    },
+    {
+      "selector": "//input[@type=\"checkbox\" and @id=\"address[80793][default]\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 15
+    },
+    {
+      "selector": "//form/div[2]/div[2]/button[normalize-space(text())=\"\"]/span[normalize-space(text())=\"\"]/span[text()=\"continue\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 16
+    },
+    {
+      "selector": "//input[@tabindex=\"0\" and @value=\"new\"]",
+      "visibility": 7,
+      "context": {
+        "isIframe": false
+      },
+      "type": "click",
+      "action_index": 17
+    },
+    {
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[43558][firstname]\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 18
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Waddams",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[43558][lastname]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_LAST",
+      "action_index": 19
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "4120 Freidrich Lane",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[43558][street1]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE1",
+      "action_index": 20
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Apt 8",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[43558][street2]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_LINE2",
+      "action_index": 21
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Austin",
+      "selector": "//input[@type=\"text\" and @maxlength=\"50\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_CITY",
+      "action_index": 22
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "57",
+      "selector": "//select[@id=\"address[43558][region_id][us]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_STATE",
+      "action_index": 23
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "78744",
+      "selector": "//input[@type=\"text\" and @maxlength=\"10\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "ADDRESS_HOME_ZIP",
+      "action_index": 24
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "5125551234",
+      "selector": "//input[@type=\"text\" and @name=\"address[telephone]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER",
+      "action_index": 25
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "Milton",
+      "selector": "//input[@type=\"text\" and @maxlength=\"30\" and @id=\"address[43558][firstname]\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "NAME_FIRST",
+      "action_index": 26
+    },
+    {
+      "selector": "//input[@aria-required=\"true\" and @id=\"payment:number\"]",
+      "context": {
+        "isIframe": false
+      },
+      "type": "autofill",
+      "visibility": 7,
+      "action_index": 27
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "05",
+      "selector": "//select[@aria-required=\"true\" and @id=\"payment:expmonth\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_EXP_MONTH",
+      "action_index": 28
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "2027",
+      "selector": "//select[@aria-required=\"true\" and @id=\"payment:expyear\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR",
+      "action_index": 29
+    },
+    {
+      "context": {
+        "isIframe": false
+      },
+      "expectedValue": "9621327911759602",
+      "selector": "//input[@aria-required=\"true\" and @id=\"payment:number\"]",
+      "type": "validateField",
+      "visibility": 7,
+      "expectedAutofillType": "CREDIT_CARD_NUMBER",
+      "action_index": 30
+    }
+  ]
+}
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 202c069b..cf44fa1 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -1884,6 +1884,21 @@
     "note": "TODO(bartfab): Flag this with can_be_recommended when http://crbug.com/106682 is fixed."
   },
 
+  "WebUsbAllowDevicesForUrls": {
+    "os": ["win", "linux", "mac", "chromeos", "android"],
+    "test_policy": {
+      "WebUsbAllowDevicesForUrls": [
+        {
+          "devices": [{"vendor_id": 1234, "product_id": 5678}],
+          "url_patterns": ["[*.]google.com", "[*.]youtube.com"]
+        }
+      ]
+    },
+    "pref_mappings": [
+      { "pref": "profile.managed_web_usb_allow_devices_for_urls" }
+    ]
+  },
+
   "WebUsbAskForUrls": {
     "os": ["win", "linux", "mac", "chromeos", "android"],
     "test_policy": { "WebUsbAskForUrls": ["[*.]google.com"] },
diff --git a/chrome/test/data/web_page_replay_go_helper_scripts/automation_helper.js b/chrome/test/data/web_page_replay_go_helper_scripts/automation_helper.js
index 03104ba8..086d250 100644
--- a/chrome/test/data/web_page_replay_go_helper_scripts/automation_helper.js
+++ b/chrome/test/data/web_page_replay_go_helper_scripts/automation_helper.js
@@ -47,16 +47,14 @@
 
         if (isReady && state_flags & this.DomElementReadyState.on_top) {
           var rect = target.getBoundingClientRect();
-          isReady &=
-            // Check that the element is not concealed behind another element.
-            isSelfOrDescendant(
-                target,
-                document.elementFromPoint(
-                    // As coordinates, use the center of the element, minus
-                    // the window offset in case the element is outside the
-                    // view.
-                    rect.left + rect.width / 2 - window.pageXOffset,
-                    rect.top + rect.height / 2 - window.pageYOffset));
+          // Check that the element is not concealed behind another element.
+          const topElement = document.elementFromPoint(
+              // As coordinates, use the center of the element, minus the
+              // window offset in case the element is outside the view.
+              rect.left + rect.width / 2 - window.pageXOffset,
+              rect.top + rect.height / 2 - window.pageYOffset);
+          isReady &= target.contains(topElement) ||
+                     target.isSameNode(topElement);
         }
       }
 
@@ -111,16 +109,5 @@
     element.dispatchEvent(event);
   }
 
-  function isSelfOrDescendant(parent, child) {
-    var node = child;
-    while (node != null) {
-      if (node == parent) {
-        return true;
-      }
-      node = node.parentNode;
-    }
-    return false;
-  }
-
   return automation_helper;
 })();
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index fe4ae05..4b8dd3e 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -801,6 +801,10 @@
     ]
   }
 
+  tast_test("chrome_all_tast_tests") {
+    tast_conditional = "(!informational && !disabled && (\"dep:chrome\" || \"dep:chrome_login\"))"
+  }
+
   group("cros_chrome_deploy") {
     # The following run-time dependencies are needed to deploy chrome to a
     # ChromeOS device. See the link for the full list:
diff --git a/chromeos/dbus/fake_shill_device_client.cc b/chromeos/dbus/fake_shill_device_client.cc
index a60922b..b02ce471 100644
--- a/chromeos/dbus/fake_shill_device_client.cc
+++ b/chromeos/dbus/fake_shill_device_client.cc
@@ -39,8 +39,8 @@
 void ErrorFunction(const std::string& device_path,
                    const std::string& error_name,
                    const std::string& error_message) {
-  LOG(ERROR) << "Shill Error for: " << device_path
-             << ": " << error_name << " : " << error_message;
+  LOG(ERROR) << "Shill Error for: " << device_path << ": " << error_name
+             << " : " << error_message;
 }
 
 void PostError(const std::string& error,
@@ -391,8 +391,10 @@
 void FakeShillDeviceClient::AddDevice(const std::string& device_path,
                                       const std::string& type,
                                       const std::string& name) {
-  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
-      AddDevice(device_path);
+  DBusThreadManager::Get()
+      ->GetShillManagerClient()
+      ->GetTestInterface()
+      ->AddDevice(device_path);
 
   base::Value* properties = GetDeviceProperties(device_path);
   properties->SetKey(shill::kTypeProperty, base::Value(type));
@@ -407,15 +409,19 @@
 }
 
 void FakeShillDeviceClient::RemoveDevice(const std::string& device_path) {
-  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
-      RemoveDevice(device_path);
+  DBusThreadManager::Get()
+      ->GetShillManagerClient()
+      ->GetTestInterface()
+      ->RemoveDevice(device_path);
 
   stub_devices_.RemoveWithoutPathExpansion(device_path, NULL);
 }
 
 void FakeShillDeviceClient::ClearDevices() {
-  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
-      ClearDevices();
+  DBusThreadManager::Get()
+      ->GetShillManagerClient()
+      ->GetTestInterface()
+      ->ClearDevices();
 
   stub_devices_.Clear();
 }
@@ -424,8 +430,8 @@
                                               const std::string& name,
                                               const base::Value& value,
                                               bool notify_changed) {
-  VLOG(1) << "SetDeviceProperty: " << device_path
-          << ": " << name << " = " << value;
+  VLOG(1) << "SetDeviceProperty: " << device_path << ": " << name << " = "
+          << value;
   SetPropertyInternal(dbus::ObjectPath(device_path), name, value,
                       base::DoNothing(),
                       base::Bind(&ErrorFunction, device_path), notify_changed);
@@ -433,14 +439,14 @@
 
 std::string FakeShillDeviceClient::GetDevicePathForType(
     const std::string& type) {
-  for (base::DictionaryValue::Iterator iter(stub_devices_);
-       !iter.IsAtEnd(); iter.Advance()) {
+  for (base::DictionaryValue::Iterator iter(stub_devices_); !iter.IsAtEnd();
+       iter.Advance()) {
     const base::DictionaryValue* properties = NULL;
     if (!iter.value().GetAsDictionary(&properties))
       continue;
     std::string prop_type;
-    if (!properties->GetStringWithoutPathExpansion(
-            shill::kTypeProperty, &prop_type) ||
+    if (!properties->GetStringWithoutPathExpansion(shill::kTypeProperty,
+                                                   &prop_type) ||
         prop_type != type)
       continue;
     return iter.key();
@@ -611,8 +617,8 @@
     const dbus::ObjectPath& device_path,
     const DictionaryValueCallback& callback) const {
   const base::DictionaryValue* device_properties = NULL;
-  if (!stub_devices_.GetDictionaryWithoutPathExpansion(
-      device_path.value(), &device_properties)) {
+  if (!stub_devices_.GetDictionaryWithoutPathExpansion(device_path.value(),
+                                                       &device_properties)) {
     base::DictionaryValue empty_dictionary;
     callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary);
     return;
@@ -638,8 +644,7 @@
   }
   base::Value* value = NULL;
   if (!dict->GetWithoutPathExpansion(property, &value)) {
-    LOG(ERROR) << "Notify for unknown property: "
-        << path << " : " << property;
+    LOG(ERROR) << "Notify for unknown property: " << path << " : " << property;
     return;
   }
   for (auto& observer : GetObserverList(device_path))
diff --git a/chromeos/dbus/fake_shill_device_client.h b/chromeos/dbus/fake_shill_device_client.h
index 0217de3..42fd4ca 100644
--- a/chromeos/dbus/fake_shill_device_client.h
+++ b/chromeos/dbus/fake_shill_device_client.h
@@ -78,11 +78,10 @@
                             const std::string& peer,
                             const StringCallback& callback,
                             const ErrorCallback& error_callback) override;
-  void AddWakeOnPacketConnection(
-      const dbus::ObjectPath& device_path,
-      const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback) override;
+  void AddWakeOnPacketConnection(const dbus::ObjectPath& device_path,
+                                 const net::IPEndPoint& ip_endpoint,
+                                 const base::Closure& callback,
+                                 const ErrorCallback& error_callback) override;
   void RemoveWakeOnPacketConnection(
       const dbus::ObjectPath& device_path,
       const net::IPEndPoint& ip_endpoint,
@@ -165,7 +164,7 @@
   std::string tdls_state_;
 
   // Wake on packet connections for each device.
-  std::map<dbus::ObjectPath, std::set<net::IPEndPoint> >
+  std::map<dbus::ObjectPath, std::set<net::IPEndPoint>>
       wake_on_packet_connections_;
 
   // Current SIM PIN per device path.
diff --git a/chromeos/dbus/shill_device_client.cc b/chromeos/dbus/shill_device_client.cc
index 7bb3110..0303c73 100644
--- a/chromeos/dbus/shill_device_client.cc
+++ b/chromeos/dbus/shill_device_client.cc
@@ -27,13 +27,11 @@
 // The ShillDeviceClient implementation.
 class ShillDeviceClientImpl : public ShillDeviceClient {
  public:
-  ShillDeviceClientImpl()
-      : bus_(NULL) {
-  }
+  ShillDeviceClientImpl() : bus_(NULL) {}
 
   ~ShillDeviceClientImpl() override {
-    for (HelperMap::iterator iter = helpers_.begin();
-         iter != helpers_.end(); ++iter) {
+    for (HelperMap::iterator iter = helpers_.begin(); iter != helpers_.end();
+         ++iter) {
       // This *should* never happen, yet we're getting crash reports that
       // seem to imply that it does happen sometimes.  Adding CHECKs here
       // so we can determine more accurately where the problem lies.
@@ -75,9 +73,9 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(name);
     ShillClientHelper::AppendValueDataAsVariant(&writer, value);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                            callback,
-                                                            error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void ClearProperty(const dbus::ObjectPath& device_path,
@@ -100,8 +98,9 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(pin);
     writer.AppendBool(require);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void EnterPin(const dbus::ObjectPath& device_path,
@@ -112,8 +111,9 @@
                                  shill::kEnterPinFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(pin);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void UnblockPin(const dbus::ObjectPath& device_path,
@@ -126,8 +126,9 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(puk);
     writer.AppendString(pin);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void ChangePin(const dbus::ObjectPath& device_path,
@@ -140,8 +141,9 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(old_pin);
     writer.AppendString(new_pin);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void Register(const dbus::ObjectPath& device_path,
@@ -152,8 +154,9 @@
                                  shill::kRegisterFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(network_id);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void SetCarrier(const dbus::ObjectPath& device_path,
@@ -164,8 +167,9 @@
                                  shill::kSetCarrierFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(carrier);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void Reset(const dbus::ObjectPath& device_path,
@@ -173,8 +177,9 @@
              const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
                                  shill::kResetFunction);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void PerformTDLSOperation(const dbus::ObjectPath& device_path,
@@ -187,15 +192,15 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(operation);
     writer.AppendString(peer);
-    GetHelper(device_path)->CallStringMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(device_path)
+        ->CallStringMethodWithErrorCallback(&method_call, callback,
+                                            error_callback);
   }
 
-  void AddWakeOnPacketConnection(
-      const dbus::ObjectPath& device_path,
-      const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback) override {
+  void AddWakeOnPacketConnection(const dbus::ObjectPath& device_path,
+                                 const net::IPEndPoint& ip_endpoint,
+                                 const base::Closure& callback,
+                                 const ErrorCallback& error_callback) override {
     if (ip_endpoint.address().empty()) {
       LOG(ERROR) << "AddWakeOnPacketConnection: null address";
       return;
@@ -204,9 +209,9 @@
                                  shill::kAddWakeOnPacketConnectionFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(ip_endpoint.ToStringWithoutPort());
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                            callback,
-                                                            error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void RemoveWakeOnPacketConnection(
@@ -222,9 +227,9 @@
                                  shill::kRemoveWakeOnPacketConnectionFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(ip_endpoint.ToStringWithoutPort());
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                            callback,
-                                                            error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void RemoveAllWakeOnPacketConnections(
@@ -234,9 +239,9 @@
     dbus::MethodCall method_call(
         shill::kFlimflamDeviceInterface,
         shill::kRemoveAllWakeOnPacketConnectionsFunction);
-    GetHelper(device_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                            callback,
-                                                            error_callback);
+    GetHelper(device_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   TestInterface* GetTestInterface() override { return NULL; }
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc
index f3fa1cd..8fc834ab 100644
--- a/chromeos/network/network_device_handler_impl.cc
+++ b/chromeos/network/network_device_handler_impl.cc
@@ -61,11 +61,8 @@
     const std::string& shill_error_name,
     const std::string& shill_error_message) {
   network_handler::ShillErrorCallbackFunction(
-      GetErrorNameForShillError(shill_error_name),
-      device_path,
-      error_callback,
-      shill_error_name,
-      shill_error_message);
+      GetErrorNameForShillError(shill_error_name), device_path, error_callback,
+      shill_error_name, shill_error_message);
 }
 
 void IPConfigRefreshCallback(const std::string& ipconfig_path, bool result) {
@@ -82,12 +79,10 @@
     const std::string& device_path,
     const base::DictionaryValue& properties) {
   const base::ListValue* ip_configs;
-  if (!properties.GetListWithoutPathExpansion(
-          shill::kIPConfigsProperty, &ip_configs)) {
+  if (!properties.GetListWithoutPathExpansion(shill::kIPConfigsProperty,
+                                              &ip_configs)) {
     network_handler::ShillErrorCallbackFunction(
-        "RequestRefreshIPConfigs Failed",
-        device_path,
-        error_callback,
+        "RequestRefreshIPConfigs Failed", device_path, error_callback,
         std::string("Missing ") + shill::kIPConfigsProperty, "");
     return;
   }
@@ -116,10 +111,7 @@
     const network_handler::ErrorCallback& error_callback) {
   NET_LOG(USER) << "Device.SetProperty: " << property_name << " = " << value;
   DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
-      dbus::ObjectPath(device_path),
-      property_name,
-      value,
-      callback,
+      dbus::ObjectPath(device_path), property_name, value, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -139,12 +131,11 @@
     const network_handler::StringResultCallback& callback,
     const network_handler::ErrorCallback& error_callback);
 
-void TDLSSuccessCallback(
-    const std::string& device_path,
-    const TDLSOperationParams& params,
-    const network_handler::StringResultCallback& callback,
-    const network_handler::ErrorCallback& error_callback,
-    const std::string& result) {
+void TDLSSuccessCallback(const std::string& device_path,
+                         const TDLSOperationParams& params,
+                         const network_handler::StringResultCallback& callback,
+                         const network_handler::ErrorCallback& error_callback,
+                         const std::string& result) {
   std::string event_desc = "TDLSSuccessCallback: " + params.operation;
   if (!result.empty())
     event_desc += ": " + result;
@@ -197,13 +188,12 @@
       request_delay);
 }
 
-void TDLSErrorCallback(
-    const std::string& device_path,
-    const TDLSOperationParams& params,
-    const network_handler::StringResultCallback& callback,
-    const network_handler::ErrorCallback& error_callback,
-    const std::string& dbus_error_name,
-    const std::string& dbus_error_message) {
+void TDLSErrorCallback(const std::string& device_path,
+                       const TDLSOperationParams& params,
+                       const network_handler::StringResultCallback& callback,
+                       const network_handler::ErrorCallback& error_callback,
+                       const std::string& dbus_error_name,
+                       const std::string& dbus_error_message) {
   // If a Setup operation receives an InProgress error, retry.
   const int kMaxRetries = 5;
   if ((params.operation == shill::kTDLSDiscoverOperation ||
@@ -234,8 +224,9 @@
     return;
 
   const std::string error_name =
-      dbus_error_name == shill::kErrorResultInProgress ?
-      NetworkDeviceHandler::kErrorTimeout : NetworkDeviceHandler::kErrorUnknown;
+      dbus_error_name == shill::kErrorResultInProgress
+          ? NetworkDeviceHandler::kErrorTimeout
+          : NetworkDeviceHandler::kErrorUnknown;
   const std::string& error_detail = params.ip_or_mac_address;
   std::unique_ptr<base::DictionaryValue> error_data(
       network_handler::CreateDBusErrorData(device_path, error_name,
@@ -253,13 +244,11 @@
   NET_LOG(EVENT) << "CallPerformTDLSOperation: " << params.operation << ": "
                  << device_path;
   DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
-      dbus::ObjectPath(device_path),
-      params.operation,
-      params.ip_or_mac_address,
-      base::Bind(&TDLSSuccessCallback,
-                 device_path, params, callback, error_callback),
-      base::Bind(&TDLSErrorCallback,
-                 device_path, params, callback, error_callback));
+      dbus::ObjectPath(device_path), params.operation, params.ip_or_mac_address,
+      base::Bind(&TDLSSuccessCallback, device_path, params, callback,
+                 error_callback),
+      base::Bind(&TDLSErrorCallback, device_path, params, callback,
+                 error_callback));
 }
 
 }  // namespace
@@ -275,8 +264,8 @@
     const network_handler::ErrorCallback& error_callback) const {
   DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
       dbus::ObjectPath(device_path),
-      base::Bind(&network_handler::GetPropertiesCallback,
-                 callback, error_callback, device_path));
+      base::Bind(&network_handler::GetPropertiesCallback, callback,
+                 error_callback, device_path));
 }
 
 void NetworkDeviceHandlerImpl::SetDeviceProperty(
@@ -287,31 +276,29 @@
     const network_handler::ErrorCallback& error_callback) {
   const char* const property_blacklist[] = {
       // Must only be changed by policy/owner through.
-      shill::kCellularAllowRoamingProperty
-  };
+      shill::kCellularAllowRoamingProperty};
 
   for (size_t i = 0; i < arraysize(property_blacklist); ++i) {
     if (property_name == property_blacklist[i]) {
       InvokeErrorCallback(
-          device_path,
-          error_callback,
+          device_path, error_callback,
           "SetDeviceProperty called on blacklisted property " + property_name);
       return;
     }
   }
 
-  SetDevicePropertyInternal(
-      device_path, property_name, value, callback, error_callback);
+  SetDevicePropertyInternal(device_path, property_name, value, callback,
+                            error_callback);
 }
 
 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
     const std::string& device_path,
     const base::Closure& callback,
     const network_handler::ErrorCallback& error_callback) {
-  GetDeviceProperties(device_path,
-                      base::Bind(&RefreshIPConfigsCallback,
-                                 callback, error_callback),
-                      error_callback);
+  GetDeviceProperties(
+      device_path,
+      base::Bind(&RefreshIPConfigsCallback, callback, error_callback),
+      error_callback);
 }
 
 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
@@ -322,9 +309,7 @@
   NET_LOG(USER) << "Device.RegisterCellularNetwork: " << device_path
                 << " Id: " << network_id;
   DBusThreadManager::Get()->GetShillDeviceClient()->Register(
-      dbus::ObjectPath(device_path),
-      network_id,
-      callback,
+      dbus::ObjectPath(device_path), network_id, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -336,9 +321,7 @@
   NET_LOG(USER) << "Device.SetCarrier: " << device_path
                 << " carrier: " << carrier;
   DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
-      dbus::ObjectPath(device_path),
-      carrier,
-      callback,
+      dbus::ObjectPath(device_path), carrier, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -350,10 +333,7 @@
     const network_handler::ErrorCallback& error_callback) {
   NET_LOG(USER) << "Device.RequirePin: " << device_path << ": " << require_pin;
   DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
-      dbus::ObjectPath(device_path),
-      pin,
-      require_pin,
-      callback,
+      dbus::ObjectPath(device_path), pin, require_pin, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -364,9 +344,7 @@
     const network_handler::ErrorCallback& error_callback) {
   NET_LOG(USER) << "Device.EnterPin: " << device_path;
   DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
-      dbus::ObjectPath(device_path),
-      pin,
-      callback,
+      dbus::ObjectPath(device_path), pin, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -378,10 +356,7 @@
     const network_handler::ErrorCallback& error_callback) {
   NET_LOG(USER) << "Device.UnblockPin: " << device_path;
   DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
-      dbus::ObjectPath(device_path),
-      puk,
-      new_pin,
-      callback,
+      dbus::ObjectPath(device_path), puk, new_pin, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -393,10 +368,7 @@
     const network_handler::ErrorCallback& error_callback) {
   NET_LOG(USER) << "Device.ChangePin: " << device_path;
   DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
-      dbus::ObjectPath(device_path),
-      old_pin,
-      new_pin,
-      callback,
+      dbus::ObjectPath(device_path), old_pin, new_pin, callback,
       base::Bind(&HandleShillCallFailure, device_path, error_callback));
 }
 
@@ -425,8 +397,8 @@
   params.operation =
       enabled ? shill::kTDLSDiscoverOperation : shill::kTDLSTeardownOperation;
   params.ip_or_mac_address = ip_or_mac_address;
-  CallPerformTDLSOperation(
-      device_state->path(), params, callback, error_callback);
+  CallPerformTDLSOperation(device_state->path(), params, callback,
+                           error_callback);
 }
 
 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
@@ -440,32 +412,29 @@
   TDLSOperationParams params;
   params.operation = shill::kTDLSStatusOperation;
   params.ip_or_mac_address = ip_or_mac_address;
-  CallPerformTDLSOperation(
-      device_state->path(), params, callback, error_callback);
+  CallPerformTDLSOperation(device_state->path(), params, callback,
+                           error_callback);
 }
 
 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketConnection(
-      const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
-      const network_handler::ErrorCallback& error_callback) {
+    const net::IPEndPoint& ip_endpoint,
+    const base::Closure& callback,
+    const network_handler::ErrorCallback& error_callback) {
   const DeviceState* device_state = GetWifiDeviceState(error_callback);
   if (!device_state)
     return;
 
   NET_LOG(USER) << "Device.AddWakeOnWifi: " << device_state->path();
   DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
-      dbus::ObjectPath(device_state->path()),
-      ip_endpoint,
-      callback,
-      base::Bind(&HandleShillCallFailure,
-                 device_state->path(),
+      dbus::ObjectPath(device_state->path()), ip_endpoint, callback,
+      base::Bind(&HandleShillCallFailure, device_state->path(),
                  error_callback));
 }
 
 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketConnection(
-      const net::IPEndPoint& ip_endpoint,
-      const base::Closure& callback,
-      const network_handler::ErrorCallback& error_callback) {
+    const net::IPEndPoint& ip_endpoint,
+    const base::Closure& callback,
+    const network_handler::ErrorCallback& error_callback) {
   const DeviceState* device_state = GetWifiDeviceState(error_callback);
   if (!device_state)
     return;
@@ -473,17 +442,15 @@
   NET_LOG(USER) << "Device.RemoveWakeOnWifi: " << device_state->path();
   DBusThreadManager::Get()
       ->GetShillDeviceClient()
-      ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state->path()),
-                                     ip_endpoint,
-                                     callback,
-                                     base::Bind(&HandleShillCallFailure,
-                                                device_state->path(),
-                                                error_callback));
+      ->RemoveWakeOnPacketConnection(
+          dbus::ObjectPath(device_state->path()), ip_endpoint, callback,
+          base::Bind(&HandleShillCallFailure, device_state->path(),
+                     error_callback));
 }
 
 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
-      const base::Closure& callback,
-      const network_handler::ErrorCallback& error_callback) {
+    const base::Closure& callback,
+    const network_handler::ErrorCallback& error_callback) {
   const DeviceState* device_state = GetWifiDeviceState(error_callback);
   if (!device_state)
     return;
@@ -491,11 +458,10 @@
   NET_LOG(USER) << "Device.RemoveAllWakeOnWifi: " << device_state->path();
   DBusThreadManager::Get()
       ->GetShillDeviceClient()
-      ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state->path()),
-                                         callback,
-                                         base::Bind(&HandleShillCallFailure,
-                                                    device_state->path(),
-                                                    error_callback));
+      ->RemoveAllWakeOnPacketConnections(
+          dbus::ObjectPath(device_state->path()), callback,
+          base::Bind(&HandleShillCallFailure, device_state->path(),
+                     error_callback));
 }
 
 void NetworkDeviceHandlerImpl::DeviceListChanged() {
@@ -523,7 +489,7 @@
     return;
   }
   for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin();
-      it != list.end(); ++it) {
+       it != list.end(); ++it) {
     const DeviceState* device_state = *it;
     bool current_allow_roaming = device_state->allow_roaming();
 
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 89a08030..f78f2e3 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1074,7 +1074,9 @@
   // about:blank or about:srcdoc frames should not be allowed to use password
   // manager.  See https://crbug.com/756587.
   WebLocalFrame* frame = render_frame()->GetWebFrame();
-  if (frame->GetDocument().Url().ProtocolIs(url::kAboutScheme))
+  blink::WebURL url = frame->GetDocument().Url();
+  if (url.ProtocolIs(url::kAboutScheme) || url.ProtocolIs(url::kBlobScheme) ||
+      url.ProtocolIs(url::kFileScheme))
     return false;
   return frame->GetSecurityOrigin().CanAccessPasswordManager();
 }
diff --git a/components/autofill/core/browser/autofill_wallet_data_type_controller.cc b/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
index 24ad447..a717a83 100644
--- a/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
+++ b/components/autofill/core/browser/autofill_wallet_data_type_controller.cc
@@ -71,29 +71,23 @@
 void AutofillWalletDataTypeController::StopModels() {
   DCHECK(CalledOnValidThread());
 
-  // This controller is used by two data types, we need to clear the data only
-  // once. (In particular, if AUTOFILL_WALLET_DATA is on USS (and thus doesn't
-  // use this controller), we *don't* want any ClearAllServerData call).
-  if (type() == syncer::AUTOFILL_WALLET_DATA) {
-    // This function is called when shutting down (nothing is changing), when
-    // sync is disabled completely, or when wallet sync is disabled. In the
-    // cases where wallet sync or sync in general is disabled, clear wallet
-    // cards and addresses copied from the server. This is different than other
-    // sync cases since this type of data reflects what's on the server rather
-    // than syncing local data between clients, so this extra step is required.
-    syncer::SyncService* service = sync_client_->GetSyncService();
+  // This function is called when shutting down (nothing is changing), when
+  // sync is disabled completely, or when wallet sync is disabled. In the
+  // cases where wallet sync or sync in general is disabled, clear wallet cards
+  // and addresses copied from the server. This is different than other sync
+  // cases since this type of data reflects what's on the server rather than
+  // syncing local data between clients, so this extra step is required.
+  syncer::SyncService* service = sync_client_->GetSyncService();
 
-    // CanSyncFeatureStart indicates if sync is currently enabled at all. The
-    // preferred data type indicates if wallet sync data is enabled, and
-    // currently_enabled_ indicates if the other prefs are enabled. All of these
-    // have to be enabled to sync wallet data.
-    if (!service->CanSyncFeatureStart() ||
-        !service->GetPreferredDataTypes().Has(type()) || !currently_enabled_) {
-      autofill::PersonalDataManager* pdm =
-          sync_client_->GetPersonalDataManager();
-      if (pdm)
-        pdm->ClearAllServerData();
-    }
+  // CanSyncFeatureStart indicates if sync is currently enabled at all. The
+  // preferred data type indicates if wallet sync data/metadata is enabled, and
+  // currently_enabled_ indicates if the other prefs are enabled. All of these
+  // have to be enabled to sync wallet data/metadata.
+  if (!service->CanSyncFeatureStart() ||
+      !service->GetPreferredDataTypes().Has(type()) || !currently_enabled_) {
+    autofill::PersonalDataManager* pdm = sync_client_->GetPersonalDataManager();
+    if (pdm)
+      pdm->ClearAllServerData();
   }
 }
 
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index 5533593..9bac421 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -105,6 +105,9 @@
   // state.
   virtual void Restart() = 0;
 
+  // Stop the current script and show |message| if it is not empty .
+  virtual void StopCurrentScript(const std::string& message) = 0;
+
   // Return the current ClientMemory.
   virtual ClientMemory* GetClientMemory() = 0;
 
diff --git a/components/autofill_assistant/browser/actions/autofill_action.cc b/components/autofill_assistant/browser/actions/autofill_action.cc
index e1af5799..beaa3414 100644
--- a/components/autofill_assistant/browser/actions/autofill_action.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action.cc
@@ -97,6 +97,8 @@
          proto.use_address().form_field_element().selectors()) {
       selectors_.emplace_back(selector);
     }
+    fill_form_message_ = proto.use_address().strings().fill_form();
+    check_form_message_ = proto.use_address().strings().check_form();
   } else {
     DCHECK(proto.has_use_card());
     is_autofill_card_ = true;
@@ -106,6 +108,8 @@
          proto.use_card().form_field_element().selectors()) {
       selectors_.emplace_back(selector);
     }
+    fill_form_message_ = proto.use_card().strings().fill_form();
+    check_form_message_ = proto.use_card().strings().check_form();
   }
 }
 
@@ -127,19 +131,14 @@
     const std::string& guid = selected_data.value();
     if (guid.empty()) {
       // User selected 'Fill manually'.
-      // TODO(crbug.com/806868): We need to differentiate between action failure
-      // and stopping an action to let the user fill a form (expected stop).
-      UpdateProcessedAction(false);
-      std::move(process_action_callback_)
-          .Run(std::move(processed_action_proto_));
+      delegate->StopCurrentScript(fill_form_message_);
+      EndAction(/* successful= */ true);
       return;
     }
 
     if (selectors_.empty()) {
       // If there is no selector, finish the action directly.
-      UpdateProcessedAction(true);
-      std::move(process_action_callback_)
-          .Run(std::move(processed_action_proto_));
+      EndAction(/* successful= */ true);
       return;
     }
 
@@ -164,6 +163,11 @@
   delegate->ChooseAddress(std::move(selection_callback));
 }
 
+void AutofillAction::EndAction(bool successful) {
+  UpdateProcessedAction(successful);
+  std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+}
+
 void AutofillAction::OnDataSelected(ActionDelegate* delegate,
                                     const std::string& guid) {
   // Remember the selection.
@@ -177,21 +181,17 @@
     // If there is no selector, finish the action directly. This can be the case
     // when we want to trigger the selection of address or card at the beginning
     // of the script and use it later.
-    UpdateProcessedAction(true);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+    EndAction(/* successful= */ true);
     return;
   }
 
   if (guid.empty()) {
     // User selected 'Fill manually'.
-    // TODO(crbug.com/806868): We need to differentiate between action failure
-    // and stopping an action to let the user fill a form (expected stop).
-    UpdateProcessedAction(false);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+    delegate->StopCurrentScript(fill_form_message_);
+    EndAction(/* successful= */ true);
     return;
   }
 
-  // TODO(crbug.com/806868): Validate form and use fallback if needed.
   FillFormWithData(guid, delegate);
 }
 
@@ -238,11 +238,9 @@
 void AutofillAction::OnFormFilled(const std::string& guid,
                                   ActionDelegate* delegate,
                                   bool successful) {
-  // In case Autofill failed, we stop the action.
+  // In case Autofill failed, we fail the action.
   if (!successful) {
-    UpdateProcessedAction(false);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
-    // TODO(crbug.com/806868): Tell the user to fill the form manually.
+    EndAction(/* successful= */ false);
     return;
   }
 
@@ -254,15 +252,13 @@
                                          bool allow_fallback) {
   if (is_autofill_card_) {
     // TODO(crbug.com/806868): Implement required fields checking for cards.
-    UpdateProcessedAction(true);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+    EndAction(/* successful= */ true);
     return;
   }
 
   // If there are no required fields, finish the action successfully.
   if (proto_.use_address().required_fields().empty()) {
-    UpdateProcessedAction(true);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+    EndAction(/* successful= */ true);
     return;
   }
 
@@ -313,12 +309,10 @@
   for (size_t i = 0; i < required_fields_value_status_.size(); i++) {
     if (required_fields_value_status_[i] == EMPTY) {
       if (!allow_fallback) {
-        // Validation failed and we don't want to try the fallback, so we fail
-        // the action.
-        UpdateProcessedAction(false);
-        std::move(process_action_callback_)
-            .Run(std::move(processed_action_proto_));
-        // TODO(crbug.com/806868): Tell the user to fill the form manually.
+        // Validation failed and we don't want to try the fallback, so we stop
+        // the script.
+        delegate->StopCurrentScript(check_form_message_);
+        EndAction(/* successful= */ true);
         return;
       }
 
@@ -342,17 +336,15 @@
   DCHECK_EQ(failed_selectors.size(), fallback_values.size());
 
   if (validation_successful) {
-    UpdateProcessedAction(true);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
+    EndAction(/* successful= */ true);
     return;
   }
 
   if (fallback_values.empty()) {
     // One or more required fields is empty but there is no fallback value, so
-    // we fail the action.
-    UpdateProcessedAction(false);
-    std::move(process_action_callback_).Run(std::move(processed_action_proto_));
-    // TODO(crbug.com/806868): Tell the user to fill the form manually.
+    // we stop the script.
+    delegate->StopCurrentScript(check_form_message_);
+    EndAction(/* successful= */ true);
     return;
   }
 
@@ -413,12 +405,10 @@
   // We can ignore the other SetFieldValue callbacks given that an action is
   // processed only once.
   if (!successful) {
-    // Fallback failed: we fail the action without checking the fields.
+    // Fallback failed: we stop the script without checking the fields.
     if (process_action_callback_) {
-      UpdateProcessedAction(false);
-      std::move(process_action_callback_)
-          .Run(std::move(processed_action_proto_));
-      // TODO(crbug.com/806868): Tell the user to fill the form manually.
+      delegate->StopCurrentScript(check_form_message_);
+      EndAction(/* successful= */ true);
     }
     return;
   }
diff --git a/components/autofill_assistant/browser/actions/autofill_action.h b/components/autofill_assistant/browser/actions/autofill_action.h
index 4107d52..cd140caa 100644
--- a/components/autofill_assistant/browser/actions/autofill_action.h
+++ b/components/autofill_assistant/browser/actions/autofill_action.h
@@ -78,10 +78,14 @@
                        ActionDelegate* delegate,
                        bool successful);
 
+  void EndAction(bool successful);
+
   // Usage of the autofilled address. Ignored if autofilling a card.
   std::string name_;
   std::string prompt_;
   std::vector<std::string> selectors_;
+  std::string fill_form_message_;
+  std::string check_form_message_;
 
   // True if autofilling a card, otherwise we are autofilling an address.
   bool is_autofill_card_;
diff --git a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
index 43a0579..b308227 100644
--- a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
@@ -112,19 +112,25 @@
   const char* const kFirstName = "Foo";
   const char* const kLastName = "Bar";
   const char* const kEmail = "foobar@gmail.com";
+  const char* const kFillForm = "fill_form";
+  const char* const kCheckForm = "check_form";
 
   ActionProto CreateUseAddressAction() {
     ActionProto action;
     UseAddressProto* use_address = action.mutable_use_address();
     use_address->set_name(kAddressName);
     use_address->mutable_form_field_element()->add_selectors(kFakeSelector);
+    use_address->mutable_strings()->set_fill_form(kFillForm);
+    use_address->mutable_strings()->set_check_form(kCheckForm);
     return action;
   }
 
   ActionProto CreateUseCardAction() {
     ActionProto action;
-    action.mutable_use_card()->mutable_form_field_element()->add_selectors(
-        kFakeSelector);
+    UseCreditCardProto* use_card = action.mutable_use_card();
+    use_card->mutable_form_field_element()->add_selectors(kFakeSelector);
+    use_card->mutable_strings()->set_fill_form(kFillForm);
+    use_card->mutable_strings()->set_check_form(kCheckForm);
     return action;
   }
 
@@ -138,6 +144,15 @@
            ProcessedActionStatusProto::ACTION_APPLIED;
   }
 
+  void ExpectActionToStopScript(const ActionProto& action_proto,
+                                const std::string& expected_message) {
+    EXPECT_CALL(mock_action_delegate_, StopCurrentScript(expected_message));
+
+    // The AutofillAction should finish successfully even when stopping the
+    // current script.
+    EXPECT_TRUE(ProcessAction(action_proto));
+  }
+
   MockActionDelegate mock_action_delegate_;
   MockClientMemory mock_client_memory_;
   std::string autofill_profile_guid_;
@@ -164,7 +179,7 @@
   // We save the selection in memory.
   EXPECT_CALL(mock_client_memory_, set_selected_address(kAddressName, ""));
 
-  EXPECT_FALSE(ProcessAction(action_proto));
+  ExpectActionToStopScript(action_proto, kFillForm);
 }
 
 TEST_F(AutofillActionTest, ValidationSucceeds) {
@@ -237,7 +252,7 @@
               OnSetFieldValue(ElementsAre(kFakeSelector), kFirstName, _))
       .WillOnce(RunOnceCallback<2>(false));
 
-  EXPECT_FALSE(ProcessAction(action_proto));
+  ExpectActionToStopScript(action_proto, kCheckForm);
 }
 
 TEST_F(AutofillActionTest, FallbackSucceeds) {
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 3d9edeea..b8d842a 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -104,6 +104,7 @@
   MOCK_METHOD0(GetClientMemory, ClientMemory*());
   MOCK_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*());
   MOCK_METHOD0(GetWebContents, content::WebContents*());
+  MOCK_METHOD1(StopCurrentScript, void(const std::string& message));
 };
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index c032a0ba5..b6823f5 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -207,7 +207,10 @@
                                const GURL& validated_url) {
   // TODO(crbug.com/806868): Find a better time to get and update assistant
   // scripts.
-  GetOrCheckScripts(validated_url);
+
+  // validated_url might not be the page URL. Ignore it and always check the
+  // last committed url.
+  GetOrCheckScripts(web_contents()->GetLastCommittedURL());
 }
 
 void Controller::WebContentsDestroyed() {
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index f7f1a97..ff4a0b6 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -24,6 +24,7 @@
     : script_path_(script_path),
       delegate_(delegate),
       at_end_(CONTINUE),
+      should_stop_script_(false),
       weak_ptr_factory_(this) {
   DCHECK(delegate_);
 }
@@ -122,6 +123,13 @@
   at_end_ = RESTART;
 }
 
+void ScriptExecutor::StopCurrentScript(const std::string& message) {
+  if (!message.empty()) {
+    delegate_->GetUiController()->ShowStatusMessage(message);
+  }
+  should_stop_script_ = true;
+}
+
 ClientMemory* ScriptExecutor::GetClientMemory() {
   return delegate_->GetClientMemory();
 }
@@ -212,6 +220,14 @@
     GetNextActions();
     return;
   }
+
+  if (should_stop_script_) {
+    // Last action called StopCurrentScript(). We simulate a successful end of
+    // script to make sure we don't display any errors.
+    RunCallback(true);
+    return;
+  }
+
   ProcessNextAction();
 }
 
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 14a966f5..75a46c7 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -85,6 +85,7 @@
   ClientMemory* GetClientMemory() override;
   autofill::PersonalDataManager* GetPersonalDataManager() override;
   content::WebContents* GetWebContents() override;
+  void StopCurrentScript(const std::string& message) override;
 
  private:
   void OnGetActions(bool result, const std::string& response);
@@ -102,6 +103,7 @@
   std::vector<ProcessedActionProto> processed_actions_;
   std::string last_server_payload_;
   AtEnd at_end_;
+  bool should_stop_script_;
 
   base::WeakPtrFactory<ScriptExecutor> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(ScriptExecutor);
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index a92b6bf..720829d 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -289,6 +289,14 @@
   optional string title = 2;
 }
 
+message AutofillStrings {
+  optional string fill_manually = 1;
+
+  optional string fill_form = 2;
+
+  optional string check_form = 3;
+}
+
 // Fill a form with an address if there is, otherwise fail this action.
 message UseAddressProto {
   // Message used to indicate what form fields should be filled with what
@@ -328,6 +336,8 @@
 
   // An optional list of fields that should be filled by this action.
   repeated RequiredField required_fields = 6;
+
+  optional AutofillStrings strings = 8;
 }
 
 // Fill a form with a credit card if there is, otherwise fail this action.
@@ -338,6 +348,8 @@
 
   // A reference to the card number field in the form that should be filled.
   optional ElementReferenceProto form_field_element = 3;
+
+  optional AutofillStrings strings = 8;
 }
 
 // Ask Chrome to wait for an element in the DOM. This can be used to only
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index 9231b0fd..1f42706 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -20,9 +20,9 @@
 #include "components/browser_sync/browser_sync_switches.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/dom_distiller/core/dom_distiller_features.h"
-#include "components/history/core/browser/history_delete_directives_data_type_controller.h"
-#include "components/history/core/browser/history_delete_directives_model_type_controller.h"
-#include "components/history/core/browser/typed_url_model_type_controller.h"
+#include "components/history/core/browser/sync/history_delete_directives_data_type_controller.h"
+#include "components/history/core/browser/sync/history_delete_directives_model_type_controller.h"
+#include "components/history/core/browser/sync/typed_url_model_type_controller.h"
 #include "components/password_manager/core/browser/password_data_type_controller.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/browser_sync/profile_sync_test_util.cc b/components/browser_sync/profile_sync_test_util.cc
index cc965ce..cc898c06 100644
--- a/components/browser_sync/profile_sync_test_util.cc
+++ b/components/browser_sync/profile_sync_test_util.cc
@@ -13,8 +13,8 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/bookmarks/browser/bookmark_model.h"
-#include "components/history/core/browser/history_model_worker.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/sync/history_model_worker.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync/base/sync_prefs.h"
diff --git a/components/certificate_transparency/log_dns_client.cc b/components/certificate_transparency/log_dns_client.cc
index 311ee2e..0464ee62 100644
--- a/components/certificate_transparency/log_dns_client.cc
+++ b/components/certificate_transparency/log_dns_client.cc
@@ -23,7 +23,7 @@
 #include "net/base/sys_addrinfo.h"
 #include "net/cert/merkle_audit_proof.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_response.h"
 #include "net/dns/dns_transaction.h"
diff --git a/components/certificate_transparency/log_dns_client_unittest.cc b/components/certificate_transparency/log_dns_client_unittest.cc
index 0cacc9f..df255fa8 100644
--- a/components/certificate_transparency/log_dns_client_unittest.cc
+++ b/components/certificate_transparency/log_dns_client_unittest.cc
@@ -23,7 +23,7 @@
 #include "net/cert/merkle_audit_proof.h"
 #include "net/cert/signed_certificate_timestamp.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 #include "net/log/net_log.h"
 #include "net/test/gtest_util.h"
diff --git a/components/certificate_transparency/mock_log_dns_traffic.cc b/components/certificate_transparency/mock_log_dns_traffic.cc
index 69d9578..d04be543 100644
--- a/components/certificate_transparency/mock_log_dns_traffic.cc
+++ b/components/certificate_transparency/mock_log_dns_traffic.cc
@@ -15,6 +15,7 @@
 #include "base/sys_byteorder.h"
 #include "base/test/test_timeouts.h"
 #include "net/dns/dns_client.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_query.h"
 #include "net/dns/dns_util.h"
diff --git a/components/certificate_transparency/mock_log_dns_traffic.h b/components/certificate_transparency/mock_log_dns_traffic.h
index 7ce4dfe..60b080f 100644
--- a/components/certificate_transparency/mock_log_dns_traffic.h
+++ b/components/certificate_transparency/mock_log_dns_traffic.h
@@ -15,9 +15,12 @@
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
 #include "net/socket/socket_test_util.h"
 
+namespace net {
+struct DnsConfig;
+}
+
 namespace certificate_transparency {
 
 // Mocks DNS requests and responses for a Certificate Transparency (CT) log.
diff --git a/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom b/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom
index d0647e730..00cfec8c 100644
--- a/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom
+++ b/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom
@@ -65,5 +65,6 @@
   //        returned.
   // Returns:
   //  - success: indicates if the extension removal was successful.
-  DisableExtensions(array<ExtensionId> extension_ids) => (bool success);
+  [MinVersion=2] DisableExtensions(array<ExtensionId> extension_ids)
+      => (bool success);
 };
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc
index fa28ae3d..c8f4b63 100644
--- a/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -117,6 +117,7 @@
   registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls);
   registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls);
   registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls);
+  registry->RegisterListPref(prefs::kManagedWebUsbAllowDevicesForUrls);
   registry->RegisterListPref(prefs::kManagedWebUsbAskForUrls);
   registry->RegisterListPref(prefs::kManagedWebUsbBlockedForUrls);
   // Preferences for default content setting policies. If a policy is not set of
diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc
index ed5f931..9e18100 100644
--- a/components/content_settings/core/common/pref_names.cc
+++ b/components/content_settings/core/common/pref_names.cc
@@ -73,6 +73,8 @@
     "profile.managed_popups_allowed_for_urls";
 const char kManagedPopupsBlockedForUrls[] =
     "profile.managed_popups_blocked_for_urls";
+const char kManagedWebUsbAllowDevicesForUrls[] =
+    "profile.managed_web_usb_allow_devices_for_urls";
 const char kManagedWebUsbAskForUrls[] = "profile.managed_web_usb_ask_for_urls";
 const char kManagedWebUsbBlockedForUrls[] =
     "profile.managed_web_usb_blocked_for_urls";
diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h
index af5e4db..4ce1bf8 100644
--- a/components/content_settings/core/common/pref_names.h
+++ b/components/content_settings/core/common/pref_names.h
@@ -43,6 +43,7 @@
 extern const char kManagedNotificationsAllowedForUrls[];
 extern const char kManagedNotificationsBlockedForUrls[];
 extern const char kManagedAutoSelectCertificateForUrls[];
+extern const char kManagedWebUsbAllowDevicesForUrls[];
 extern const char kManagedWebUsbAskForUrls[];
 extern const char kManagedWebUsbBlockedForUrls[];
 
diff --git a/components/crash/content/browser/crash_metrics_reporter_android.cc b/components/crash/content/browser/crash_metrics_reporter_android.cc
index 3a01a78f..14394505 100644
--- a/components/crash/content/browser/crash_metrics_reporter_android.cc
+++ b/components/crash/content/browser/crash_metrics_reporter_android.cc
@@ -4,12 +4,10 @@
 
 #include "components/crash/content/browser/crash_metrics_reporter_android.h"
 
-#include "base/debug/dump_without_crashing.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/optional.h"
-#include "base/rand_util.h"
 #include "components/crash/content/browser/crash_dump_manager_android.h"
 
 namespace crash_reporter {
@@ -151,12 +149,6 @@
 
   if (info.process_type == content::PROCESS_TYPE_GPU && app_foreground &&
       android_oom_kill) {
-    constexpr int kCrashDumpFrequency = 20;
-    if (base::RandInt(1, kCrashDumpFrequency) == kCrashDumpFrequency) {
-      // Diagnostic crash dump to investigate crbug.com/879259.
-      base::debug::DumpWithoutCrashing();
-    }
-
     ReportCrashCount(ProcessedCrashCounts::kGpuForegroundOom, &reported_counts);
   }
 
diff --git a/components/cronet/BUILD.gn b/components/cronet/BUILD.gn
index 8cf7b62..2804fc69 100644
--- a/components/cronet/BUILD.gn
+++ b/components/cronet/BUILD.gn
@@ -2,10 +2,24 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
 import("//build/util/process_version.gni")
 import("//build/util/version.gni")
 import("//testing/test.gni")
 
+declare_args() {
+  # If set to true, this will remove histogram manager to reduce binary size.
+  disable_histogram_support = false
+}
+
+# Disable histogram support is not allowed on Android.
+assert(!disable_histogram_support || !is_android)
+
+buildflag_header("cronet_buildflags") {
+  header = "cronet_buildflags.h"
+  flags = [ "DISABLE_HISTOGRAM_SUPPORT=$disable_histogram_support" ]
+}
+
 process_version("cronet_version_header") {
   template_file = "//components/cronet/version.h.in"
   sources = [
@@ -40,6 +54,7 @@
     "url_request_context_config.h",
   ]
   deps = [
+    ":cronet_buildflags",
     ":cronet_version_header",
     "//base",
     "//components/metrics:metrics",
@@ -47,6 +62,17 @@
     "//net",
     "//third_party/metrics_proto",
   ]
+
+  if (disable_histogram_support) {
+    sources -= [
+      "histogram_manager.cc",
+      "histogram_manager.h",
+    ]
+    deps -= [
+      "//components/metrics:metrics",
+      "//third_party/metrics_proto",
+    ]
+  }
 }
 
 # Unit tests for Cronet common implementation.
@@ -65,6 +91,10 @@
     "stale_host_resolver_unittest.cc",
     "url_request_context_config_unittest.cc",
   ]
+
+  if (disable_histogram_support) {
+    sources -= [ "histogram_manager_unittest.cc" ]
+  }
 }
 
 # For platforms on which the native Cronet library is used, build the library,
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index 8ef1dfe..5fce3410 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -40,6 +40,7 @@
 _cronet_deps = [
   ":generate_accept_languages",
   "//base:base",
+  "//components/cronet:cronet_buildflags",
   "//components/cronet:cronet_common",
   "//components/cronet:cronet_version_header",
   "//components/cronet/native:cronet_native_impl",
@@ -141,7 +142,6 @@
     "//base/test:test_support",
     "//components/cronet:cronet_common_unittests",
     "//components/cronet/native:cronet_native_unittests",
-    "//components/metrics",
     "//net",
     "//testing/gtest",
   ]
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index 492ea9e..36ebff436 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -20,6 +20,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
+#include "components/cronet/cronet_buildflags.h"
 #include "components/cronet/cronet_global_state.h"
 #include "components/cronet/cronet_prefs_manager.h"
 #include "components/cronet/histogram_manager.h"
@@ -440,8 +441,12 @@
 
 std::vector<uint8_t> CronetEnvironment::GetHistogramDeltas() {
   std::vector<uint8_t> data;
+#if BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
+  NOTREACHED() << "Histogram support is disabled";
+#else   // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
   if (!HistogramManager::GetInstance()->GetDeltas(&data))
     return std::vector<uint8_t>();
+#endif  // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
   return data;
 }
 
diff --git a/components/cronet/ios/test/BUILD.gn b/components/cronet/ios/test/BUILD.gn
index 2a2a30f..a25b6570 100644
--- a/components/cronet/ios/test/BUILD.gn
+++ b/components/cronet/ios/test/BUILD.gn
@@ -29,6 +29,7 @@
   deps = [
     "//base",
     "//base:i18n",
+    "//components/cronet:cronet_buildflags",
     "//components/cronet/ios:cronet_framework+link",
     "//components/cronet/native/test:cronet_native_tests",
     "//components/cronet/test:test_support",
diff --git a/components/cronet/ios/test/cronet_http_test.mm b/components/cronet/ios/test/cronet_http_test.mm
index 0217d96..19b4741 100644
--- a/components/cronet/ios/test/cronet_http_test.mm
+++ b/components/cronet/ios/test/cronet_http_test.mm
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
+#include "components/cronet/cronet_buildflags.h"
 #include "components/cronet/ios/test/cronet_test_base.h"
 #include "components/cronet/ios/test/start_cronet.h"
 #include "components/cronet/test/test_server.h"
@@ -180,7 +181,13 @@
             base::SysNSStringToUTF8([delegate_ responseBody]));
 }
 
-TEST_F(HttpTest, GetGlobalMetricsDeltas) {
+// https://crbug.com/830005 Disable histogram support to reduce binary size.
+#if BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
+#define MAYBE_GetGlobalMetricsDeltas DISABLED_GetGlobalMetricsDeltas
+#else  // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
+#define MAYBE_GetGlobalMetricsDeltas GetGlobalMetricsDeltas
+#endif  // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
+TEST_F(HttpTest, MAYBE_GetGlobalMetricsDeltas) {
   NSData* delta1 = [Cronet getGlobalMetricsDeltas];
   NSURL* url = net::NSURLWithGURL(net::QuicSimpleTestServer::GetSimpleURL());
   NSURLSessionDataTask* task = [session_ dataTaskWithURL:url];
diff --git a/components/cronet/stale_host_resolver_unittest.cc b/components/cronet/stale_host_resolver_unittest.cc
index df805c31..8cd15cd 100644
--- a/components/cronet/stale_host_resolver_unittest.cc
+++ b/components/cronet/stale_host_resolver_unittest.cc
@@ -25,6 +25,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
 #include "net/cert/cert_verifier.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_hosts.h"
 #include "net/dns/dns_test_util.h"
 #include "net/dns/host_resolver_impl.h"
diff --git a/components/feed/DEPS b/components/feed/DEPS
index d58e934..96e0352 100644
--- a/components/feed/DEPS
+++ b/components/feed/DEPS
@@ -18,6 +18,7 @@
   "+services/network/public/mojom",
   "+services/network/test",
   "+third_party/zlib/google",
+  "+ui/base/mojo",
   "+ui/gfx/geometry",
   "+ui/gfx/image",
  ]
diff --git a/components/feed/core/BUILD.gn b/components/feed/core/BUILD.gn
index f2732b3..68e34e0 100644
--- a/components/feed/core/BUILD.gn
+++ b/components/feed/core/BUILD.gn
@@ -26,6 +26,8 @@
     "feed_journal_mutation.h",
     "feed_journal_operation.cc",
     "feed_journal_operation.h",
+    "feed_logging_metrics.cc",
+    "feed_logging_metrics.h",
     "feed_networking_host.cc",
     "feed_networking_host.h",
     "feed_scheduler_host.cc",
@@ -47,6 +49,7 @@
     "//components/image_fetcher/core:core",
     "//components/leveldb_proto",
     "//net",
+    "//ui/base/mojo:mojo",
   ]
 
   deps = [
@@ -81,6 +84,7 @@
     "feed_image_manager_unittest.cc",
     "feed_journal_database_unittest.cc",
     "feed_journal_mutation_unittest.cc",
+    "feed_logging_metrics_unittest.cc",
     "feed_networking_host_unittest.cc",
     "feed_scheduler_host_unittest.cc",
     "refresh_throttler_unittest.cc",
diff --git a/components/feed/core/feed_logging_metrics.cc b/components/feed/core/feed_logging_metrics.cc
new file mode 100644
index 0000000..1b0eca7
--- /dev/null
+++ b/components/feed/core/feed_logging_metrics.cc
@@ -0,0 +1,186 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/feed_logging_metrics.h"
+
+#include <cmath>
+#include <string>
+#include <type_traits>
+
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "ui/base/mojo/window_open_disposition.mojom.h"
+
+namespace feed {
+namespace metrics {
+
+namespace {
+
+// The constant integers(bucket sizes) and strings(UMA names) in this file need
+// matching with Zine's in the file
+// components/ntp_snippets/content_suggestions_metrics.cc. The purpose to have
+// identical bucket sizes and names with Zine is for comparing Feed with Zine
+// easily. After Zine is deprecated, we can change the values if we needed.
+
+const int kMaxSuggestionsTotal = 50;
+
+// Keep in sync with MAX_SUGGESTIONS_PER_SECTION in NewTabPageUma.java.
+const int kMaxSuggestionsForArticle = 20;
+
+const char kHistogramArticlesUsageTimeLocal[] =
+    "NewTabPage.ContentSuggestions.UsageTimeLocal";
+
+// Records ContentSuggestions usage. Therefore the day is sliced into 20min
+// buckets. Depending on the current local time the count of the corresponding
+// bucket is increased.
+void RecordContentSuggestionsUsage() {
+  const int kBucketSizeMins = 20;
+  const int kNumBuckets = 24 * 60 / kBucketSizeMins;
+
+  base::Time::Exploded now_exploded;
+  base::Time::Now().LocalExplode(&now_exploded);
+  int bucket = (now_exploded.hour * 60 + now_exploded.minute) / kBucketSizeMins;
+
+  const char* kWeekdayNames[] = {"Sunday",   "Monday", "Tuesday", "Wednesday",
+                                 "Thursday", "Friday", "Saturday"};
+  std::string histogram_name(
+      base::StringPrintf("%s.%s", kHistogramArticlesUsageTimeLocal,
+                         kWeekdayNames[now_exploded.day_of_week]));
+  base::UmaHistogramExactLinear(histogram_name, bucket, kNumBuckets);
+  UMA_HISTOGRAM_EXACT_LINEAR(kHistogramArticlesUsageTimeLocal, bucket,
+                             kNumBuckets);
+
+  base::RecordAction(
+      base::UserMetricsAction("NewTabPage_ContentSuggestions_ArticlesUsage"));
+}
+
+int ToUMAScore(float score) {
+  // Scores are typically reported in a range of (0,1]. As UMA does not support
+  // floats, we put them on a discrete scale of [1,10]. We keep the extra bucket
+  // 11 for unexpected over-flows as we want to distinguish them from scores
+  // close to 1. For instance, the discrete value 1 represents score values
+  // within (0.0, 0.1].
+  return ceil(score * 10);
+}
+
+}  // namespace
+
+void OnPageShown(const int suggestions_count) {
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible",
+      suggestions_count, kMaxSuggestionsTotal);
+}
+
+void OnSuggestionShown(int position,
+                       base::Time publish_date,
+                       float score,
+                       base::Time fetch_date) {
+  UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.Shown", position,
+                             kMaxSuggestionsTotal);
+
+  base::TimeDelta age = base::Time::Now() - publish_date;
+  UMA_HISTOGRAM_CUSTOM_TIMES("NewTabPage.ContentSuggestions.ShownAge.Articles",
+                             age, base::TimeDelta::FromSeconds(1),
+                             base::TimeDelta::FromDays(7), 100);
+
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.ShownScoreNormalized.Articles",
+      ToUMAScore(score), 11);
+
+  // Records the time since the fetch time of the displayed snippet.
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+      "NewTabPage.ContentSuggestions.TimeSinceSuggestionFetched",
+      base::Time::Now() - fetch_date, base::TimeDelta::FromSeconds(1),
+      base::TimeDelta::FromDays(7),
+      /*bucket_count=*/100);
+
+  // When the first of the articles suggestions is shown, then we count this as
+  // a single usage of content suggestions.
+  if (position == 0) {
+    RecordContentSuggestionsUsage();
+  }
+}
+
+void OnSuggestionOpened(int position,
+                        base::Time publish_date,
+                        float score,
+                        WindowOpenDisposition disposition) {
+  UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.Opened", position,
+                             kMaxSuggestionsTotal);
+
+  base::TimeDelta age = base::Time::Now() - publish_date;
+  UMA_HISTOGRAM_CUSTOM_TIMES("NewTabPage.ContentSuggestions.OpenedAge.Articles",
+                             age, base::TimeDelta::FromSeconds(1),
+                             base::TimeDelta::FromDays(7), 100);
+
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.OpenedScoreNormalized.Articles",
+      ToUMAScore(score), 11);
+
+  // We use WindowOpenDisposition::MAX_VALUE + 1 for |value_max| since MAX_VALUE
+  // itself is a valid (and used) enum value.
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.OpenDisposition.Articles",
+      static_cast<int>(disposition),
+      static_cast<int>(WindowOpenDisposition::MAX_VALUE) + 1);
+
+  RecordContentSuggestionsUsage();
+
+  base::RecordAction(base::UserMetricsAction("Suggestions.Content.Opened"));
+}
+
+void OnSuggestionMenuOpened(int position,
+                            base::Time publish_date,
+                            float score) {
+  UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.MenuOpened",
+                             position, kMaxSuggestionsTotal);
+
+  base::TimeDelta age = base::Time::Now() - publish_date;
+  UMA_HISTOGRAM_CUSTOM_TIMES(
+      "NewTabPage.ContentSuggestions.MenuOpenedAge.Articles", age,
+      base::TimeDelta::FromSeconds(1), base::TimeDelta::FromDays(7), 100);
+
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.MenuOpenedScoreNormalized.Articles",
+      ToUMAScore(score), 11);
+}
+
+void OnSuggestionDismissed(int position, bool visited) {
+  if (visited) {
+    UMA_HISTOGRAM_EXACT_LINEAR("NewTabPage.ContentSuggestions.DismissedVisited",
+                               position, kMaxSuggestionsTotal);
+  } else {
+    UMA_HISTOGRAM_EXACT_LINEAR(
+        "NewTabPage.ContentSuggestions.DismissedUnvisited", position,
+        kMaxSuggestionsTotal);
+  }
+}
+
+void OnSuggestionArticleVisited(base::TimeDelta visit_time) {
+  base::UmaHistogramLongTimes(
+      "NewTabPage.ContentSuggestions.VisitDuration.Articles", visit_time);
+}
+
+void OnMoreButtonShown(int position) {
+  // The "more" card can appear in addition to the actual suggestions, so add
+  // one extra bucket to this histogram.
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.MoreButtonShown.Articles", position,
+      kMaxSuggestionsForArticle + 1);
+}
+
+void OnMoreButtonClicked(int position) {
+  // The "more" card can appear in addition to the actual suggestions, so add
+  // one extra bucket to this histogram.
+  UMA_HISTOGRAM_EXACT_LINEAR(
+      "NewTabPage.ContentSuggestions.MoreButtonClicked.Articles", position,
+      kMaxSuggestionsForArticle + 1);
+}
+
+}  // namespace metrics
+}  // namespace feed
diff --git a/components/feed/core/feed_logging_metrics.h b/components/feed/core/feed_logging_metrics.h
new file mode 100644
index 0000000..a7d16b9
--- /dev/null
+++ b/components/feed/core/feed_logging_metrics.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEED_CORE_FEED_LOGGING_METRICS_H_
+#define COMPONENTS_FEED_CORE_FEED_LOGGING_METRICS_H_
+
+namespace base {
+class Time;
+class TimeDelta;
+}  // namespace base
+
+enum class WindowOpenDisposition;
+
+namespace feed {
+namespace metrics {
+
+// |suggestions_count| contains how many cards show to users. It does not depend
+// on whether the user actually saw the cards.
+void OnPageShown(const int suggestions_count);
+
+// Should only be called once per NTP for each suggestion.
+void OnSuggestionShown(int position,
+                       base::Time publish_date,
+                       float score,
+                       base::Time fetch_date);
+
+void OnSuggestionOpened(int position,
+                        base::Time publish_date,
+                        float score,
+                        WindowOpenDisposition disposition);
+
+void OnSuggestionMenuOpened(int position, base::Time publish_date, float score);
+
+void OnSuggestionDismissed(int position, bool visited);
+
+void OnSuggestionArticleVisited(base::TimeDelta visit_time);
+
+// Should only be called once per NTP for each "more" button.
+void OnMoreButtonShown(int position);
+
+void OnMoreButtonClicked(int position);
+
+}  // namespace metrics
+}  // namespace feed
+
+#endif  // COMPONENTS_FEED_CORE_FEED_LOGGING_METRICS_H_
diff --git a/components/feed/core/feed_logging_metrics_unittest.cc b/components/feed/core/feed_logging_metrics_unittest.cc
new file mode 100644
index 0000000..59baf3dc
--- /dev/null
+++ b/components/feed/core/feed_logging_metrics_unittest.cc
@@ -0,0 +1,91 @@
+// 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/feed/core/feed_logging_metrics.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/time/time.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/mojo/window_open_disposition.mojom.h"
+
+namespace feed {
+namespace metrics {
+namespace {
+
+using testing::ElementsAre;
+using testing::IsEmpty;
+
+// This needs to keep in sync with ActionType in third_party/feed/src/src/main/
+// java/com/google/android/libraries/feed/host/logging/ActionType.java.
+enum FeedActionType {
+  UNKNOWN = -1,
+  OPEN_URL = 1,
+  OPEN_URL_INCOGNITO = 2,
+  OPEN_URL_NEW_WINDOW = 3,
+  OPEN_URL_NEW_TAB = 4,
+  DOWNLOAD = 5,
+};
+
+TEST(FeedLoggingMetricsTest, ShouldLogOnSuggestionsShown) {
+  base::HistogramTester histogram_tester;
+  OnSuggestionShown(/*position=*/1, base::Time::Now(),
+                    /*score=*/0.01f,
+                    base::Time::Now() - base::TimeDelta::FromHours(2));
+  // Test corner cases for score.
+  OnSuggestionShown(/*position=*/2, base::Time::Now(),
+                    /*score=*/0.0f,
+                    base::Time::Now() - base::TimeDelta::FromHours(2));
+  OnSuggestionShown(/*position=*/3, base::Time::Now(),
+                    /*score=*/1.0f,
+                    base::Time::Now() - base::TimeDelta::FromHours(2));
+  OnSuggestionShown(/*position=*/4, base::Time::Now(),
+                    /*score=*/8.0f,
+                    base::Time::Now() - base::TimeDelta::FromHours(2));
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.ContentSuggestions.Shown"),
+      ElementsAre(base::Bucket(/*min=*/1, /*count=*/1),
+                  base::Bucket(/*min=*/2, /*count=*/1),
+                  base::Bucket(/*min=*/3, /*count=*/1),
+                  base::Bucket(/*min=*/4, /*count=*/1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(
+          "NewTabPage.ContentSuggestions.ShownScoreNormalized.Articles"),
+      ElementsAre(base::Bucket(/*min=*/0, /*count=*/1),
+                  base::Bucket(/*min=*/1, /*count=*/1),
+                  base::Bucket(/*min=*/10, /*count=*/1),
+                  base::Bucket(/*min=*/11, /*count=*/1)));
+}
+
+TEST(FeedLoggingMetricsTest, ShouldLogOnPageShown) {
+  base::HistogramTester histogram_tester;
+  OnPageShown(/*content_count=*/10);
+  EXPECT_THAT(histogram_tester.GetAllSamples(
+                  "NewTabPage.ContentSuggestions.CountOnNtpOpenedIfVisible"),
+              ElementsAre(base::Bucket(/*min=*/10, /*count=*/1)));
+}
+
+TEST(FeedLoggingMetricsTest, ShouldLogPrefetchedSuggestionsWhenOpened) {
+  base::HistogramTester histogram_tester;
+  OnSuggestionOpened(/*position=*/11, base::Time::Now(),
+                     /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB);
+  OnSuggestionOpened(/*position=*/13, base::Time::Now(),
+                     /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB);
+  OnSuggestionOpened(/*position=*/15, base::Time::Now(),
+                     /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB);
+  OnSuggestionOpened(/*position=*/23, base::Time::Now(),
+                     /*score=*/1.0f, WindowOpenDisposition::CURRENT_TAB);
+
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples("NewTabPage.ContentSuggestions.Opened"),
+      ElementsAre(base::Bucket(/*min=*/11, /*count=*/1),
+                  base::Bucket(/*min=*/13, /*count=*/1),
+                  base::Bucket(/*min=*/15, /*count=*/1),
+                  base::Bucket(/*min=*/23, /*count=*/1)));
+}
+
+}  // namespace
+}  // namespace metrics
+}  // namespace feed
diff --git a/components/gcm_driver/gcm_driver_android.cc b/components/gcm_driver/gcm_driver_android.cc
index abd293a..f54f61f8 100644
--- a/components/gcm_driver/gcm_driver_android.cc
+++ b/components/gcm_driver/gcm_driver_android.cc
@@ -19,7 +19,7 @@
 using base::android::AttachCurrentThread;
 using base::android::ConvertJavaStringToUTF8;
 using base::android::ConvertUTF8ToJavaString;
-using base::android::JavaByteArrayToByteVector;
+using base::android::JavaByteArrayToString;
 using base::android::JavaParamRef;
 
 namespace gcm {
@@ -96,9 +96,7 @@
   }
   // Convert j_raw_data from byte[] to binary std::string.
   if (j_raw_data) {
-    std::vector<uint8_t> raw_data;
-    JavaByteArrayToByteVector(env, j_raw_data, &raw_data);
-    message.raw_data.assign(raw_data.begin(), raw_data.end());
+    JavaByteArrayToString(env, j_raw_data, &message.raw_data);
 
     message_byte_size += message.raw_data.size();
   }
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn
index d0b9fd3..1fa054d 100644
--- a/components/history/core/browser/BUILD.gn
+++ b/components/history/core/browser/BUILD.gn
@@ -9,8 +9,6 @@
     "browsing_history_service.h",
     "default_top_sites_provider.cc",
     "default_top_sites_provider.h",
-    "delete_directive_handler.cc",
-    "delete_directive_handler.h",
     "domain_mixing_metrics.cc",
     "domain_mixing_metrics.h",
     "download_constants.h",
@@ -38,12 +36,6 @@
     "history_database_params.cc",
     "history_database_params.h",
     "history_db_task.h",
-    "history_delete_directives_data_type_controller.cc",
-    "history_delete_directives_data_type_controller.h",
-    "history_delete_directives_model_type_controller.cc",
-    "history_delete_directives_model_type_controller.h",
-    "history_model_worker.cc",
-    "history_model_worker.h",
     "history_service.cc",
     "history_service.h",
     "history_service_observer.h",
@@ -58,6 +50,20 @@
     "keyword_search_term.h",
     "page_usage_data.cc",
     "page_usage_data.h",
+    "sync/delete_directive_handler.cc",
+    "sync/delete_directive_handler.h",
+    "sync/history_delete_directives_data_type_controller.cc",
+    "sync/history_delete_directives_data_type_controller.h",
+    "sync/history_delete_directives_model_type_controller.cc",
+    "sync/history_delete_directives_model_type_controller.h",
+    "sync/history_model_worker.cc",
+    "sync/history_model_worker.h",
+    "sync/typed_url_model_type_controller.cc",
+    "sync/typed_url_model_type_controller.h",
+    "sync/typed_url_sync_bridge.cc",
+    "sync/typed_url_sync_bridge.h",
+    "sync/typed_url_sync_metadata_database.cc",
+    "sync/typed_url_sync_metadata_database.h",
     "thumbnail_database.cc",
     "thumbnail_database.h",
     "top_sites.cc",
@@ -72,12 +78,6 @@
     "top_sites_impl.h",
     "top_sites_observer.h",
     "top_sites_provider.h",
-    "typed_url_model_type_controller.cc",
-    "typed_url_model_type_controller.h",
-    "typed_url_sync_bridge.cc",
-    "typed_url_sync_bridge.h",
-    "typed_url_sync_metadata_database.cc",
-    "typed_url_sync_metadata_database.h",
     "url_database.cc",
     "url_database.h",
     "url_row.cc",
@@ -205,16 +205,16 @@
     "history_backend_db_unittest.cc",
     "history_backend_unittest.cc",
     "history_database_unittest.cc",
-    "history_model_worker_unittest.cc",
     "history_querying_unittest.cc",
     "history_service_unittest.cc",
     "history_types_unittest.cc",
+    "sync/history_model_worker_unittest.cc",
+    "sync/typed_url_sync_bridge_unittest.cc",
+    "sync/typed_url_sync_metadata_database_unittest.cc",
     "thumbnail_database_unittest.cc",
     "top_sites_cache_unittest.cc",
     "top_sites_database_unittest.cc",
     "top_sites_impl_unittest.cc",
-    "typed_url_sync_bridge_unittest.cc",
-    "typed_url_sync_metadata_database_unittest.cc",
     "url_database_unittest.cc",
     "url_utils_unittest.cc",
     "visit_database_unittest.cc",
diff --git a/components/history/core/browser/OWNERS b/components/history/core/browser/OWNERS
deleted file mode 100644
index 52086dd..0000000
--- a/components/history/core/browser/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file history_delete_directives_data_type_controller*=file://components/sync/OWNERS
-per-file history_delete_directives_model_type_controller*=file://components/sync/OWNERS
-per-file typed_url_model_type_controller*=file://components/sync/OWNERS
-per-file typed_url_sync_bridge*=file://components/sync/OWNERS
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index 3e9de09..8d223f0 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -33,8 +33,8 @@
 #include "components/history/core/browser/history_backend_notifier.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/history/core/browser/keyword_id.h"
+#include "components/history/core/browser/sync/typed_url_sync_bridge.h"
 #include "components/history/core/browser/thumbnail_database.h"
-#include "components/history/core/browser/typed_url_sync_bridge.h"
 #include "components/history/core/browser/visit_tracker.h"
 #include "sql/init_status.h"
 
diff --git a/components/history/core/browser/history_database.h b/components/history/core/browser/history_database.h
index 2c83c06..56f3c4a 100644
--- a/components/history/core/browser/history_database.h
+++ b/components/history/core/browser/history_database.h
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "components/history/core/browser/download_database.h"
 #include "components/history/core/browser/history_types.h"
-#include "components/history/core/browser/typed_url_sync_metadata_database.h"
+#include "components/history/core/browser/sync/typed_url_sync_metadata_database.h"
 #include "components/history/core/browser/url_database.h"
 #include "components/history/core/browser/visit_database.h"
 #include "components/history/core/browser/visitsegment_database.h"
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h
index 2612a4d0..24b23fab 100644
--- a/components/history/core/browser/history_service.h
+++ b/components/history/core/browser/history_service.h
@@ -32,9 +32,9 @@
 #include "build/build_config.h"
 #include "components/favicon_base/favicon_callback.h"
 #include "components/favicon_base/favicon_usage_data.h"
-#include "components/history/core/browser/delete_directive_handler.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/history/core/browser/keyword_id.h"
+#include "components/history/core/browser/sync/delete_directive_handler.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/sync/model/syncable_service.h"
 #include "sql/init_status.h"
diff --git a/components/history/core/browser/sync/OWNERS b/components/history/core/browser/sync/OWNERS
new file mode 100644
index 0000000..261ab18
--- /dev/null
+++ b/components/history/core/browser/sync/OWNERS
@@ -0,0 +1 @@
+file://components/sync/OWNERS
diff --git a/components/history/core/browser/delete_directive_handler.cc b/components/history/core/browser/sync/delete_directive_handler.cc
similarity index 96%
rename from components/history/core/browser/delete_directive_handler.cc
rename to components/history/core/browser/sync/delete_directive_handler.cc
index a0b737bb..71fee776 100644
--- a/components/history/core/browser/delete_directive_handler.cc
+++ b/components/history/core/browser/sync/delete_directive_handler.cc
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/history/core/browser/delete_directive_handler.h"
+#include "components/history/core/browser/sync/delete_directive_handler.h"
 
 #include <stddef.h>
 
+#include <algorithm>
+#include <map>
+#include <string>
 #include <utility>
 
 #include "base/json/json_writer.h"
@@ -127,13 +130,13 @@
         delete_directives_(delete_directive),
         post_processing_action_(post_processing_action) {}
 
+  ~DeleteDirectiveTask() override {}
+
   // Implements HistoryDBTask.
   bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) override;
   void DoneRunOnMainThread() override;
 
  private:
-  ~DeleteDirectiveTask() override {}
-
   // Process a list of global Id directives. Delete all visits to a URL in
   // time ranges of directives if the timestamp of one visit matches with one
   // global id.
@@ -286,8 +289,7 @@
   }
 }
 
-DeleteDirectiveHandler::DeleteDirectiveHandler() : weak_ptr_factory_(this) {
-}
+DeleteDirectiveHandler::DeleteDirectiveHandler() : weak_ptr_factory_(this) {}
 
 DeleteDirectiveHandler::~DeleteDirectiveHandler() {
   weak_ptr_factory_.InvalidateWeakPtrs();
@@ -303,9 +305,9 @@
     // Drop processed delete directives during startup.
     history_service->ScheduleDBTask(
         FROM_HERE,
-        std::unique_ptr<HistoryDBTask>(
-            new DeleteDirectiveTask(weak_ptr_factory_.GetWeakPtr(),
-                                    initial_sync_data, DROP_AFTER_PROCESSING)),
+        std::make_unique<DeleteDirectiveTask>(weak_ptr_factory_.GetWeakPtr(),
+                                              initial_sync_data,
+                                              DROP_AFTER_PROCESSING),
         &internal_tracker_);
   }
 }
@@ -409,9 +411,9 @@
     // in one chrome session.
     history_service->ScheduleDBTask(
         FROM_HERE,
-        std::unique_ptr<HistoryDBTask>(
-            new DeleteDirectiveTask(weak_ptr_factory_.GetWeakPtr(),
-                                    delete_directives, KEEP_AFTER_PROCESSING)),
+        std::make_unique<DeleteDirectiveTask>(weak_ptr_factory_.GetWeakPtr(),
+                                              delete_directives,
+                                              KEEP_AFTER_PROCESSING),
         &internal_tracker_);
   }
   return syncer::SyncError();
diff --git a/components/history/core/browser/delete_directive_handler.h b/components/history/core/browser/sync/delete_directive_handler.h
similarity index 92%
rename from components/history/core/browser/delete_directive_handler.h
rename to components/history/core/browser/sync/delete_directive_handler.h
index 1e18852c..61e0f07 100644
--- a/components/history/core/browser/delete_directive_handler.h
+++ b/components/history/core/browser/sync/delete_directive_handler.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 COMPONENTS_HISTORY_CORE_BROWSER_DELETE_DIRECTIVE_HANDLER_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_DELETE_DIRECTIVE_HANDLER_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_DELETE_DIRECTIVE_HANDLER_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_DELETE_DIRECTIVE_HANDLER_H_
 
 #include <stdint.h>
 
 #include <memory>
+#include <set>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -81,4 +82,4 @@
 
 }  // namespace history
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_DELETE_DIRECTIVE_HANDLER_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_DELETE_DIRECTIVE_HANDLER_H_
diff --git a/components/history/core/browser/history_delete_directives_data_type_controller.cc b/components/history/core/browser/sync/history_delete_directives_data_type_controller.cc
similarity index 86%
rename from components/history/core/browser/history_delete_directives_data_type_controller.cc
rename to components/history/core/browser/sync/history_delete_directives_data_type_controller.cc
index b74d5ec..f36863f 100644
--- a/components/history/core/browser/history_delete_directives_data_type_controller.cc
+++ b/components/history/core/browser/sync/history_delete_directives_data_type_controller.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/history/core/browser/history_delete_directives_data_type_controller.h"
+#include "components/history/core/browser/sync/history_delete_directives_data_type_controller.h"
 
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/sync/driver/sync_client.h"
@@ -21,8 +21,7 @@
       sync_client_(sync_client) {}
 
 HistoryDeleteDirectivesDataTypeController::
-    ~HistoryDeleteDirectivesDataTypeController() {
-}
+    ~HistoryDeleteDirectivesDataTypeController() {}
 
 bool HistoryDeleteDirectivesDataTypeController::ReadyForStart() const {
   DCHECK(CalledOnValidThread());
@@ -58,11 +57,9 @@
 
   if (sync_client_->GetSyncService()->HasObserver(this))
     sync_client_->GetSyncService()->RemoveObserver(this);
-  syncer::SyncError error(
-      FROM_HERE,
-      syncer::SyncError::DATATYPE_POLICY_ERROR,
-      "Delete directives not supported with encryption.",
-      type());
+  syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_POLICY_ERROR,
+                          "Delete directives not supported with encryption.",
+                          type());
   CreateErrorHandler()->OnUnrecoverableError(error);
   return true;
 }
diff --git a/components/history/core/browser/history_delete_directives_data_type_controller.h b/components/history/core/browser/sync/history_delete_directives_data_type_controller.h
similarity index 83%
rename from components/history/core/browser/history_delete_directives_data_type_controller.h
rename to components/history/core/browser/sync/history_delete_directives_data_type_controller.h
index 2e85c01..30b8a78f 100644
--- a/components/history/core/browser/history_delete_directives_data_type_controller.h
+++ b/components/history/core/browser/sync/history_delete_directives_data_type_controller.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 COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
 
 #include "base/macros.h"
 #include "components/sync/driver/async_directory_type_controller.h"
@@ -42,4 +42,4 @@
 
 }  // namespace browser_sync
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_DATA_TYPE_CONTROLLER_H_
diff --git a/components/history/core/browser/history_delete_directives_model_type_controller.cc b/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
similarity index 96%
rename from components/history/core/browser/history_delete_directives_model_type_controller.cc
rename to components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
index 7f7111c..9b719bd 100644
--- a/components/history/core/browser/history_delete_directives_model_type_controller.cc
+++ b/components/history/core/browser/sync/history_delete_directives_model_type_controller.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/history/core/browser/history_delete_directives_model_type_controller.h"
+#include "components/history/core/browser/sync/history_delete_directives_model_type_controller.h"
 
 #include <utility>
 
diff --git a/components/history/core/browser/history_delete_directives_model_type_controller.h b/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
similarity index 84%
rename from components/history/core/browser/history_delete_directives_model_type_controller.h
rename to components/history/core/browser/sync/history_delete_directives_model_type_controller.h
index 07c3521e..516b35d 100644
--- a/components/history/core/browser/history_delete_directives_model_type_controller.h
+++ b/components/history/core/browser/sync/history_delete_directives_model_type_controller.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 COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
 
 #include "base/macros.h"
 #include "components/sync/driver/sync_service_observer.h"
@@ -48,4 +48,4 @@
 
 }  // namespace browser_sync
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_DELETE_DIRECTIVES_MODEL_TYPE_CONTROLLER_H_
diff --git a/components/history/core/browser/history_model_worker.cc b/components/history/core/browser/sync/history_model_worker.cc
similarity index 94%
rename from components/history/core/browser/history_model_worker.cc
rename to components/history/core/browser/sync/history_model_worker.cc
index c68b377e..a309b734 100644
--- a/components/history/core/browser/history_model_worker.cc
+++ b/components/history/core/browser/sync/history_model_worker.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/history/core/browser/history_model_worker.h"
+#include "components/history/core/browser/sync/history_model_worker.h"
 
 #include <memory>
 #include <utility>
@@ -14,7 +14,7 @@
 
 class WorkerTask : public history::HistoryDBTask {
  public:
-  WorkerTask(base::OnceClosure work) : work_(std::move(work)) {}
+  explicit WorkerTask(base::OnceClosure work) : work_(std::move(work)) {}
 
   bool RunOnDBThread(history::HistoryBackend* backend,
                      history::HistoryDatabase* db) override {
diff --git a/components/history/core/browser/history_model_worker.h b/components/history/core/browser/sync/history_model_worker.h
similarity index 88%
rename from components/history/core/browser/history_model_worker.h
rename to components/history/core/browser/sync/history_model_worker.h
index 1588ab5..4bcacaf 100644
--- a/components/history/core/browser/history_model_worker.h
+++ b/components/history/core/browser/sync/history_model_worker.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 COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_MODEL_WORKER_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_MODEL_WORKER_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
 
 #include <memory>
 
@@ -52,4 +52,4 @@
 
 }  // namespace browser_sync
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_MODEL_WORKER_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
diff --git a/components/history/core/browser/history_model_worker_unittest.cc b/components/history/core/browser/sync/history_model_worker_unittest.cc
similarity index 97%
rename from components/history/core/browser/history_model_worker_unittest.cc
rename to components/history/core/browser/sync/history_model_worker_unittest.cc
index fc5aa08..b4606ad 100644
--- a/components/history/core/browser/history_model_worker_unittest.cc
+++ b/components/history/core/browser/sync/history_model_worker_unittest.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/history/core/browser/history_model_worker.h"
+#include "components/history/core/browser/sync/history_model_worker.h"
 
 #include <memory>
 #include <utility>
@@ -24,7 +24,8 @@
 
 class HistoryServiceMock : public history::HistoryService {
  public:
-  HistoryServiceMock(scoped_refptr<base::SingleThreadTaskRunner> history_thread)
+  explicit HistoryServiceMock(
+      scoped_refptr<base::SingleThreadTaskRunner> history_thread)
       : history_thread_(std::move(history_thread)) {}
 
   base::CancelableTaskTracker::TaskId ScheduleDBTask(
diff --git a/components/history/core/browser/typed_url_model_type_controller.cc b/components/history/core/browser/sync/typed_url_model_type_controller.cc
similarity index 96%
rename from components/history/core/browser/typed_url_model_type_controller.cc
rename to components/history/core/browser/sync/typed_url_model_type_controller.cc
index da489acc..2b1dc8b 100644
--- a/components/history/core/browser/typed_url_model_type_controller.cc
+++ b/components/history/core/browser/sync/typed_url_model_type_controller.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/history/core/browser/typed_url_model_type_controller.h"
+#include "components/history/core/browser/sync/typed_url_model_type_controller.h"
 
 #include <memory>
 
diff --git a/components/history/core/browser/typed_url_model_type_controller.h b/components/history/core/browser/sync/typed_url_model_type_controller.h
similarity index 82%
rename from components/history/core/browser/typed_url_model_type_controller.h
rename to components/history/core/browser/sync/typed_url_model_type_controller.h
index 8cbc6d0..51280ad 100644
--- a/components/history/core/browser/typed_url_model_type_controller.h
+++ b/components/history/core/browser/sync/typed_url_model_type_controller.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 COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
-#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_MODEL_TYPE_CONTROLLER_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_MODEL_TYPE_CONTROLLER_H_
 
 #include "components/prefs/pref_change_registrar.h"
 #include "components/sync/driver/model_type_controller.h"
@@ -40,4 +40,4 @@
 
 }  // namespace history
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_MODEL_TYPE_CONTROLLER_H__
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_MODEL_TYPE_CONTROLLER_H_
diff --git a/components/history/core/browser/typed_url_sync_bridge.cc b/components/history/core/browser/sync/typed_url_sync_bridge.cc
similarity index 99%
rename from components/history/core/browser/typed_url_sync_bridge.cc
rename to components/history/core/browser/sync/typed_url_sync_bridge.cc
index 4b6e891c..371106c 100644
--- a/components/history/core/browser/typed_url_sync_bridge.cc
+++ b/components/history/core/browser/sync/typed_url_sync_bridge.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/history/core/browser/typed_url_sync_bridge.h"
+#include "components/history/core/browser/sync/typed_url_sync_bridge.h"
 
 #include <memory>
 
@@ -94,8 +94,7 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
 }
 
-TypedURLSyncBridge::~TypedURLSyncBridge() {
-}
+TypedURLSyncBridge::~TypedURLSyncBridge() {}
 
 std::unique_ptr<MetadataChangeList>
 TypedURLSyncBridge::CreateMetadataChangeList() {
@@ -515,7 +514,7 @@
     // the history DB has an inaccurate count for some reason (there's been
     // bugs in the history code in the past which has left users in the wild
     // with incorrect counts - http://crbug.com/84258).
-    DCHECK(typed_count > 0);
+    DCHECK_GT(typed_count, 0);
 
     if (typed_count > kMaxTypedUrlVisits) {
       only_typed = true;
@@ -772,7 +771,7 @@
     URLRows* new_synced_urls,
     TypedURLVisitVector* new_synced_visits,
     URLRows* updated_synced_urls) {
-  DCHECK(server_typed_url.visits_size() != 0);
+  DCHECK_NE(0, server_typed_url.visits_size());
   DCHECK_EQ(server_typed_url.visits_size(),
             server_typed_url.visit_transitions_size());
 
@@ -878,7 +877,7 @@
         // Should never be possible to delete all the items, since the
         // visit vector contains newer local visits it will keep and/or the
         // visits in typed_url.visits newer than older local visits.
-        DCHECK(visits.size() > 0);
+        DCHECK_GT(visits.size(), 0U);
       }
       DCHECK_EQ(new_url.last_visit().ToInternalValue(),
                 visits.back().visit_time.ToInternalValue());
diff --git a/components/history/core/browser/typed_url_sync_bridge.h b/components/history/core/browser/sync/typed_url_sync_bridge.h
similarity index 96%
rename from components/history/core/browser/typed_url_sync_bridge.h
rename to components/history/core/browser/sync/typed_url_sync_bridge.h
index 39b30756..35e1939 100644
--- a/components/history/core/browser/typed_url_sync_bridge.h
+++ b/components/history/core/browser/sync/typed_url_sync_bridge.h
@@ -2,12 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_BRIDGE_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_BRIDGE_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_BRIDGE_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_BRIDGE_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/scoped_observer.h"
 #include "components/history/core/browser/history_backend_observer.h"
-#include "components/history/core/browser/typed_url_sync_metadata_database.h"
+#include "components/history/core/browser/sync/typed_url_sync_metadata_database.h"
 #include "components/sync/model/metadata_change_list.h"
 #include "components/sync/model/model_type_change_processor.h"
 #include "components/sync/model/model_type_sync_bridge.h"
@@ -250,4 +257,4 @@
 
 }  // namespace history
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_BRIDGE_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_BRIDGE_H_
diff --git a/components/history/core/browser/typed_url_sync_bridge_unittest.cc b/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc
similarity index 99%
rename from components/history/core/browser/typed_url_sync_bridge_unittest.cc
rename to components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc
index e2ceafc..637336a2 100644
--- a/components/history/core/browser/typed_url_sync_bridge_unittest.cc
+++ b/components/history/core/browser/sync/typed_url_sync_bridge_unittest.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/history/core/browser/typed_url_sync_bridge.h"
+#include "components/history/core/browser/sync/typed_url_sync_bridge.h"
 
 #include <memory>
 
@@ -51,13 +51,13 @@
 const char kURL[] = "http://pie.com/";
 const char kURL2[] = "http://cookie.com/";
 
-bool URLsEqual(URLRow& row, sync_pb::TypedUrlSpecifics& specifics) {
+bool URLsEqual(URLRow& row, const sync_pb::TypedUrlSpecifics& specifics) {
   return ((row.url().spec().compare(specifics.url()) == 0) &&
           (base::UTF16ToUTF8(row.title()).compare(specifics.title()) == 0) &&
           (row.hidden() == specifics.hidden()));
 }
 
-bool URLsEqual(URLRow& lhs, URLRow& rhs) {
+bool URLsEqual(const URLRow& lhs, const URLRow& rhs) {
   // Only compare synced fields (ignore typed_count and visit_count as those
   // are maintained by the history subsystem).
   return (lhs.url().spec().compare(rhs.url().spec()) == 0) &&
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.cc b/components/history/core/browser/sync/typed_url_sync_metadata_database.cc
similarity index 98%
rename from components/history/core/browser/typed_url_sync_metadata_database.cc
rename to components/history/core/browser/sync/typed_url_sync_metadata_database.cc
index 3781898..9b95fbbe 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.cc
+++ b/components/history/core/browser/sync/typed_url_sync_metadata_database.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/history/core/browser/typed_url_sync_metadata_database.h"
+#include "components/history/core/browser/sync/typed_url_sync_metadata_database.h"
 
 #include "base/big_endian.h"
 #include "base/logging.h"
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.h b/components/history/core/browser/sync/typed_url_sync_metadata_database.h
similarity index 91%
rename from components/history/core/browser/typed_url_sync_metadata_database.h
rename to components/history/core/browser/sync/typed_url_sync_metadata_database.h
index eff5d16..e49c9c5 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.h
+++ b/components/history/core/browser/sync/typed_url_sync_metadata_database.h
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_METADATA_DATABASE_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_METADATA_DATABASE_H_
+#ifndef COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_METADATA_DATABASE_H_
+#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_METADATA_DATABASE_H_
 
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -16,7 +17,7 @@
 namespace sql {
 class Database;
 class MetaTable;
-}
+}  // namespace sql
 
 namespace history {
 
@@ -81,4 +82,4 @@
 
 }  // namespace history
 
-#endif  // COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_METADATA_DATABASE_H_
+#endif  // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_TYPED_URL_SYNC_METADATA_DATABASE_H_
diff --git a/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc b/components/history/core/browser/sync/typed_url_sync_metadata_database_unittest.cc
similarity index 98%
rename from components/history/core/browser/typed_url_sync_metadata_database_unittest.cc
rename to components/history/core/browser/sync/typed_url_sync_metadata_database_unittest.cc
index 039a423d..1274f8f 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database_unittest.cc
+++ b/components/history/core/browser/sync/typed_url_sync_metadata_database_unittest.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/history/core/browser/typed_url_sync_metadata_database.h"
+#include "components/history/core/browser/sync/typed_url_sync_metadata_database.h"
 
 #include "base/big_endian.h"
 #include "base/files/file_path.h"
diff --git a/components/invalidation/impl/invalidation_service_android.cc b/components/invalidation/impl/invalidation_service_android.cc
index 46c94f15..6377b9e 100644
--- a/components/invalidation/impl/invalidation_service_android.cc
+++ b/components/invalidation/impl/invalidation_service_android.cc
@@ -93,9 +93,8 @@
       Java_InvalidationService_getInvalidatorClientId(env, java_ref_);
 
   // Convert it into a more convenient format for C++.
-  std::vector<uint8_t> id_bytes;
-  base::android::JavaByteArrayToByteVector(env, id_bytes_java.obj(), &id_bytes);
-  std::string id(id_bytes.begin(), id_bytes.end());
+  std::string id;
+  base::android::JavaByteArrayToString(env, id_bytes_java.obj(), &id);
 
   return id;
 }
diff --git a/components/leveldb_proto/proto_database_perftest.cc b/components/leveldb_proto/proto_database_perftest.cc
index 45e5825b..9152e726 100644
--- a/components/leveldb_proto/proto_database_perftest.cc
+++ b/components/leveldb_proto/proto_database_perftest.cc
@@ -608,23 +608,55 @@
                                 kFewEntriesDistributionTestParams, false);
 }
 
-TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Single) {
+// Times out on Win.  http://crbug.com/879922
+#if defined(OS_WIN)
+#define MAYBE_DistributionTestSmall_ManyEntries_Single \
+  DISABLED_DistributionTestSmall_ManyEntries_Single
+#else
+#define MAYBE_DistributionTestSmall_ManyEntries_Single \
+  DistributionTestSmall_ManyEntries_Single
+#endif
+TEST_F(ProtoDBPerfTest, MAYBE_DistributionTestSmall_ManyEntries_Single) {
   RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries", "Single",
                                 kManyEntriesDistributionTestParams, true);
 }
 
-TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Multi) {
+// Times out on Win.  http://crbug.com/879922
+#if defined(OS_WIN)
+#define MAYBE_DistributionTestSmall_ManyEntries_Multi \
+  DISABLED_DistributionTestSmall_ManyEntries_Multi
+#else
+#define MAYBE_DistributionTestSmall_ManyEntries_Multi \
+  DistributionTestSmall_ManyEntries_Multi
+#endif
+TEST_F(ProtoDBPerfTest, MAYBE_DistributionTestSmall_ManyEntries_Multi) {
   RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries", "Multi",
                                 kManyEntriesDistributionTestParams, false);
 }
 
-TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Batch_Single) {
+// Times out on Win.  http://crbug.com/879922
+#if defined(OS_WIN)
+#define MAYBE_DistributionTestSmall_ManyEntries_Batch_Single \
+  DISABLED_DistributionTestSmall_ManyEntries_Batch_Single
+#else
+#define MAYBE_DistributionTestSmall_ManyEntries_Batch_Single \
+  DistributionTestSmall_ManyEntries_Batch_Single
+#endif
+TEST_F(ProtoDBPerfTest, MAYBE_DistributionTestSmall_ManyEntries_Batch_Single) {
   RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch",
                                 "Single", kManyEntriesDistributionTestParams,
                                 true);
 }
 
-TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Batch_Multi) {
+// Times out on Win.  http://crbug.com/879922
+#if defined(OS_WIN)
+#define MAYBE_DistributionTestSmall_ManyEntries_Batch_Multi \
+  DISABLED_DistributionTestSmall_ManyEntries_Batch_Multi
+#else
+#define MAYBE_DistributionTestSmall_ManyEntries_Batch_Multi \
+  DistributionTestSmall_ManyEntries_Batch_Multi
+#endif
+TEST_F(ProtoDBPerfTest, MAYBE_DistributionTestSmall_ManyEntries_Batch_Multi) {
   RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch",
                                 "Multi", kManyEntriesDistributionTestParams,
                                 false);
diff --git a/components/metrics/child_call_stack_profile_collector.cc b/components/metrics/child_call_stack_profile_collector.cc
index 8019390..6f5b509 100644
--- a/components/metrics/child_call_stack_profile_collector.cc
+++ b/components/metrics/child_call_stack_profile_collector.cc
@@ -11,6 +11,7 @@
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "third_party/metrics_proto/sampled_profile.pb.h"
 
 namespace metrics {
 
@@ -20,7 +21,7 @@
 
 ChildCallStackProfileCollector::ProfileState::ProfileState(
     base::TimeTicks start_timestamp,
-    SampledProfile profile)
+    std::string profile)
     : start_timestamp(start_timestamp), profile(std::move(profile)) {}
 
 ChildCallStackProfileCollector::ProfileState::~ProfileState() = default;
@@ -48,7 +49,7 @@
   if (parent_collector_) {
     for (ProfileState& state : profiles_) {
       mojom::SampledProfilePtr mojo_profile = mojom::SampledProfile::New();
-      state.profile.SerializeToString(&mojo_profile->contents);
+      mojo_profile->contents = std::move(state.profile);
       parent_collector_->Collect(state.start_timestamp,
                                  std::move(mojo_profile));
     }
@@ -77,8 +78,13 @@
     mojom::SampledProfilePtr mojo_profile = mojom::SampledProfile::New();
     profile.SerializeToString(&mojo_profile->contents);
     parent_collector_->Collect(start_timestamp, std::move(mojo_profile));
-  } else if (retain_profiles_) {
-    profiles_.push_back(ProfileState(start_timestamp, std::move(profile)));
+    return;
+  }
+
+  if (retain_profiles_) {
+    std::string serialized_profile;
+    profile.SerializeToString(&serialized_profile);
+    profiles_.emplace_back(start_timestamp, std::move(serialized_profile));
   }
 }
 
diff --git a/components/metrics/child_call_stack_profile_collector.h b/components/metrics/child_call_stack_profile_collector.h
index 27815d8..efb8d56 100644
--- a/components/metrics/child_call_stack_profile_collector.h
+++ b/components/metrics/child_call_stack_profile_collector.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_METRICS_CHILD_CALL_STACK_PROFILE_COLLECTOR_H_
 #define COMPONENTS_METRICS_CHILD_CALL_STACK_PROFILE_COLLECTOR_H_
 
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -12,7 +13,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "components/metrics/public/interfaces/call_stack_profile_collector.mojom.h"
-#include "third_party/metrics_proto/sampled_profile.pb.h"
 
 namespace service_manager {
 class InterfaceProvider;
@@ -20,6 +20,8 @@
 
 namespace metrics {
 
+class SampledProfile;
+
 // ChildCallStackProfileCollector collects stacks at startup, caching them
 // internally until a CallStackProfileCollector interface is available. If a
 // CallStackProfileCollector is provided via the InterfaceProvider supplied to
@@ -63,21 +65,21 @@
  private:
   friend class ChildCallStackProfileCollectorTest;
 
-  // Bundles together a collected profile and the collection state for
-  // storage, pending availability of the parent mojo interface. |profile|
+  // Bundles together a collected serialized profile and the collection state
+  // for storage, pending availability of the parent mojo interface. |profile|
   // is not const& because it must be passed with std::move.
   struct ProfileState {
     ProfileState();
     ProfileState(ProfileState&&);
-    ProfileState(base::TimeTicks start_timestamp, SampledProfile profile);
+    ProfileState(base::TimeTicks start_timestamp, std::string profile);
     ~ProfileState();
 
     ProfileState& operator=(ProfileState&&);
 
     base::TimeTicks start_timestamp;
 
-    // The sampled profile.
-    SampledProfile profile;
+    // The serialized sampled profile.
+    std::string profile;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(ProfileState);
diff --git a/components/metrics/child_call_stack_profile_collector_unittest.cc b/components/metrics/child_call_stack_profile_collector_unittest.cc
index bead3d95..3ced131b 100644
--- a/components/metrics/child_call_stack_profile_collector_unittest.cc
+++ b/components/metrics/child_call_stack_profile_collector_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/metrics_proto/sampled_profile.pb.h"
 
 namespace metrics {
 
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index 22a0c9d..baafe13 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -1271,6 +1271,9 @@
     INITIAL_ENROLLMENT_MODE_NONE = 0;
     // Enterprise enrollment is enforced and cannot be skipped.
     INITIAL_ENROLLMENT_MODE_ENROLLMENT_ENFORCED = 1;
+    // Zero-Touch (attestation-based) enrollment is enforced and cannot be
+    // skipped.
+    INITIAL_ENROLLMENT_MODE_ZERO_TOUCH_ENFORCED = 2;
   };
   // The server-indicated initial enrollment mode.
   optional InitialEnrollmentMode initial_enrollment_mode = 1
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index d3ce79a..2239e214c 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -485,6 +485,7 @@
         'PopupsBlockedForUrls',
         'NotificationsAllowedForUrls',
         'NotificationsBlockedForUrls',
+        "WebUsbAllowDevicesForUrls",
         'WebUsbAskForUrls',
         'WebUsbBlockedForUrls',
       ],
@@ -4189,6 +4190,50 @@
           If this policy is left not set, '3' will be used, and the user will be able to change it.''',
     },
     {
+      'name': 'WebUsbAllowDevicesForUrls',
+      'type': 'dict',
+      'schema': {
+        'type': 'array',
+        'items': {
+          'type': 'object',
+          'properties': {
+            'devices': {
+              'type': 'array',
+              'items': {
+                'type': 'object',
+                'properties': {
+                  'vendor_id': { 'type': 'integer' },
+                  'product_id': { 'type': 'integer' }
+                }
+              }
+            },
+            'url_patterns': {
+              'type': 'array',
+              'items': { 'type': 'string' }
+            }
+          },
+          'required': ['devices', 'url_patterns']
+        }
+      },
+      'supported_on': ['chrome_os:71-', 'android:71-', 'chrome.*:71-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': [{
+        'devices': [{'vendor_id': 1234, 'product_id': 5678}],
+        'url_patterns': ['https://[*].google.com'],
+      }],
+      'id': 486,
+      'caption': '''Automatically grant permission to these sites to connect to USB devices with the given vendor and product IDs.''',
+      'tags': ['website-sharing'],
+      'desc': '''Allows you to set a list of url patterns that specify which sites will automatically be granted permission to access a USB device with the given vendor and product IDs. Each item in the list must contain both devices and url patterns in order for the policy to be valid. Each item in devices can contain a vendor ID and product ID field. Any ID that is omitted is treated as a wildcard with one exception, and that exception is that a product ID cannot be specified without a vendor ID also being specified. Otherwise, the policy will not be valid. Invalid policy values are ignored.
+
+        If this policy is left not set, the global default value will be used for all sites either from the 'DefaultWebUsbGuardSetting' policy if it is set, or the user's personal configuration otherwise.
+
+        URL patterns in this policy should not clash with the ones configured via WebUsbBlockedForUrls. If there is a clash, this policy will take precedence over WebUsbBlockedForUrls and WebUsbAskForUrls.''',
+    },
+    {
       'name': 'WebUsbAskForUrls',
       'type': 'list',
       'schema': {
@@ -13472,5 +13517,5 @@
   },
   'placeholders': [],
   'deleted_policy_ids': [412],
-  'highest_id_currently_used': 485
+  'highest_id_currently_used': 486
 }
diff --git a/components/pref_registry/OWNERS b/components/pref_registry/OWNERS
index 7c452a5..17dc7671 100644
--- a/components/pref_registry/OWNERS
+++ b/components/pref_registry/OWNERS
@@ -1,5 +1,4 @@
 battre@chromium.org
 gab@chromium.org
-pam@chromium.org
 
 # COMPONENT: UI>Browser>Preferences
diff --git a/components/prefs/OWNERS b/components/prefs/OWNERS
index 7c452a5..17dc7671 100644
--- a/components/prefs/OWNERS
+++ b/components/prefs/OWNERS
@@ -1,5 +1,4 @@
 battre@chromium.org
 gab@chromium.org
-pam@chromium.org
 
 # COMPONENT: UI>Browser>Preferences
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index ce153368..6d1b77e2 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -432,6 +432,12 @@
     std::vector<gaia::ListedAccount>&& gaia_accounts) {
   DCHECK(base::FeatureList::IsEnabled(kUseMultiloginEndpoint));
 
+  signin::MultiloginMode mode;
+  if (delegate_->ShouldUpdateAccountsOrderInCookies())
+    mode = signin::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
+  else
+    mode = signin::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER;
+
   std::vector<std::string> accounts_to_send;
   if (delegate_->ReorderChromeAccountsForReconcileIfNeeded(
           chrome_accounts, primary_account, gaia_accounts, &accounts_to_send)) {
@@ -439,7 +445,13 @@
   } else {
     OnSetAccountsInCookieCompleted(GoogleServiceAuthError::AuthErrorNone());
   }
-  // TODO(valeriyas): Log operation here.
+
+  VLOG(1) << "AccountReconcilor::FinishReconcileWithMultiloginEndpoint "
+          << "in mode: "
+          << (mode == signin::MultiloginMode::
+                          MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER
+                  ? "UPDATE"
+                  : "PRESERVE");
   // TODO (valeriyas): Write correct first gaia account to cache for desktop.
   if (!is_reconcile_started_)
     delegate_->OnReconcileFinished(primary_account, reconcile_is_noop_);
diff --git a/components/signin/core/browser/account_reconcilor_delegate.cc b/components/signin/core/browser/account_reconcilor_delegate.cc
index 5542649..634a7730 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -44,6 +44,10 @@
   return false;
 }
 
+bool AccountReconcilorDelegate::ShouldUpdateAccountsOrderInCookies() const {
+  return true;
+}
+
 AccountReconcilorDelegate::RevokeTokenOption
 AccountReconcilorDelegate::ShouldRevokeSecondaryTokensBeforeReconcile(
     const std::vector<gaia::ListedAccount>& gaia_accounts) {
diff --git a/components/signin/core/browser/account_reconcilor_delegate.h b/components/signin/core/browser/account_reconcilor_delegate.h
index cbec21d6..7b72d4b 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/components/signin/core/browser/account_reconcilor_delegate.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/time/time.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
@@ -71,6 +72,10 @@
       const std::vector<gaia::ListedAccount>& gaia_accounts,
       std::vector<std::string>* accounts_to_send) const;
 
+  // Returns true if it is allowed to change the order of the gaia accounts
+  // (e.g. on mobile or on stratup). Default is true.
+  virtual bool ShouldUpdateAccountsOrderInCookies() const;
+
   // Returns whether secondary accounts should be revoked at the beginning of
   // the reconcile.
   virtual RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index fcdefffa..1ed14318 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -215,7 +215,6 @@
     "engine/polling_constants.h",
     "engine/sequenced_model_worker.cc",
     "engine/sequenced_model_worker.h",
-    "engine/shutdown_reason.cc",
     "engine/shutdown_reason.h",
     "engine/sync_auth_provider.h",
     "engine/sync_backend_registrar.cc",
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index 81dbe58..dcdff0c 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -303,7 +303,7 @@
   // If we're performing a "catch up", first stop the model types to ensure the
   // call to Initialize triggers model association.
   if (catch_up_in_progress_)
-    model_association_manager_.Stop(STOP_SYNC);
+    model_association_manager_.Stop(KEEP_METADATA);
   download_started_ = false;
   model_association_manager_.Initialize(
       /*desired_types=*/last_enabled_types_,
@@ -794,9 +794,21 @@
   // Invalidate weak pointer to drop download callbacks.
   weak_ptr_factory_.InvalidateWeakPtrs();
 
+  // Leave metadata If we do not disable sync completely.
+  SyncStopMetadataFate metadata_fate = KEEP_METADATA;
+  switch (reason) {
+    case STOP_SYNC:
+      break;
+    case DISABLE_SYNC:
+      metadata_fate = CLEAR_METADATA;
+      break;
+    case BROWSER_SHUTDOWN:
+      break;
+  }
+
   // Stop all data types. This may trigger association callback but the
   // callback will do nothing because state is set to STOPPING above.
-  model_association_manager_.Stop(reason);
+  model_association_manager_.Stop(metadata_fate);
 
   // Individual data type controllers might still be STOPPING, but we don't
   // reflect that in |state_| because, for all practical matters, the manager is
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index 4ff34096..99bb800 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -16,7 +16,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "components/sync/base/model_type.h"
-#include "components/sync/base/sync_stop_metadata_fate.h"
 #include "components/sync/model/sync_merge_result.h"
 
 namespace syncer {
@@ -127,7 +126,7 @@
   notified_about_ready_for_configure_ = false;
 
   DVLOG(1) << "ModelAssociationManager: Stopping disabled types.";
-  std::map<DataTypeController*, ShutdownReason> types_to_stop;
+  std::map<DataTypeController*, SyncStopMetadataFate> types_to_stop;
   for (const auto& type_and_dtc : *controllers_) {
     DataTypeController* dtc = type_and_dtc.second.get();
     // We stop a datatype if it's not desired. Independently of being desired,
@@ -136,9 +135,9 @@
     if ((dtc->state() != DataTypeController::NOT_RUNNING &&
          !desired_types_.Has(dtc->type())) ||
         dtc->state() == DataTypeController::STOPPING) {
-      const ShutdownReason reason =
-          preferred_types.Has(dtc->type()) ? STOP_SYNC : DISABLE_SYNC;
-      types_to_stop[dtc] = reason;
+      const SyncStopMetadataFate metadata_fate =
+          preferred_types.Has(dtc->type()) ? KEEP_METADATA : CLEAR_METADATA;
+      types_to_stop[dtc] = metadata_fate;
     }
   }
 
@@ -150,18 +149,18 @@
       base::BindOnce(&ModelAssociationManager::LoadEnabledTypes,
                      weak_ptr_factory_.GetWeakPtr()));
 
-  for (const auto& dtc_and_reason : types_to_stop) {
-    DataTypeController* dtc = dtc_and_reason.first;
-    const ShutdownReason reason = dtc_and_reason.second;
-    DVLOG(1) << "ModelAssociationManager: stop " << dtc->name() << " due to "
-             << ShutdownReasonToString(reason);
-    StopDatatype(SyncError(), reason, dtc, barrier_closure);
+  for (const auto& dtc_and_metadata_fate : types_to_stop) {
+    DataTypeController* dtc = dtc_and_metadata_fate.first;
+    const SyncStopMetadataFate metadata_fate = dtc_and_metadata_fate.second;
+    DVLOG(1) << "ModelAssociationManager: stop " << dtc->name() << " with "
+             << SyncStopMetadataFateToString(metadata_fate);
+    StopDatatype(SyncError(), metadata_fate, dtc, barrier_closure);
   }
 }
 
 void ModelAssociationManager::StopDatatype(
     const SyncError& error,
-    ShutdownReason shutdown_reason,
+    SyncStopMetadataFate metadata_fate,
     DataTypeController* dtc,
     DataTypeController::StopCallback callback) {
   loaded_types_.Remove(dtc->type());
@@ -171,25 +170,6 @@
   DCHECK(error.IsSet() || (dtc->state() != DataTypeController::NOT_RUNNING));
 
   delegate_->OnSingleDataTypeWillStop(dtc->type(), error);
-
-  // Leave metadata if we do not disable sync completely.
-  SyncStopMetadataFate metadata_fate = KEEP_METADATA;
-  switch (shutdown_reason) {
-    case STOP_SYNC:
-      // Special case: For AUTOFILL_WALLET_DATA, we want to clear all data even
-      // when Sync is stopped temporarily.
-      // TODO(crbug.com/890361): Consider moving this decision into the
-      // individual controller
-      if (dtc->type() == AUTOFILL_WALLET_DATA) {
-        metadata_fate = CLEAR_METADATA;
-      }
-      break;
-    case DISABLE_SYNC:
-      metadata_fate = CLEAR_METADATA;
-      break;
-    case BROWSER_SHUTDOWN:
-      break;
-  }
   dtc->Stop(metadata_fate, std::move(callback));
 }
 
@@ -274,7 +254,7 @@
   }
 }
 
-void ModelAssociationManager::Stop(ShutdownReason shutdown_reason) {
+void ModelAssociationManager::Stop(SyncStopMetadataFate metadata_fate) {
   // Ignore callbacks from controllers.
   weak_ptr_factory_.InvalidateWeakPtrs();
 
@@ -285,7 +265,7 @@
         dtc->state() != DataTypeController::STOPPING) {
       // We don't really wait until all datatypes have been fully stopped, which
       // is only required (and in fact waited for) when Initialize() is called.
-      StopDatatype(SyncError(), shutdown_reason, dtc, base::DoNothing());
+      StopDatatype(SyncError(), metadata_fate, dtc, base::DoNothing());
       DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name();
     }
   }
@@ -355,7 +335,8 @@
     DVLOG(1) << "ModelAssociationManager: Type encountered an error.";
     desired_types_.Remove(type);
     DataTypeController* dtc = controllers_->find(type)->second.get();
-    StopDatatype(local_merge_result.error(), STOP_SYNC, dtc, base::DoNothing());
+    StopDatatype(local_merge_result.error(), KEEP_METADATA, dtc,
+                 base::DoNothing());
     NotifyDelegateIfReadyForConfigure();
 
     // Update configuration result.
@@ -429,7 +410,7 @@
                                 static_cast<int>(MODEL_TYPE_COUNT));
       StopDatatype(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
                              "Association timed out.", dtc->type()),
-                   STOP_SYNC, dtc, base::DoNothing());
+                   KEEP_METADATA, dtc, base::DoNothing());
     }
   }
 
diff --git a/components/sync/driver/model_association_manager.h b/components/sync/driver/model_association_manager.h
index aada6fee..07dcc5f0 100644
--- a/components/sync/driver/model_association_manager.h
+++ b/components/sync/driver/model_association_manager.h
@@ -11,12 +11,12 @@
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
 
+#include "components/sync/base/sync_stop_metadata_fate.h"
 #include "components/sync/base/weak_handle.h"
 #include "components/sync/driver/configure_context.h"
 #include "components/sync/driver/data_type_controller.h"
 #include "components/sync/driver/data_type_manager.h"
 #include "components/sync/engine/data_type_association_stats.h"
-#include "components/sync/engine/shutdown_reason.h"
 
 namespace syncer {
 
@@ -94,7 +94,9 @@
                   const ConfigureContext& context);
 
   // Can be called at any time. Synchronously stops all datatypes.
-  void Stop(ShutdownReason shutdown_reason);
+  // If |metadata_fate| equals  CLEAR_METADATA controllers should clear sync
+  // metadata.
+  void Stop(SyncStopMetadataFate metadata_fate);
 
   // Should only be called after Initialize to start the actual association.
   // |types_to_associate| should be subset of |desired_types| in Initialize().
@@ -136,7 +138,7 @@
 
   // A helper to stop an individual datatype.
   void StopDatatype(const SyncError& error,
-                    ShutdownReason shutdown_reason,
+                    SyncStopMetadataFate metadata_fate,
                     DataTypeController* dtc,
                     DataTypeController::StopCallback callback);
 
diff --git a/components/sync/driver/model_association_manager_unittest.cc b/components/sync/driver/model_association_manager_unittest.cc
index 5eac7ab4..6d74f01 100644
--- a/components/sync/driver/model_association_manager_unittest.cc
+++ b/components/sync/driver/model_association_manager_unittest.cc
@@ -120,7 +120,7 @@
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::ASSOCIATING);
-  model_association_manager.Stop(STOP_SYNC);
+  model_association_manager.Stop(KEEP_METADATA);
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
   EXPECT_EQ(
@@ -148,7 +148,7 @@
             DataTypeController::ASSOCIATING);
   GetController(controllers_, BOOKMARKS)->FinishStart(DataTypeController::OK);
 
-  model_association_manager.Stop(STOP_SYNC);
+  model_association_manager.Stop(KEEP_METADATA);
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
   EXPECT_EQ(
@@ -572,7 +572,7 @@
   ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::MODEL_LOADED);
 
-  model_association_manager.Stop(DISABLE_SYNC);
+  model_association_manager.Stop(CLEAR_METADATA);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
diff --git a/components/sync/engine/shutdown_reason.cc b/components/sync/engine/shutdown_reason.cc
deleted file mode 100644
index c95f91c..0000000
--- a/components/sync/engine/shutdown_reason.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/sync/engine/shutdown_reason.h"
-
-#include "base/logging.h"
-
-namespace syncer {
-
-const char* ShutdownReasonToString(ShutdownReason reason) {
-  switch (reason) {
-    case STOP_SYNC:
-      return "STOP_SYNC";
-    case DISABLE_SYNC:
-      return "DISABLE_SYNC";
-    case BROWSER_SHUTDOWN:
-      return "BROWSER_SHUTDOWN";
-  }
-
-  NOTREACHED();
-  return "";
-}
-
-}  // namespace syncer
diff --git a/components/sync/engine/shutdown_reason.h b/components/sync/engine/shutdown_reason.h
index 1a3f082..a61be8f 100644
--- a/components/sync/engine/shutdown_reason.h
+++ b/components/sync/engine/shutdown_reason.h
@@ -14,8 +14,6 @@
   BROWSER_SHUTDOWN,  // Browser is closed.
 };
 
-const char* ShutdownReasonToString(ShutdownReason reason);
-
 }  // namespace syncer
 
 #endif  // COMPONENTS_SYNC_ENGINE_SHUTDOWN_REASON_H_
diff --git a/components/sync_preferences/OWNERS b/components/sync_preferences/OWNERS
index 7c452a5..17dc7671 100644
--- a/components/sync_preferences/OWNERS
+++ b/components/sync_preferences/OWNERS
@@ -1,5 +1,4 @@
 battre@chromium.org
 gab@chromium.org
-pam@chromium.org
 
 # COMPONENT: UI>Browser>Preferences
diff --git a/components/test/data/autofill/credit_card_upload_form_address_and_cc.html b/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
index fef9707..56b47ed 100644
--- a/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
+++ b/components/test/data/autofill/credit_card_upload_form_address_and_cc.html
@@ -22,18 +22,24 @@
     <div>Name on card: <input type="text" name="name_cc" autocomplete="cc-name"></div>
     <div>Credit card number: <input type="text" name="cc_number" autocomplete="cc-number"></div>
     <div>Expiry Date:
-    <input type="text" name="cc_month_exp" placeholder="MM" autocomplete="cc-exp-month">
+    <select name="cc_month_exp" autocomplete="cc-month-exp">
+      <option value="1">01</option>
+      <option value="2">02</option>
+      <option value="3">03</option>
+      <option value="4">04</option>
+      <option value="5">05</option>
+      <option value="6">06</option>
+      <option value="7">07</option>
+      <option value="8">08</option>
+      <option value="9">09</option>
+      <option value="10">10</option>
+      <option value="11">11</option>
+      <option value="12">12</option>
+    </select>
     /
     <input type="text" name="cc_year_exp" placeholder="YYYY" autocomplete="cc-exp-year"></div>
     <div>CVC: <input name="cc_cvc" autocomplete="cc-csc"></div>
     <hr>
-    Test Dropdown Field: <select id="test_dropdown">
-      <option value="dropdown_1">Test Option 1</option>
-      <option value="dropdown_2">Test Option 2</option>
-      <option value="dropdown_3">Test Option 3</option>
-      <option value="dropdown_4">Test Option 4</option>
-    </select>
-    <hr>
     <button id="fill_form" type="button">Fill entire form with default (MasterCard) values</button>
     <button id="fill_form_delay" type="button">Fill out the name field after 3 seconds</button>
     <button id="fill_invalid_cvc" type="button">Fill the CVC field with an invalid value</button>
diff --git a/components/tracing/common/stack_unwinder_android.cc b/components/tracing/common/stack_unwinder_android.cc
index 7d9b0a5..a6c89a1 100644
--- a/components/tracing/common/stack_unwinder_android.cc
+++ b/components/tracing/common/stack_unwinder_android.cc
@@ -92,13 +92,19 @@
 size_t TraceStackWithContext(unw_cursor_t* cursor,
                              CFIBacktraceAndroid* cfi_unwinder,
                              const tracing::StackUnwinderAndroid* unwinder,
+                             uintptr_t stack_segment_base,
                              const void** out_trace,
                              size_t max_depth) {
   size_t depth = 0;
   unw_word_t ip = 0, sp = 0;
+  unw_get_reg(cursor, UNW_REG_SP, &sp);
+  uintptr_t initial_sp = sp;
   do {
     unw_get_reg(cursor, UNW_REG_IP, &ip);
     unw_get_reg(cursor, UNW_REG_SP, &sp);
+    DCHECK_GE(sp, initial_sp);
+    if (stack_segment_base > 0)
+      DCHECK_LT(sp, stack_segment_base);
 
     // If address is in chrome library, then use CFI unwinder since chrome might
     // not have EHABI unwind tables.
@@ -151,6 +157,7 @@
   uintptr_t* sp;
   // The address where the full stack is copied to.
   char* stack_copy_buffer;
+  size_t* stack_size;
 };
 
 // Argument passed to the ThreadSignalHandler() from the sampling thread to the
@@ -180,10 +187,11 @@
   *params->sp = sp;
 
   uintptr_t stack_base_addr = params->unwinder->GetEndAddressOfRegion(sp);
-  size_t size = stack_base_addr - sp;
-  if (stack_base_addr == 0 || size > kMaxStackBytesCopied)
+  *params->stack_size = stack_base_addr - sp;
+  if (stack_base_addr == 0 || *params->stack_size > kMaxStackBytesCopied)
     return;
-  memcpy(params->stack_copy_buffer, reinterpret_cast<void*>(sp), size);
+  memcpy(params->stack_copy_buffer, reinterpret_cast<void*>(sp),
+         *params->stack_size);
   *params->success = true;
 }
 
@@ -259,9 +267,9 @@
     return 0;
   if (unw_init_local(&cursor, &context) != 0)
     return 0;
-  return TraceStackWithContext(&cursor,
-                               CFIBacktraceAndroid::GetInitializedInstance(),
-                               this, out_trace, max_depth);
+  return TraceStackWithContext(
+      &cursor, CFIBacktraceAndroid::GetInitializedInstance(), this,
+      /* stack_segment_base=*/0, out_trace, max_depth);
 }
 
 size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
@@ -272,12 +280,14 @@
   // stack frames from the copied stack.
   DCHECK(is_initialized_);
   AsyncSafeWaitableEvent wait_event;
+  size_t stack_size;
   std::unique_ptr<char[]> stack_copy_buffer(new char[kMaxStackBytesCopied]);
   bool copied = false;
   unw_context_t context;
   uintptr_t sp = 0;
-  HandlerParams params = {this,     &wait_event, &copied,
-                          &context, &sp,         stack_copy_buffer.get()};
+  HandlerParams params = {this,       &wait_event, &copied,
+                          &context,   &sp,         stack_copy_buffer.get(),
+                          &stack_size};
   base::subtle::Release_Store(&g_handler_params,
                               reinterpret_cast<uintptr_t>(&params));
 
@@ -287,9 +297,7 @@
   struct sigaction oact;
   memset(&act, 0, sizeof(act));
   act.sa_sigaction = ThreadSignalHandler;
-  // TODO(ssid): SA_ONSTACK will not work if sigaltstack was set. So, unwind
-  // should work without this flag.
-  act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
+  act.sa_flags = SA_RESTART | SA_SIGINFO;
   sigemptyset(&act.sa_mask);
   // SIGURG is chosen here because we observe no crashes with this signal and
   // neither Chrome or the AOSP sets up a special handler for this signal.
@@ -311,19 +319,28 @@
     return 0;
   }
 
-  // Context contains list of saved registers. Replace the SP to the copied
-  // stack. The SP should be one of the first 16 registers.
+  // Context contains list of saved registers. Replace the SP and any register
+  // that points to address on the previous stack to point to the copied stack.
+  const uintptr_t relocation_offset =
+      reinterpret_cast<uintptr_t>(stack_copy_buffer.get()) - sp;
   bool replaced_sp = false;
-  for (size_t i = 0; i < 17; ++i) {
-    uintptr_t* data = reinterpret_cast<uintptr_t*>(&context) + i;
-    if (*data == sp) {
-      *data = reinterpret_cast<uintptr_t>(stack_copy_buffer.get());
-      replaced_sp = true;
-      break;
+  uintptr_t* register_context = reinterpret_cast<uintptr_t*>(&context);
+  for (size_t i = 0; i < 16; ++i) {
+    if (register_context[i] >= sp && register_context[i] < sp + stack_size) {
+      replaced_sp = replaced_sp || register_context[i] == sp;
+      register_context[i] += relocation_offset;
     }
   }
   DCHECK(replaced_sp);
 
+  // Unwind can use address on the stack. So, replace them as well. See EHABI
+  // #7.5.4 table 3.
+  uintptr_t* new_stack = reinterpret_cast<uintptr_t*>(stack_copy_buffer.get());
+  for (size_t i = 0; i < stack_size / sizeof(uintptr_t); ++i) {
+    if (new_stack[i] >= sp && new_stack[i] < sp + stack_size)
+      new_stack[i] += relocation_offset;
+  }
+
   // Initialize an unwind cursor on copied stack.
   unw_cursor_t cursor;
   if (unw_init_local(&cursor, &context) != 0) {
@@ -359,8 +376,10 @@
   unw_set_reg(&cursor, UNW_REG_SP, sp);
   unw_set_reg(&cursor, UNW_REG_IP, ip);
 
-  return TraceStackWithContext(&cursor, cfi_unwinder, this, out_trace,
-                               max_depth);
+  return TraceStackWithContext(
+      &cursor, cfi_unwinder, this,
+      reinterpret_cast<uintptr_t>(stack_copy_buffer.get()) + stack_size,
+      out_trace, max_depth);
 }
 
 uintptr_t StackUnwinderAndroid::GetEndAddressOfRegion(uintptr_t addr) const {
diff --git a/components/user_prefs/OWNERS b/components/user_prefs/OWNERS
index 7c452a5..17dc7671 100644
--- a/components/user_prefs/OWNERS
+++ b/components/user_prefs/OWNERS
@@ -1,5 +1,4 @@
 battre@chromium.org
 gab@chromium.org
-pam@chromium.org
 
 # COMPONENT: UI>Browser>Preferences
diff --git a/components/variations/android/variations_seed_bridge.cc b/components/variations/android/variations_seed_bridge.cc
index 5356248..cc209c6 100644
--- a/components/variations/android/variations_seed_bridge.cc
+++ b/components/variations/android/variations_seed_bridge.cc
@@ -19,27 +19,6 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ScopedJavaLocalRef;
 
-namespace {
-
-std::string JNI_VariationsSeedBridge_JavaByteArrayToString(
-    JNIEnv* env,
-    jbyteArray byte_array) {
-  if (!byte_array)
-    return std::string();
-  std::vector<uint8_t> array_data;
-  base::android::JavaByteArrayToByteVector(env, byte_array, &array_data);
-  return std::string(array_data.begin(), array_data.end());
-}
-
-ScopedJavaLocalRef<jbyteArray> JNI_VariationsSeedBridge_StringToJavaByteArray(
-    JNIEnv* env,
-    const std::string& str_data) {
-  std::vector<uint8_t> array_data(str_data.begin(), str_data.end());
-  return base::android::ToJavaByteArray(env, array_data);
-}
-
-}  // namespace
-
 namespace variations {
 namespace android {
 
@@ -57,8 +36,9 @@
       Java_VariationsSeedBridge_getVariationsFirstRunSeedIsGzipCompressed(env);
 
   auto seed = std::make_unique<variations::SeedResponse>();
-  seed->data =
-      JNI_VariationsSeedBridge_JavaByteArrayToString(env, j_seed_data.obj());
+  if (!j_seed_data.is_null()) {
+    base::android::JavaByteArrayToString(env, j_seed_data.obj(), &seed->data);
+  }
   seed->signature = ConvertJavaStringToUTF8(j_seed_signature);
   seed->country = ConvertJavaStringToUTF8(j_seed_country);
   seed->date = ConvertJavaStringToUTF8(j_response_date);
@@ -83,7 +63,7 @@
                                     bool is_gzip_compressed) {
   JNIEnv* env = AttachCurrentThread();
   Java_VariationsSeedBridge_setVariationsFirstRunSeed(
-      env, JNI_VariationsSeedBridge_StringToJavaByteArray(env, seed_data),
+      env, base::android::ToJavaByteArray(env, seed_data),
       ConvertUTF8ToJavaString(env, seed_signature),
       ConvertUTF8ToJavaString(env, seed_country),
       ConvertUTF8ToJavaString(env, response_date),
diff --git a/content/browser/media/forwarding_audio_stream_factory.cc b/content/browser/media/forwarding_audio_stream_factory.cc
index 09f4fa1b..a76d573 100644
--- a/content/browser/media/forwarding_audio_stream_factory.cc
+++ b/content/browser/media/forwarding_audio_stream_factory.cc
@@ -179,17 +179,17 @@
 void ForwardingAudioStreamFactory::FrameDeleted(
     RenderFrameHost* render_frame_host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(render_frame_host);
   CleanupStreamsBelongingTo(render_frame_host);
 }
 
 void ForwardingAudioStreamFactory::CleanupStreamsBelongingTo(
     RenderFrameHost* render_frame_host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(render_frame_host);
 
-  const int process_id =
-      render_frame_host ? render_frame_host->GetProcess()->GetID() : -1;
-  const int frame_id =
-      render_frame_host ? render_frame_host->GetRoutingID() : -1;
+  const int process_id = render_frame_host->GetProcess()->GetID();
+  const int frame_id = render_frame_host->GetRoutingID();
 
   TRACE_EVENT_BEGIN2("audio", "CleanupStreamsBelongingTo", "group",
                      group_id_.GetLowForSerialization(), "process id",
diff --git a/content/browser/media/in_process_audio_loopback_stream_creator.cc b/content/browser/media/in_process_audio_loopback_stream_creator.cc
index 8248ad3e..ad26dac 100644
--- a/content/browser/media/in_process_audio_loopback_stream_creator.cc
+++ b/content/browser/media/in_process_audio_loopback_stream_creator.cc
@@ -70,7 +70,6 @@
 
 InProcessAudioLoopbackStreamCreator::~InProcessAudioLoopbackStreamCreator() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  factory_.FrameDeleted(nullptr);
 }
 
 void InProcessAudioLoopbackStreamCreator::CreateLoopbackStream(
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 09ad88c..d50dbf0 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -182,10 +182,10 @@
 
 void InputRouterImpl::SendTouchEvent(
     const TouchEventWithLatencyInfo& touch_event) {
-  TouchEventWithLatencyInfo updatd_touch_event = touch_event;
-  SetMovementXYForTouchPoints(&updatd_touch_event.event);
-  input_stream_validator_.Validate(updatd_touch_event.event);
-  touch_event_queue_.QueueEvent(updatd_touch_event);
+  TouchEventWithLatencyInfo updated_touch_event = touch_event;
+  SetMovementXYForTouchPoints(&updated_touch_event.event);
+  input_stream_validator_.Validate(updated_touch_event.event);
+  touch_event_queue_.QueueEvent(updated_touch_event);
 }
 
 void InputRouterImpl::NotifySiteIsMobileOptimized(bool is_mobile_optimized) {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 5d465d70..97a34da 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1980,8 +1980,6 @@
   DCHECK(!is_mus_browser_plugin_guest_);
   window_ = new aura::Window(this);
   window_->SetName("RenderWidgetHostViewAura");
-  window_->SetProperty(aura::client::kEmbedType,
-                       aura::client::WindowEmbedType::EMBED_IN_OWNER);
   event_handler_->set_window(window_);
   window_observer_.reset(new WindowObserver(this));
 
diff --git a/content/browser/resources/media/util.js b/content/browser/resources/media/util.js
index 29cc1b1..3ab7da7 100644
--- a/content/browser/resources/media/util.js
+++ b/content/browser/resources/media/util.js
@@ -30,17 +30,19 @@
     }
   };
   util.millisecondsToString = function(timeMillis) {
-    function pad(num) {
+    function pad(num, len) {
       num = num.toString();
-      if (num.length < 2) {
-        return '0' + num;
+      while (num.length < len) {
+        num = '0' + num;
       }
       return num;
     }
 
     var date = new Date(timeMillis);
-    return pad(date.getUTCHours()) + ':' + pad(date.getUTCMinutes()) + ':' +
-        pad(date.getUTCSeconds()) + ' ' + pad((date.getMilliseconds()) % 1000);
+    return pad(date.getUTCHours(), 2) + ':' +
+           pad(date.getUTCMinutes(), 2) + ':' +
+           pad(date.getUTCSeconds(), 2) + '.' +
+           pad((date.getMilliseconds()) % 1000, 3);
   };
 
   return util;
diff --git a/content/renderer/gpu/layer_tree_view.cc b/content/renderer/gpu/layer_tree_view.cc
index 8f103f1..a4a31970 100644
--- a/content/renderer/gpu/layer_tree_view.cc
+++ b/content/renderer/gpu/layer_tree_view.cc
@@ -479,12 +479,9 @@
   }
 }
 
-void LayerTreeView::SynchronouslyCompositeNoRasterForTesting() {
-  SynchronouslyComposite(false /* raster */, nullptr /* swap_promise */);
-}
-
-void LayerTreeView::CompositeWithRasterForTesting() {
-  SynchronouslyComposite(true /* raster */, nullptr /* swap_promise */);
+void LayerTreeView::UpdateAllLifecyclePhasesAndCompositeForTesting(
+    bool do_raster) {
+  SynchronouslyComposite(do_raster, nullptr /* swap_promise */);
 }
 
 void LayerTreeView::SynchronouslyComposite(
diff --git a/content/renderer/gpu/layer_tree_view.h b/content/renderer/gpu/layer_tree_view.h
index efe85bf..37d5783 100644
--- a/content/renderer/gpu/layer_tree_view.h
+++ b/content/renderer/gpu/layer_tree_view.h
@@ -137,8 +137,10 @@
   void LayoutAndPaintAsync(base::OnceClosure callback) override;
   void CompositeAndReadbackAsync(
       base::OnceCallback<void(const SkBitmap&)> callback) override;
-  void SynchronouslyCompositeNoRasterForTesting() override;
-  void CompositeWithRasterForTesting() override;
+  // Synchronously performs the complete set of document lifecycle phases,
+  // including updates to the compositor state, optionally including
+  // rasterization.
+  void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override;
   std::unique_ptr<cc::ScopedDeferCommits> DeferCommits() override;
   void RegisterViewportLayers(const ViewportLayers& viewport_layers) override;
   void ClearViewportLayers() override;
diff --git a/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc b/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
index 2d97f8e..d13d9616 100644
--- a/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
+++ b/content/shell/renderer/layout_test/layout_test_render_frame_observer.cc
@@ -56,15 +56,9 @@
     CompositeWithRasterCallback callback) {
   blink::WebWidget* widget = render_frame()->GetWebFrame()->FrameWidget();
   if (widget) {
-    widget->CompositeWithRasterForTesting();
-    // TODO(vmpstr): This doesn't embed the popup frame into the browser. We
-    // likely need to manually readback the pixels here and return them via the
-    // callback, so that the browser can embed it into the final screenshot. If
-    // we do this without using WebPagePopup::CompositeWithRasterForTesting(),
-    // then we can put CompositeWithRasterForTesting() on WebFrameWidgetBase
-    // instead, and remove the overrides from a bunch of places.
+    widget->UpdateAllLifecyclePhasesAndCompositeForTesting(/*do_raster=*/true);
     if (blink::WebPagePopup* popup = widget->GetPagePopup())
-      popup->CompositeWithRasterForTesting();
+      popup->UpdateAllLifecyclePhasesAndCompositeForTesting(/*do_raster=*/true);
   }
   std::move(callback).Run();
 }
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 185275bc..a89dddf 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -201,6 +201,10 @@
   void GetBluetoothManualChooserEvents(v8::Local<v8::Function> callback);
   void GetManifestThen(v8::Local<v8::Function> callback);
   void InsertStyleSheet(const std::string& source_code);
+  void UpdateAllLifecyclePhasesAndComposite();
+  void UpdateAllLifecyclePhasesAndCompositeThen(
+      v8::Local<v8::Function> callback);
+  void SetAnimationRequiresRaster(bool do_raster);
   void LayoutAndPaintAsync();
   void LayoutAndPaintAsyncThen(v8::Local<v8::Function> callback);
   void LogToStderr(const std::string& output);
@@ -488,6 +492,12 @@
       .SetMethod("isChooserShown", &TestRunnerBindings::IsChooserShown)
       .SetMethod("isCommandEnabled", &TestRunnerBindings::IsCommandEnabled)
       .SetMethod("keepWebHistory", &TestRunnerBindings::NotImplemented)
+      .SetMethod("updateAllLifecyclePhasesAndComposite",
+                 &TestRunnerBindings::UpdateAllLifecyclePhasesAndComposite)
+      .SetMethod("updateAllLifecyclePhasesAndCompositeThen",
+                 &TestRunnerBindings::UpdateAllLifecyclePhasesAndCompositeThen)
+      .SetMethod("setAnimationRequiresRaster",
+                 &TestRunnerBindings::SetAnimationRequiresRaster)
       .SetMethod("layoutAndPaintAsync",
                  &TestRunnerBindings::LayoutAndPaintAsync)
       .SetMethod("layoutAndPaintAsyncThen",
@@ -1343,6 +1353,23 @@
     view_runner_->RemoveWebPageOverlay();
 }
 
+void TestRunnerBindings::UpdateAllLifecyclePhasesAndComposite() {
+  if (view_runner_)
+    view_runner_->UpdateAllLifecyclePhasesAndComposite();
+}
+
+void TestRunnerBindings::UpdateAllLifecyclePhasesAndCompositeThen(
+    v8::Local<v8::Function> callback) {
+  if (view_runner_)
+    view_runner_->UpdateAllLifecyclePhasesAndCompositeThen(callback);
+}
+
+void TestRunnerBindings::SetAnimationRequiresRaster(bool do_raster) {
+  if (!runner_)
+    return;
+  runner_->SetAnimationRequiresRaster(do_raster);
+}
+
 void TestRunnerBindings::LayoutAndPaintAsync() {
   if (view_runner_)
     view_runner_->LayoutAndPaintAsync();
@@ -1518,6 +1545,7 @@
       chooser_count_(0),
       previously_focused_view_(nullptr),
       is_web_platform_tests_mode_(false),
+      animation_requires_raster_(false),
       effective_connection_type_(
           blink::WebEffectiveConnectionType::kTypeUnknown),
       weak_factory_(this) {}
@@ -1579,6 +1607,7 @@
   test_repaint_ = false;
   sweep_horizontally_ = false;
   midi_accessor_result_ = midi::mojom::Result::OK;
+  animation_requires_raster_ = false;
 
   http_headers_to_clear_.clear();
 
@@ -2562,6 +2591,10 @@
   delegate_->SimulateWebNotificationClose(title, by_user);
 }
 
+void TestRunner::SetAnimationRequiresRaster(bool do_raster) {
+  animation_requires_raster_ = do_raster;
+}
+
 void TestRunner::OnLayoutTestRuntimeFlagsChanged() {
   if (layout_test_runtime_flags_.tracked_dictionary().changed_values().empty())
     return;
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index cd15376..257e1e4 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -136,6 +136,8 @@
   const base::Optional<std::vector<std::string>>& file_chooser_paths() const {
     return file_chooser_paths_;
   }
+  bool animation_requires_raster() const { return animation_requires_raster_; }
+  void SetAnimationRequiresRaster(bool do_raster);
 
   // To be called when |frame| starts loading - TestRunner will check if
   // there is currently no top-loading-frame being tracked and if so, then it
@@ -593,6 +595,11 @@
   // True when running a test in LayoutTests/external/wpt/.
   bool is_web_platform_tests_mode_;
 
+  // True if rasterization should be performed during tests that examine
+  // fling-style animations. This includes middle-click auto-scroll behaviors.
+  // This does not include most "ordinary" animations, such as CSS animations.
+  bool animation_requires_raster_;
+
   // An effective connection type settable by layout tests.
   blink::WebEffectiveConnectionType effective_connection_type_;
 
diff --git a/content/shell/test_runner/test_runner_for_specific_view.cc b/content/shell/test_runner/test_runner_for_specific_view.cc
index db2f338..5d38646db 100644
--- a/content/shell/test_runner/test_runner_for_specific_view.cc
+++ b/content/shell/test_runner/test_runner_for_specific_view.cc
@@ -193,6 +193,23 @@
                          blink::MainThreadIsolate(), callback)));
 }
 
+void TestRunnerForSpecificView::UpdateAllLifecyclePhasesAndComposite() {
+  // Note, this is executed synchronously. Wrap in setTimeout() to run
+  // asynchronously.
+  blink::WebWidget* widget =
+      web_view()->MainFrame()->ToWebLocalFrame()->FrameWidget();
+  widget->UpdateAllLifecyclePhasesAndCompositeForTesting(/* raster = */ true);
+}
+
+void TestRunnerForSpecificView::UpdateAllLifecyclePhasesAndCompositeThen(
+    v8::Local<v8::Function> callback) {
+  // Note, this is executed synchronously. Wrap in setTimeout() to run
+  // asynchronously.
+  TestRunnerForSpecificView::UpdateAllLifecyclePhasesAndComposite();
+  InvokeV8Callback(
+      v8::UniquePersistent<v8::Function>(blink::MainThreadIsolate(), callback));
+}
+
 void TestRunnerForSpecificView::LayoutAndPaintAsync() {
   // TODO(lfg, lukasza): TestRunnerForSpecificView assumes that there's a single
   // WebWidget for the entire view, but with out-of-process iframes there may be
diff --git a/content/shell/test_runner/test_runner_for_specific_view.h b/content/shell/test_runner/test_runner_for_specific_view.h
index 1ca05bce7..0db241f1 100644
--- a/content/shell/test_runner/test_runner_for_specific_view.h
+++ b/content/shell/test_runner/test_runner_for_specific_view.h
@@ -72,6 +72,10 @@
   base::OnceClosure CreateClosureThatPostsV8Callback(
       const v8::Local<v8::Function>& callback);
 
+  void UpdateAllLifecyclePhasesAndComposite();
+  void UpdateAllLifecyclePhasesAndCompositeThen(
+      v8::Local<v8::Function> callback);
+
   void LayoutAndPaintAsync();
   void LayoutAndPaintAsyncThen(v8::Local<v8::Function> callback);
 
diff --git a/content/shell/test_runner/web_widget_test_client.cc b/content/shell/test_runner/web_widget_test_client.cc
index 5fd30f4..343997f 100644
--- a/content/shell/test_runner/web_widget_test_client.cc
+++ b/content/shell/test_runner/web_widget_test_client.cc
@@ -49,10 +49,13 @@
     return;
 
   animation_scheduled_ = false;
+  bool animation_requires_raster = test_runner()->animation_requires_raster();
   blink::WebWidget* web_widget = web_widget_test_proxy_base_->web_widget();
-  web_widget->UpdateAllLifecyclePhasesAndCompositeForTesting();
+  web_widget->UpdateAllLifecyclePhasesAndCompositeForTesting(
+      animation_requires_raster);
   if (blink::WebPagePopup* popup = web_widget->GetPagePopup())
-    popup->UpdateAllLifecyclePhasesAndCompositeForTesting();
+    popup->UpdateAllLifecyclePhasesAndCompositeForTesting(
+        animation_requires_raster);
 }
 
 blink::WebScreenInfo WebWidgetTestClient::GetScreenInfo() {
diff --git a/docs/testing/writing_layout_tests.md b/docs/testing/writing_layout_tests.md
index f71eb3a..9fa8b07 100644
--- a/docs/testing/writing_layout_tests.md
+++ b/docs/testing/writing_layout_tests.md
@@ -491,6 +491,18 @@
 [third_party/WebKit/LayoutTests/paint/invalidation/resources/text-based-repaint.js](../../third_party/WebKit/LayoutTests/paint/invalidation/resources/text-based-repaint.js)
 to help with writing paint invalidation and repaint tests.
 
+### Tests for scrolling animations
+
+Some layout tests need to ensure animations such as middle-click auto-scroll,
+fling, etc. get performed properly. When testing in display compositor pixel
+dump mode (now the standard), the standard behavior for tests is to
+synchronously composite without rastering (to save time). However, animations
+run upon surface activation, which only happens once rasterization is performed.
+Therefore, for these tests, an additional setting needs to be set. Near the
+beginning of these tests, call `continuouslyRunAnimations()` defined in
+[third_party/WebKit/LayoutTests/resources/compositor-controls.js](../../third_party/WebKit/LayoutTests/resources/compositor-controls.js)
+which will enable full rasterization during the test.
+
 ## Layout tree tests
 
 A layout tree test renders a web page and produces up to two results, which
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index af244aa..bfae9c4 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -82,6 +82,7 @@
     // WebRequest logic that cares, e.g. some permission checking to determine
     // when to filter certain kinds of requests.
     info_->type.reset();
+    info_->web_request_type = WebRequestResourceType::OTHER;
   }
 
   auto continuation =
diff --git a/extensions/common/permissions/media_galleries_permission.h b/extensions/common/permissions/media_galleries_permission.h
index 40a2277b..706cd5ba 100644
--- a/extensions/common/permissions/media_galleries_permission.h
+++ b/extensions/common/permissions/media_galleries_permission.h
@@ -25,6 +25,7 @@
 //   {"mediaGalleries": "read delete"},
 // We also allow a permission without any sub-permissions:
 //   "mediaGalleries",
+// TODO(devlin): Move this class to chrome/common/apps/platform_apps.
 class MediaGalleriesPermission
   : public SetDisjunctionPermission<MediaGalleriesPermissionData,
                                     MediaGalleriesPermission> {
diff --git a/google_apis/gaia/gaia_auth_fetcher.h b/google_apis/gaia/gaia_auth_fetcher.h
index cb5662b..130861c 100644
--- a/google_apis/gaia/gaia_auth_fetcher.h
+++ b/google_apis/gaia/gaia_auth_fetcher.h
@@ -33,6 +33,15 @@
 
 class GaiaAuthFetcherTest;
 
+namespace signin {
+// Mode determining whether Gaia can change the order of the accounts in
+// cookies.
+enum class MultiloginMode {
+  MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER = 0,
+  MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER
+};
+}  // namespace signin
+
 namespace network {
 class SimpleURLLoader;
 class SharedURLLoaderFactory;
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 93c5758f7..5260da7 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -272,8 +272,6 @@
     "lib/browser/protocol/dp_browser.h",
     "lib/browser/protocol/dp_headless_experimental.cc",
     "lib/browser/protocol/dp_headless_experimental.h",
-    "lib/browser/protocol/dp_network.cc",
-    "lib/browser/protocol/dp_network.h",
     "lib/browser/protocol/dp_page.cc",
     "lib/browser/protocol/dp_page.h",
     "lib/browser/protocol/dp_target.cc",
@@ -304,8 +302,6 @@
     "lib/browser/headless_devtools_client_impl.cc",
     "lib/browser/headless_devtools_manager_delegate.cc",
     "lib/browser/headless_devtools_manager_delegate.h",
-    "lib/browser/headless_network_conditions.cc",
-    "lib/browser/headless_network_conditions.h",
     "lib/browser/headless_permission_manager.cc",
     "lib/browser/headless_permission_manager.h",
     "lib/browser/headless_platform_event_source.cc",
@@ -327,8 +323,6 @@
     "lib/browser/protocol/headless_devtools_session.h",
     "lib/browser/protocol/headless_handler.cc",
     "lib/browser/protocol/headless_handler.h",
-    "lib/browser/protocol/network_handler.cc",
-    "lib/browser/protocol/network_handler.h",
     "lib/browser/protocol/page_handler.cc",
     "lib/browser/protocol/page_handler.h",
     "lib/browser/protocol/protocol_string.cc",
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index 4a19349..d90b6a6 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -363,15 +363,6 @@
   return UniqueId();
 }
 
-void HeadlessBrowserContextImpl::SetNetworkConditions(
-    HeadlessNetworkConditions conditions) {
-  network_conditions_ = conditions;
-}
-
-HeadlessNetworkConditions HeadlessBrowserContextImpl::GetNetworkConditions() {
-  return network_conditions_;
-}
-
 HeadlessBrowserContext::Builder::Builder(HeadlessBrowserImpl* browser)
     : browser_(browser),
       options_(new HeadlessBrowserContextOptions(browser->options())) {}
diff --git a/headless/lib/browser/headless_browser_context_impl.h b/headless/lib/browser/headless_browser_context_impl.h
index 25b9cf2..120a37c 100644
--- a/headless/lib/browser/headless_browser_context_impl.h
+++ b/headless/lib/browser/headless_browser_context_impl.h
@@ -16,7 +16,6 @@
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/resource_context.h"
 #include "headless/lib/browser/headless_browser_context_options.h"
-#include "headless/lib/browser/headless_network_conditions.h"
 #include "headless/lib/browser/headless_url_request_context_getter.h"
 #include "headless/public/headless_browser.h"
 #include "headless/public/headless_browser_context.h"
@@ -110,9 +109,6 @@
   const base::UnguessableToken* GetDevToolsFrameTokenForFrameTreeNodeId(
       int frame_tree_node_id) const;
 
-  void SetNetworkConditions(HeadlessNetworkConditions conditions);
-  HeadlessNetworkConditions GetNetworkConditions() override;
-
  private:
   HeadlessBrowserContextImpl(
       HeadlessBrowserImpl* browser,
@@ -144,8 +140,6 @@
   std::unique_ptr<content::PermissionControllerDelegate>
       permission_controller_delegate_;
 
-  HeadlessNetworkConditions network_conditions_;
-
   DISALLOW_COPY_AND_ASSIGN(HeadlessBrowserContextImpl);
 };
 
diff --git a/headless/lib/browser/headless_network_conditions.cc b/headless/lib/browser/headless_network_conditions.cc
deleted file mode 100644
index 208208c90..0000000
--- a/headless/lib/browser/headless_network_conditions.cc
+++ /dev/null
@@ -1,26 +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 "headless/lib/browser/headless_network_conditions.h"
-
-namespace headless {
-
-HeadlessNetworkConditions::HeadlessNetworkConditions()
-    : HeadlessNetworkConditions(false) {}
-
-HeadlessNetworkConditions::HeadlessNetworkConditions(bool offline)
-    : HeadlessNetworkConditions(offline, 0, 0, 0) {}
-
-HeadlessNetworkConditions::HeadlessNetworkConditions(bool offline,
-                                                     double latency,
-                                                     double download_throughput,
-                                                     double upload_throughput)
-    : offline(offline),
-      latency(latency),
-      download_throughput(download_throughput),
-      upload_throughput(upload_throughput) {}
-
-HeadlessNetworkConditions::~HeadlessNetworkConditions() = default;
-
-}  // namespace headless
diff --git a/headless/lib/browser/headless_network_conditions.h b/headless/lib/browser/headless_network_conditions.h
deleted file mode 100644
index 041847d..0000000
--- a/headless/lib/browser/headless_network_conditions.h
+++ /dev/null
@@ -1,36 +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 HEADLESS_LIB_BROWSER_HEADLESS_NETWORK_CONDITIONS_H_
-#define HEADLESS_LIB_BROWSER_HEADLESS_NETWORK_CONDITIONS_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-#include "headless/public/headless_export.h"
-
-namespace headless {
-
-// HeadlessNetworkConditions holds information about desired network conditions.
-struct HEADLESS_EXPORT HeadlessNetworkConditions {
-  HeadlessNetworkConditions();
-  ~HeadlessNetworkConditions();
-
-  explicit HeadlessNetworkConditions(bool offline);
-  HeadlessNetworkConditions(bool offline,
-                            double latency,
-                            double download_throughput,
-                            double upload_throughput);
-
-  bool offline;
-  double latency;
-  double download_throughput;
-  double upload_throughput;
-};
-
-}  // namespace headless
-
-#endif  // HEADLESS_LIB_BROWSER_HEADLESS_NETWORK_CONDITIONS_H_
diff --git a/headless/lib/browser/protocol/headless_devtools_session.cc b/headless/lib/browser/protocol/headless_devtools_session.cc
index d7cc307..7eb37595 100644
--- a/headless/lib/browser/protocol/headless_devtools_session.cc
+++ b/headless/lib/browser/protocol/headless_devtools_session.cc
@@ -8,7 +8,6 @@
 #include "content/public/browser/devtools_agent_host_client.h"
 #include "headless/lib/browser/protocol/browser_handler.h"
 #include "headless/lib/browser/protocol/headless_handler.h"
-#include "headless/lib/browser/protocol/network_handler.h"
 #include "headless/lib/browser/protocol/page_handler.h"
 #include "headless/lib/browser/protocol/target_handler.h"
 
@@ -32,7 +31,6 @@
   }
   if (agent_host->GetType() == content::DevToolsAgentHost::kTypeBrowser)
     AddHandler(std::make_unique<BrowserHandler>(browser_));
-  AddHandler(std::make_unique<NetworkHandler>(browser_));
   AddHandler(std::make_unique<TargetHandler>(browser_));
 }
 
diff --git a/headless/lib/browser/protocol/network_handler.cc b/headless/lib/browser/protocol/network_handler.cc
deleted file mode 100644
index ff8a1bd..0000000
--- a/headless/lib/browser/protocol/network_handler.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "headless/lib/browser/protocol/network_handler.h"
-
-#include "headless/lib/browser/headless_browser_context_impl.h"
-#include "headless/lib/browser/headless_browser_impl.h"
-
-namespace headless {
-namespace protocol {
-
-NetworkHandler::NetworkHandler(base::WeakPtr<HeadlessBrowserImpl> browser)
-    : DomainHandler(Network::Metainfo::domainName, browser) {}
-
-NetworkHandler::~NetworkHandler() = default;
-
-void NetworkHandler::Wire(UberDispatcher* dispatcher) {
-  Network::Dispatcher::wire(dispatcher, this);
-}
-
-Response NetworkHandler::EmulateNetworkConditions(
-    bool offline,
-    double latency,
-    double download_throughput,
-    double upload_throughput,
-    Maybe<Network::ConnectionType>) {
-  // Associate NetworkConditions to context
-  std::vector<HeadlessBrowserContext*> browser_contexts =
-      browser()->GetAllBrowserContexts();
-  HeadlessNetworkConditions conditions(HeadlessNetworkConditions(
-      offline, std::max(latency, 0.0), std::max(download_throughput, 0.0),
-      std::max(upload_throughput, 0.0)));
-  SetNetworkConditions(browser_contexts, conditions);
-  return Response::FallThrough();
-}
-
-Response NetworkHandler::Disable() {
-  // Can be a part of the shutdown cycle.
-  if (!browser())
-    return Response::OK();
-  std::vector<HeadlessBrowserContext*> browser_contexts =
-      browser()->GetAllBrowserContexts();
-  SetNetworkConditions(browser_contexts, HeadlessNetworkConditions());
-  return Response::FallThrough();
-}
-
-void NetworkHandler::SetNetworkConditions(
-    std::vector<HeadlessBrowserContext*> browser_contexts,
-    HeadlessNetworkConditions conditions) {
-  for (std::vector<HeadlessBrowserContext*>::iterator it =
-           browser_contexts.begin();
-       it != browser_contexts.end(); ++it) {
-    HeadlessBrowserContextImpl* context =
-        static_cast<HeadlessBrowserContextImpl*>(*it);
-    context->SetNetworkConditions(conditions);
-  }
-}
-
-}  // namespace protocol
-}  // namespace headless
diff --git a/headless/lib/browser/protocol/network_handler.h b/headless/lib/browser/protocol/network_handler.h
deleted file mode 100644
index b9c3e30..0000000
--- a/headless/lib/browser/protocol/network_handler.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef HEADLESS_LIB_BROWSER_PROTOCOL_NETWORK_HANDLER_H_
-#define HEADLESS_LIB_BROWSER_PROTOCOL_NETWORK_HANDLER_H_
-
-#include "headless/lib/browser/headless_network_conditions.h"
-#include "headless/lib/browser/protocol/domain_handler.h"
-#include "headless/lib/browser/protocol/dp_network.h"
-
-namespace headless {
-
-class HeadlessBrowserContext;
-
-namespace protocol {
-
-class NetworkHandler : public DomainHandler, public Network::Backend {
- public:
-  explicit NetworkHandler(base::WeakPtr<HeadlessBrowserImpl> browser);
-  ~NetworkHandler() override;
-
-  void Wire(UberDispatcher* dispatcher) override;
-
-  // Network::Backend implementation
-  Response EmulateNetworkConditions(
-      bool offline,
-      double latency,
-      double download_throughput,
-      double upload_throughput,
-      Maybe<Network::ConnectionType> connection_type) override;
-  Response Disable() override;
-
- private:
-  void SetNetworkConditions(
-      std::vector<HeadlessBrowserContext*> browser_contexts,
-      HeadlessNetworkConditions conditions);
-  DISALLOW_COPY_AND_ASSIGN(NetworkHandler);
-};
-
-}  // namespace protocol
-}  // namespace headless
-
-#endif  // HEADLESS_LIB_BROWSER_PROTOCOL_NETWORK_HANDLER_H_
diff --git a/headless/protocol_config.json b/headless/protocol_config.json
index 80fc13a2..78bba00 100644
--- a/headless/protocol_config.json
+++ b/headless/protocol_config.json
@@ -25,11 +25,6 @@
                 "async": ["beginFrame"]
             },
             {
-                "domain": "Network",
-                "include": ["emulateNetworkConditions", "disable"],
-                "include_events": []
-            },
-            {
                 "domain": "Page",
                 "include": ["printToPDF"],
                 "async": ["printToPDF"],
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h
index 8c2ecb6..0a21c55 100644
--- a/headless/public/headless_browser_context.h
+++ b/headless/public/headless_browser_context.h
@@ -15,7 +15,6 @@
 #include "base/optional.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/common/web_preferences.h"
-#include "headless/lib/browser/headless_network_conditions.h"
 #include "headless/public/headless_export.h"
 #include "headless/public/headless_web_contents.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
@@ -65,8 +64,6 @@
   // GUID for this browser context.
   virtual const std::string& Id() const = 0;
 
-  virtual HeadlessNetworkConditions GetNetworkConditions() = 0;
-
   // TODO(skyostil): Allow saving and restoring contexts (crbug.com/617931).
 
  protected:
diff --git a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
index 4992d1b..c7fbd6d0 100644
--- a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
+++ b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
@@ -79,15 +79,15 @@
 
   base::DictionaryValue selectDict = base::DictionaryValue();
   selectDict.SetKey("type", base::Value("select"));
-  selectDict.SetKey("selector", base::Value("//*[@id=\"test_dropdown\"]"));
-  selectDict.SetKey("index", base::Value(1));
+  selectDict.SetKey("selector", base::Value("//*[@name=\"cc_month_exp\"]"));
+  selectDict.SetKey("index", base::Value(5));
   AutomationAction* selectAction =
       [AutomationAction actionWithValueDictionary:selectDict];
   [selectAction execute];
 
   NSError* error;
   id result = chrome_test_util::ExecuteJavaScript(
-      @"document.getElementById(\"test_dropdown\").value == \"dropdown_2\"",
+      @"document.getElementsByName(\"cc_month_exp\")[0].value == \"6\"",
       &error);
   GREYAssert([result boolValue] && !error,
              @"Select automation action did not change the dropdown.");
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 00f3291..b5c8152 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -26,9 +26,9 @@
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/consent_auditor/consent_auditor.h"
 #include "components/dom_distiller/core/dom_distiller_service.h"
-#include "components/history/core/browser/history_model_worker.h"
 #include "components/history/core/browser/history_service.h"
-#include "components/history/core/browser/typed_url_sync_bridge.h"
+#include "components/history/core/browser/sync/history_model_worker.h"
+#include "components/history/core/browser/sync/typed_url_sync_bridge.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/password_manager/core/browser/password_model_worker.h"
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index b437e9f..3ae6d68e 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -143,6 +143,7 @@
   self.omniboxPopupCoordinator =
       [self.omniboxCoordinator createPopupCoordinator:self.popupPositioner];
   self.omniboxPopupCoordinator.dispatcher = self.dispatcher;
+  self.omniboxPopupCoordinator.webStateList = self.webStateList;
   [self.omniboxPopupCoordinator start];
 
   self.mediator =
@@ -265,11 +266,13 @@
     [self.viewController.dispatcher focusFakebox];
   } else {
     [self.omniboxCoordinator focusOmnibox];
+    [self.omniboxPopupCoordinator openPopup];
   }
 }
 
 - (void)cancelOmniboxEdit {
   [self.omniboxCoordinator endEditing];
+  [self.omniboxPopupCoordinator closePopup];
 }
 
 #pragma mark - LocationBarDelegate
diff --git a/ios/chrome/browser/ui/material_components/BUILD.gn b/ios/chrome/browser/ui/material_components/BUILD.gn
index a26ab601..1c2163b 100644
--- a/ios/chrome/browser/ui/material_components/BUILD.gn
+++ b/ios/chrome/browser/ui/material_components/BUILD.gn
@@ -7,7 +7,6 @@
   sources = [
     "activity_indicator.h",
     "activity_indicator.mm",
-    "app_bar_presenting.h",
     "app_bar_view_controller_presenting.h",
     "chrome_app_bar_view_controller.h",
     "chrome_app_bar_view_controller.m",
diff --git a/ios/chrome/browser/ui/material_components/app_bar_presenting.h b/ios/chrome/browser/ui/material_components/app_bar_presenting.h
deleted file mode 100644
index a304a60..0000000
--- a/ios/chrome/browser/ui/material_components/app_bar_presenting.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_APP_BAR_PRESENTING_H_
-#define IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_APP_BAR_PRESENTING_H_
-
-#import <UIKit/UIKit.h>
-
-@class MDCAppBar;
-
-// An object conforming to this protocol is capable of creating and managing an
-// MDCAppBar. Typically, UIViewController's can implement this protocol to vend
-// the app bar they can optionally be presenting.
-@protocol AppBarPresenting<NSObject>
-
-// The installed app bar, if any.
-@property(nonatomic, readonly, strong) MDCAppBar* appBar;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_APP_BAR_PRESENTING_H_
diff --git a/ios/chrome/browser/ui/material_components/utils.h b/ios/chrome/browser/ui/material_components/utils.h
index 075123a..dc9636c 100644
--- a/ios/chrome/browser/ui/material_components/utils.h
+++ b/ios/chrome/browser/ui/material_components/utils.h
@@ -5,13 +5,9 @@
 #ifndef IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_UTILS_H_
 #define IOS_CHROME_BROWSER_UI_MATERIAL_COMPONENTS_UTILS_H_
 
-@class MDCAppBar;
 @class MDCAppBarViewController;
 @class UIScrollView;
 
-// Styles the passed app bar for displaying in Settings, history, bookmarks,
-// etc. It follows the card style for collection views.
-void ConfigureAppBarWithCardStyle(MDCAppBar* appBar);
 // Styles the passed app bar view controller for displaying in Settings,
 // history, bookmarks, etc. It follows the card style for collection views.
 void ConfigureAppBarViewControllerWithCardStyle(
diff --git a/ios/chrome/browser/ui/material_components/utils.mm b/ios/chrome/browser/ui/material_components/utils.mm
index 74c41b19..33fd717 100644
--- a/ios/chrome/browser/ui/material_components/utils.mm
+++ b/ios/chrome/browser/ui/material_components/utils.mm
@@ -36,18 +36,6 @@
                           intensityDidChangeBlock:intensityBlock];
 }
 
-void ConfigureAppBarWithCardStyle(MDCAppBar* appBar) {
-  appBar.headerViewController.headerView.canOverExtend = NO;
-  appBar.headerViewController.headerView.shiftBehavior =
-      MDCFlexibleHeaderShiftBehaviorDisabled;
-  appBar.headerViewController.headerView.backgroundColor =
-      [[MDCPalette greyPalette] tint200];
-  appBar.navigationBar.tintColor = [[MDCPalette greyPalette] tint900];
-  appBar.navigationBar.titleAlignment = MDCNavigationBarTitleAlignmentLeading;
-
-  CustomizeAppBarShadow(appBar.headerViewController);
-}
-
 void ConfigureAppBarViewControllerWithCardStyle(
     MDCAppBarViewController* viewController) {
   viewController.headerView.canOverExtend = NO;
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
index a99211a2..dcf6fac 100644
--- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -32,12 +32,14 @@
     "//ios/chrome/browser/ui:ui",
     "//ios/chrome/browser/ui:ui_util",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/ntp:util",
     "//ios/chrome/browser/ui/omnibox:omnibox_popup_shared",
     "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/public:feature_flags",
     "//ios/chrome/browser/ui/toolbar/public:public",
     "//ios/chrome/browser/ui/util:util",
+    "//ios/chrome/browser/web_state_list:web_state_list",
     "//ios/web/public:public",
     "//net",
   ]
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h
index d10d50e..b2dfb8d 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h
@@ -16,6 +16,7 @@
 namespace ios {
 class ChromeBrowserState;
 }
+class WebStateList;
 
 // Coordinator for the Omnibox Popup.
 @interface OmniboxPopupCoordinator : NSObject
@@ -34,9 +35,18 @@
 @property(nonatomic, assign, readonly) BOOL isOpen;
 // The dispatcher for this view controller.
 @property(nonatomic, readwrite, weak) CommandDispatcher* dispatcher;
+// The web state list this coordinator is handling.
+@property(nonatomic, assign) WebStateList* webStateList;
 
 - (void)start;
 - (void)stop;
+
+// Opens the popup immediately. It's auto-sized to fit the suggestions.
+- (void)openPopup;
+
+// Closes the popup immediately.
+- (void)closePopup;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
index 5012569..7a2178c 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -4,16 +4,20 @@
 
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.h"
 
+#include "base/feature_list.h"
 #import "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
 #include "components/omnibox/browser/autocomplete_result.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
+#import "ios/chrome/browser/ui/ntp/ntp_util.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_presenter.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h"
 #include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.h"
 #include "ios/chrome/browser/ui/ui_util.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -91,6 +95,25 @@
   return self.mediator.isOpen;
 }
 
+- (void)openPopup {
+  // Show shortcuts when the feature is enabled. Don't show them on NTP as they
+  // are already part of the NTP.
+  if (!IsVisibleUrlNewTabPage(self.webStateList->GetActiveWebState()) &&
+      base::FeatureList::IsEnabled(
+          omnibox::kOmniboxPopupShortcutIconsInZeroState)) {
+    self.popupViewController.shortcutsEnabled = YES;
+  }
+
+  [self.mediator.presenter updateHeightAndAnimateAppearanceIfNecessary];
+  self.mediator.open = YES;
+}
+
+- (void)closePopup {
+  self.mediator.open = NO;
+  self.popupViewController.shortcutsEnabled = NO;
+  [self.mediator.presenter animateCollapse];
+}
+
 #pragma mark - Property accessor
 
 - (BOOL)hasResults {
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
index d013d3a..3322132 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.mm
@@ -87,8 +87,6 @@
 
   if (self.open) {
     [self.presenter updateHeightAndAnimateAppearanceIfNecessary];
-  } else {
-    [self.presenter animateCollapse];
   }
 }
 
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index 63bbf351..33d4f0f 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -11,7 +11,6 @@
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h"
-#import "ios/chrome/browser/ui/material_components/app_bar_presenting.h"
 #import "ios/chrome/browser/ui/material_components/app_bar_view_controller_presenting.h"
 #import "ios/chrome/browser/ui/material_components/utils.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
@@ -557,8 +556,7 @@
 - (UIViewController*)wrappedControllerIfNeeded:(UIViewController*)controller {
   // If the controller can't be presented with an app bar, it needs to be
   // wrapped in an MDCAppBarContainerViewController.
-  if (![controller conformsToProtocol:@protocol(AppBarPresenting)] &&
-      ![controller
+  if (![controller
           conformsToProtocol:@protocol(AppBarViewControllerPresenting)]) {
     MDCAppBarContainerViewController* appBarContainer =
         [[SettingsAppBarContainerViewController alloc]
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h
index db0ff1e7..04fb622e 100644
--- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h
+++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h
@@ -7,7 +7,6 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ui/material_components/app_bar_presenting.h"
 #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h"
 
 // TableCellCatalogViewController is a Debug-only settings screen which serves
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
index 1fae370..f62455b3 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -259,7 +259,7 @@
   return view;
 }
 
-#pragma mark - MDCAppBar support
+#pragma mark - MDCAppBarViewController support
 
 - (UIViewController*)childViewControllerForStatusBarHidden {
   return self.appBarViewController;
diff --git a/media/base/android/android_util.cc b/media/base/android/android_util.cc
index e2252c9..ca627d9 100644
--- a/media/base/android/android_util.cc
+++ b/media/base/android/android_util.cc
@@ -12,19 +12,6 @@
 
 namespace media {
 
-std::string JavaBytesToString(JNIEnv* env, jbyteArray j_byte_array) {
-  std::vector<uint8_t> byte_vector;
-  base::android::JavaByteArrayToByteVector(env, j_byte_array, &byte_vector);
-  return std::string(byte_vector.begin(), byte_vector.end());
-}
-
-base::android::ScopedJavaLocalRef<jbyteArray> StringToJavaBytes(
-    JNIEnv* env,
-    const std::string& str) {
-  return base::android::ToJavaByteArray(
-      env, reinterpret_cast<const uint8_t*>(str.data()), str.size());
-}
-
 JavaObjectPtr CreateJavaObjectPtr(jobject object) {
   JavaObjectPtr j_object_ptr(new base::android::ScopedJavaGlobalRef<jobject>());
   j_object_ptr->Reset(base::android::AttachCurrentThread(), object);
diff --git a/media/base/android/android_util.h b/media/base/android/android_util.h
index 650be942..39026177 100644
--- a/media/base/android/android_util.h
+++ b/media/base/android/android_util.h
@@ -16,14 +16,6 @@
 using JavaObjectPtr =
     std::unique_ptr<base::android::ScopedJavaGlobalRef<jobject>>;
 
-// Converts jbyteArray (byte[] in Java) into std::string.
-std::string JavaBytesToString(JNIEnv* env, jbyteArray j_byte_array);
-
-// Converts std::string to jbyteArray (byte[] in Java).
-base::android::ScopedJavaLocalRef<jbyteArray> StringToJavaBytes(
-    JNIEnv* env,
-    const std::string& str);
-
 // A helper method to create a JavaObjectPtr.
 JavaObjectPtr CreateJavaObjectPtr(jobject object);
 
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc
index d03c4e8..ac782a4 100644
--- a/media/base/android/media_drm_bridge.cc
+++ b/media/base/android/media_drm_bridge.cc
@@ -40,9 +40,11 @@
 using base::android::ConvertUTF8ToJavaString;
 using base::android::ConvertJavaStringToUTF8;
 using base::android::JavaByteArrayToByteVector;
+using base::android::JavaByteArrayToString;
 using base::android::JavaParamRef;
 using base::android::ScopedJavaGlobalRef;
 using base::android::ScopedJavaLocalRef;
+using base::android::ToJavaByteArray;
 
 namespace media {
 
@@ -471,7 +473,7 @@
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jbyteArray> j_session_id =
-      StringToJavaBytes(env, session_id);
+      ToJavaByteArray(env, session_id);
   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
   Java_MediaDrmBridge_loadSession(env, j_media_drm_, j_session_id, promise_id);
 }
@@ -487,7 +489,7 @@
   ScopedJavaLocalRef<jbyteArray> j_response =
       base::android::ToJavaByteArray(env, response.data(), response.size());
   ScopedJavaLocalRef<jbyteArray> j_session_id =
-      StringToJavaBytes(env, session_id);
+      ToJavaByteArray(env, session_id);
   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
   Java_MediaDrmBridge_updateSession(env, j_media_drm_, j_session_id, j_response,
                                     promise_id);
@@ -501,7 +503,7 @@
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jbyteArray> j_session_id =
-      StringToJavaBytes(env, session_id);
+      ToJavaByteArray(env, session_id);
   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
   Java_MediaDrmBridge_closeSession(env, j_media_drm_, j_session_id, promise_id);
 }
@@ -514,7 +516,7 @@
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jbyteArray> j_session_id =
-      StringToJavaBytes(env, session_id);
+      ToJavaByteArray(env, session_id);
   uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
   Java_MediaDrmBridge_removeSession(env, j_media_drm_, j_session_id,
                                     promise_id);
@@ -606,8 +608,8 @@
   if (!task_runner_->BelongsToCurrentThread()) {
     task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB,
-                   weak_factory_.GetWeakPtr(), media_crypto_ready_cb));
+        base::BindOnce(&MediaDrmBridge::SetMediaCryptoReadyCB,
+                       weak_factory_.GetWeakPtr(), media_crypto_ready_cb));
     return;
   }
 
@@ -642,9 +644,9 @@
 
   task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&MediaDrmBridge::NotifyMediaCryptoReady,
-                 weak_factory_.GetWeakPtr(),
-                 base::Passed(CreateJavaObjectPtr(j_media_crypto.obj()))));
+      base::BindOnce(&MediaDrmBridge::NotifyMediaCryptoReady,
+                     weak_factory_.GetWeakPtr(),
+                     base::Passed(CreateJavaObjectPtr(j_media_crypto.obj()))));
 }
 
 void MediaDrmBridge::OnStartProvisioning(
@@ -654,19 +656,21 @@
     const JavaParamRef<jbyteArray>& j_request_data) {
   DVLOG(1) << __func__;
 
-  task_runner_->PostTask(FROM_HERE,
-                         base::Bind(&MediaDrmBridge::SendProvisioningRequest,
-                                    weak_factory_.GetWeakPtr(),
-                                    ConvertJavaStringToUTF8(env, j_default_url),
-                                    JavaBytesToString(env, j_request_data)));
+  std::string request_data;
+  JavaByteArrayToString(env, j_request_data, &request_data);
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaDrmBridge::SendProvisioningRequest,
+                                weak_factory_.GetWeakPtr(),
+                                ConvertJavaStringToUTF8(env, j_default_url),
+                                std::move(request_data)));
 }
 
 void MediaDrmBridge::OnPromiseResolved(JNIEnv* env,
                                        const JavaParamRef<jobject>& j_media_drm,
                                        jint j_promise_id) {
-  task_runner_->PostTask(FROM_HERE,
-                         base::Bind(&MediaDrmBridge::ResolvePromise,
-                                    weak_factory_.GetWeakPtr(), j_promise_id));
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaDrmBridge::ResolvePromise,
+                                weak_factory_.GetWeakPtr(), j_promise_id));
 }
 
 void MediaDrmBridge::OnPromiseResolvedWithSession(
@@ -674,10 +678,12 @@
     const JavaParamRef<jobject>& j_media_drm,
     jint j_promise_id,
     const JavaParamRef<jbyteArray>& j_session_id) {
-  task_runner_->PostTask(FROM_HERE,
-                         base::Bind(&MediaDrmBridge::ResolvePromiseWithSession,
-                                    weak_factory_.GetWeakPtr(), j_promise_id,
-                                    JavaBytesToString(env, j_session_id)));
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaDrmBridge::ResolvePromiseWithSession,
+                                weak_factory_.GetWeakPtr(), j_promise_id,
+                                std::move(session_id)));
 }
 
 void MediaDrmBridge::OnPromiseRejected(
@@ -686,9 +692,9 @@
     jint j_promise_id,
     const JavaParamRef<jstring>& j_error_message) {
   task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&MediaDrmBridge::RejectPromise, weak_factory_.GetWeakPtr(),
-                 j_promise_id, ConvertJavaStringToUTF8(env, j_error_message)));
+      FROM_HERE, base::BindOnce(&MediaDrmBridge::RejectPromise,
+                                weak_factory_.GetWeakPtr(), j_promise_id,
+                                ConvertJavaStringToUTF8(env, j_error_message)));
 }
 
 void MediaDrmBridge::OnSessionMessage(
@@ -704,10 +710,11 @@
   CdmMessageType message_type =
       GetMessageType(static_cast<RequestType>(j_message_type));
 
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
   task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(session_message_cb_, JavaBytesToString(env, j_session_id),
-                 message_type, message));
+      FROM_HERE, base::BindOnce(session_message_cb_, std::move(session_id),
+                                message_type, message));
 }
 
 void MediaDrmBridge::OnSessionClosed(
@@ -715,9 +722,10 @@
     const JavaParamRef<jobject>& j_media_drm,
     const JavaParamRef<jbyteArray>& j_session_id) {
   DVLOG(2) << __func__;
-  std::string session_id = JavaBytesToString(env, j_session_id);
-  task_runner_->PostTask(FROM_HERE,
-                         base::BindOnce(session_closed_cb_, session_id));
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(session_closed_cb_, std::move(session_id)));
 }
 
 void MediaDrmBridge::OnSessionKeysChange(
@@ -756,15 +764,17 @@
         std::make_unique<CdmKeyInformation>(key_id, key_status, 0));
   }
 
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
   task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(session_keys_change_cb_, JavaBytesToString(env, j_session_id),
-                 has_additional_usable_key, base::Passed(&cdm_keys_info)));
+      base::BindOnce(session_keys_change_cb_, std::move(session_id),
+                     has_additional_usable_key, base::Passed(&cdm_keys_info)));
 
   if (has_additional_usable_key) {
-    task_runner_->PostTask(FROM_HERE,
-                           base::Bind(&MediaDrmBridge::OnHasAdditionalUsableKey,
-                                      weak_factory_.GetWeakPtr()));
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaDrmBridge::OnHasAdditionalUsableKey,
+                                  weak_factory_.GetWeakPtr()));
   }
 }
 
@@ -785,10 +795,11 @@
     const JavaParamRef<jbyteArray>& j_session_id,
     jlong expiry_time_ms) {
   DVLOG(2) << __func__ << ": " << expiry_time_ms << " ms";
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
   task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(session_expiration_update_cb_,
-                     JavaBytesToString(env, j_session_id),
+      base::BindOnce(session_expiration_update_cb_, std::move(session_id),
                      base::Time::FromDoubleT(expiry_time_ms / 1000.0)));
 }
 
@@ -938,7 +949,7 @@
 
   JNIEnv* env = AttachCurrentThread();
 
-  ScopedJavaLocalRef<jbyteArray> j_response = StringToJavaBytes(env, response);
+  ScopedJavaLocalRef<jbyteArray> j_response = ToJavaByteArray(env, response);
 
   Java_MediaDrmBridge_processProvisionResponse(env, j_media_drm_, success,
                                                j_response);
diff --git a/media/base/android/media_drm_storage_bridge.cc b/media/base/android/media_drm_storage_bridge.cc
index d72e965..de6ed51 100644
--- a/media/base/android/media_drm_storage_bridge.cc
+++ b/media/base/android/media_drm_storage_bridge.cc
@@ -22,6 +22,7 @@
 using base::android::AttachCurrentThread;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaByteArrayToByteVector;
+using base::android::JavaByteArrayToString;
 using base::android::JavaParamRef;
 using base::android::RunBooleanCallbackAndroid;
 using base::android::RunObjectCallbackAndroid;
@@ -69,7 +70,8 @@
     // Callback<PersistentInfo>
     const JavaParamRef<jobject>& j_callback) {
   DCHECK(impl_);
-  std::string session_id = JavaBytesToString(env, j_session_id);
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
   task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
@@ -96,8 +98,9 @@
   std::string mime = ConvertJavaStringToUTF8(
       env, Java_PersistentInfo_mimeType(env, j_persist_info));
 
-  std::string session_id = JavaBytesToString(
-      env, Java_PersistentInfo_emeId(env, j_persist_info).obj());
+  std::string session_id;
+  JavaByteArrayToString(
+      env, Java_PersistentInfo_emeId(env, j_persist_info).obj(), &session_id);
 
   task_runner_->PostTask(
       FROM_HERE,
@@ -117,11 +120,13 @@
     // Callback<Boolean>
     const JavaParamRef<jobject>& j_callback) {
   DCHECK(impl_);
+  std::string session_id;
+  JavaByteArrayToString(env, j_session_id, &session_id);
   task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
           &MediaDrmStorage::RemovePersistentSession, impl_->AsWeakPtr(),
-          JavaBytesToString(env, j_session_id),
+          std::move(session_id),
           base::BindOnce(&MediaDrmStorageBridge::RunAndroidBoolCallback,
                          weak_factory_.GetWeakPtr(),
                          base::Passed(CreateJavaObjectPtr(j_callback.obj())))));
@@ -153,7 +158,7 @@
   }
 
   JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jbyteArray> j_eme_id = StringToJavaBytes(env, session_id);
+  ScopedJavaLocalRef<jbyteArray> j_eme_id = ToJavaByteArray(env, session_id);
   ScopedJavaLocalRef<jbyteArray> j_key_set_id = ToJavaByteArray(
       env, session_data->key_set_id.data(), session_data->key_set_id.size());
   ScopedJavaLocalRef<jstring> j_mime =
diff --git a/media/base/media_status.cc b/media/base/media_status.cc
index 4640eef..63e988e 100644
--- a/media/base/media_status.cc
+++ b/media/base/media_status.cc
@@ -15,11 +15,12 @@
 
 bool MediaStatus::operator==(const MediaStatus& other) const {
   return std::tie(title, can_play_pause, can_mute, can_set_volume, can_seek,
-                  play_state, is_muted, volume, duration, current_time) ==
+                  state, is_muted, volume, duration, current_time,
+                  reached_end_of_stream) ==
          std::tie(other.title, other.can_play_pause, other.can_mute,
-                  other.can_set_volume, other.can_seek, play_state,
+                  other.can_set_volume, other.can_seek, other.state,
                   other.is_muted, other.volume, other.duration,
-                  other.current_time);
+                  other.current_time, other.reached_end_of_stream);
 }
 
 }  // namespace media
diff --git a/media/base/media_status.h b/media/base/media_status.h
index 15b6d4f..8d913e3 100644
--- a/media/base/media_status.h
+++ b/media/base/media_status.h
@@ -16,7 +16,7 @@
 // TODO(https://crbug.com/820277): Deduplicate media_router::MediaStatus.
 struct MEDIA_EXPORT MediaStatus {
  public:
-  enum class PlayState { PLAYING, PAUSED, BUFFERING };
+  enum class State { UNKNOWN, PLAYING, PAUSED, BUFFERING, STOPPED };
 
   MediaStatus();
   MediaStatus(const MediaStatus& other);
@@ -41,7 +41,7 @@
   // If this is true, the media's current playback position can be changed.
   bool can_seek = false;
 
-  PlayState play_state = PlayState::PLAYING;
+  State state = State::UNKNOWN;
 
   bool is_muted = false;
 
@@ -56,6 +56,9 @@
 
   // Current playback position. Must be less than or equal to |duration|.
   base::TimeDelta current_time;
+
+  // True if we have reached the end of stream.
+  bool reached_end_of_stream = false;
 };
 
 }  // namespace media
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index b4ce7ac..88d611b 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -10,6 +10,7 @@
 #include "net/android/network_change_notifier_android.h"
 
 using base::android::JavaParamRef;
+using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
 
 namespace net {
@@ -51,10 +52,10 @@
 // static
 void NetworkChangeNotifierDelegateAndroid::JavaLongArrayToNetworkMap(
     JNIEnv* env,
-    jlongArray long_array,
+    const JavaRef<jlongArray>& long_array,
     NetworkMap* network_map) {
   std::vector<int64_t> int64_list;
-  base::android::JavaLongArrayToInt64Vector(env, long_array, &int64_list);
+  base::android::JavaLongArrayToInt64Vector(env, long_array.obj(), &int64_list);
   network_map->clear();
   for (auto i = int64_list.begin(); i != int64_list.end(); ++i) {
     NetworkChangeNotifier::NetworkHandle network_handle = *i;
@@ -86,7 +87,7 @@
   ScopedJavaLocalRef<jlongArray> networks_and_types =
       Java_NetworkChangeNotifier_getCurrentNetworksAndTypes(
           env, java_network_change_notifier_);
-  JavaLongArrayToNetworkMap(env, networks_and_types.obj(), &network_map);
+  JavaLongArrayToNetworkMap(env, networks_and_types, &network_map);
   SetCurrentNetworksAndTypes(network_map);
 }
 
diff --git a/net/android/network_change_notifier_delegate_android.h b/net/android/network_change_notifier_delegate_android.h
index d102f63..e36d39c 100644
--- a/net/android/network_change_notifier_delegate_android.h
+++ b/net/android/network_change_notifier_delegate_android.h
@@ -138,9 +138,10 @@
 
   // Converts a Java long[] into a NetworkMap. Expects long[] to contain
   // repeated instances of: NetworkHandle, ConnectionType
-  static void JavaLongArrayToNetworkMap(JNIEnv* env,
-                                        jlongArray long_array,
-                                        NetworkMap* network_map);
+  static void JavaLongArrayToNetworkMap(
+      JNIEnv* env,
+      const base::android::JavaRef<jlongArray>& long_array,
+      NetworkMap* network_map);
 
   // Setters that grab appropriate lock.
   void SetCurrentConnectionType(ConnectionType connection_type);
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 4f9d77ca..b4f3d5f7 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -12,11 +12,12 @@
 #include "base/strings/string_util.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "net/base/network_change_notifier_factory.h"
 #include "net/base/network_interfaces.h"
 #include "net/base/url_util.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/url_request/url_request.h"
 #include "url/gurl.h"
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index 40f30163..fccb3475 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -1137,6 +1137,8 @@
 
   histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_ATTEMPT);
 
+  CookieMap::iterator cookie_it_to_possibly_delete = cookies_.end();
+  CanonicalCookie* cc_skipped_secure = nullptr;
   for (CookieMapItPair its = cookies_.equal_range(key);
        its.first != its.second;) {
     CookieMap::iterator curit = its.first;
@@ -1152,6 +1154,7 @@
     if (cc->IsSecure() && !source_secure &&
         ecc.IsEquivalentForSecureCookieMatching(*cc)) {
       skipped_secure_cookie = true;
+      cc_skipped_secure = cc;
       histogram_cookie_delete_equivalent_->Add(
           COOKIE_DELETE_EQUIVALENT_SKIPPING_SECURE);
       net_log_.AddEvent(
@@ -1176,6 +1179,7 @@
       // and be considered equivalent.
       CHECK(!found_equivalent_cookie)
           << "Duplicate equivalent cookies found, cookie store is corrupted.";
+      DCHECK(cookie_it_to_possibly_delete == cookies_.end());
       if (skip_httponly && cc->IsHttpOnly()) {
         skipped_httponly = true;
         net_log_.AddEvent(
@@ -1183,20 +1187,38 @@
             base::BindRepeating(&NetLogCookieMonsterCookieRejectedHttponly, cc,
                                 &ecc));
       } else {
-        histogram_cookie_delete_equivalent_->Add(
-            COOKIE_DELETE_EQUIVALENT_FOUND);
-        if (cc->Value() == ecc.Value()) {
-          *creation_date_to_inherit = cc->CreationDate();
-          histogram_cookie_delete_equivalent_->Add(
-              COOKIE_DELETE_EQUIVALENT_FOUND_WITH_SAME_VALUE);
-        }
-        InternalDeleteCookie(curit, true, already_expired
-                                              ? DELETE_COOKIE_EXPIRED_OVERWRITE
-                                              : DELETE_COOKIE_OVERWRITE);
+        cookie_it_to_possibly_delete = curit;
       }
       found_equivalent_cookie = true;
     }
   }
+
+  if (cookie_it_to_possibly_delete != cookies_.end()) {
+    CanonicalCookie* cc_to_possibly_delete =
+        cookie_it_to_possibly_delete->second.get();
+    // If a secure cookie was encountered (and left alone), don't actually
+    // modify any of the pre-existing cookies. Only delete if no secure cookies
+    // were skipped.
+    if (!skipped_secure_cookie) {
+      histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_FOUND);
+      if (cc_to_possibly_delete->Value() == ecc.Value()) {
+        *creation_date_to_inherit = cc_to_possibly_delete->CreationDate();
+        histogram_cookie_delete_equivalent_->Add(
+            COOKIE_DELETE_EQUIVALENT_FOUND_WITH_SAME_VALUE);
+      }
+      InternalDeleteCookie(cookie_it_to_possibly_delete, true,
+                           already_expired ? DELETE_COOKIE_EXPIRED_OVERWRITE
+                                           : DELETE_COOKIE_OVERWRITE);
+    } else {
+      // If any secure cookie was skipped, preserve the pre-existing cookie.
+      DCHECK(cc_skipped_secure);
+      net_log_.AddEvent(
+          NetLogEventType::COOKIE_STORE_COOKIE_PRESERVED_SKIPPED_SECURE,
+          base::BindRepeating(&NetLogCookieMonsterCookiePreservedSkippedSecure,
+                              cc_skipped_secure, cc_to_possibly_delete, &ecc));
+    }
+  }
+
   return skipped_httponly || skipped_secure_cookie;
 }
 
diff --git a/net/cookies/cookie_monster_netlog_params.cc b/net/cookies/cookie_monster_netlog_params.cc
index e4f358c2..b4b17d28 100644
--- a/net/cookies/cookie_monster_netlog_params.cc
+++ b/net/cookies/cookie_monster_netlog_params.cc
@@ -97,4 +97,23 @@
   return dict;
 }
 
+std::unique_ptr<base::Value> NetLogCookieMonsterCookiePreservedSkippedSecure(
+    const CanonicalCookie* skipped_secure,
+    const CanonicalCookie* preserved,
+    const CanonicalCookie* new_cookie,
+    NetLogCaptureMode capture_mode) {
+  if (!capture_mode.include_cookies_and_credentials())
+    return nullptr;
+  std::unique_ptr<base::Value> dict =
+      std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
+  dict->SetKey("name", base::Value(preserved->Name()));
+  dict->SetKey("domain", base::Value(preserved->Domain()));
+  dict->SetKey("path", base::Value(preserved->Path()));
+  dict->SetKey("securecookiedomain", base::Value(skipped_secure->Domain()));
+  dict->SetKey("securecookiepath", base::Value(skipped_secure->Path()));
+  dict->SetKey("preservedvalue", base::Value(preserved->Value()));
+  dict->SetKey("discardedvalue", base::Value(new_cookie->Value()));
+  return dict;
+}
+
 }  // namespace net
diff --git a/net/cookies/cookie_monster_netlog_params.h b/net/cookies/cookie_monster_netlog_params.h
index fa8b0571..8a5dc1f 100644
--- a/net/cookies/cookie_monster_netlog_params.h
+++ b/net/cookies/cookie_monster_netlog_params.h
@@ -50,6 +50,16 @@
     const CanonicalCookie* new_cookie,
     NetLogCaptureMode capture_mode);
 
+// Returns a Value containing NetLog parameters for when, upon an attempted
+// cookie addition which is rejected due to a conflict with a secure cookie, a
+// pre-existing cookie would have been deleted but is instead preserved because
+// the addition failed.
+std::unique_ptr<base::Value> NetLogCookieMonsterCookiePreservedSkippedSecure(
+    const CanonicalCookie* skipped_secure,
+    const CanonicalCookie* preserved,
+    const CanonicalCookie* new_cookie,
+    NetLogCaptureMode capture_mode);
+
 }  // namespace net
 
 #endif  // NET_COOKIES_COOKIE_MONSTER_NETLOG_PARAMS_H_
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index ecedc22..57c19d8 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -2889,6 +2889,8 @@
   GURL http_url("http://www.foo.com");
   GURL http_superdomain_url("http://foo.com");
   GURL https_url("https://www.foo.com");
+  GURL https_foo_url("https://www.foo.com/foo");
+  GURL http_foo_url("http://www.foo.com/foo");
 
   // A non-secure cookie can be created from either a URL with a secure or
   // insecure scheme.
@@ -2932,6 +2934,36 @@
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/my/path"));
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "WITH_PATH=C; path=/my/path/sub"));
 
+  DeleteAll(cm.get());
+
+  // If a secure cookie is set on top of an existing insecure cookie but with a
+  // different path, both are retained.
+  EXPECT_TRUE(SetCookie(cm.get(), http_url, "A=B; path=/foo"));
+  EXPECT_TRUE(SetCookie(cm.get(), https_url, "A=C; Secure; path=/"));
+
+  // Querying from an insecure url gets only the insecure cookie, but querying
+  // from a secure url returns both.
+  EXPECT_EQ("A=B", GetCookies(cm.get(), http_foo_url));
+  EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=B"));
+  EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=C"));
+
+  // Attempting to set an insecure cookie (from an insecure scheme) that domain-
+  // matches and path-matches the secure cookie fails i.e. the secure cookie is
+  // left alone...
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/foo"));
+  EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/"));
+  EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=C"));
+
+  // ...but the original insecure cookie is still retained.
+  EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=B"));
+  EXPECT_THAT(GetCookies(cm.get(), https_foo_url),
+              testing::Not(testing::HasSubstr("A=D")));
+
+  // Deleting the secure cookie leaves only the original insecure cookie.
+  EXPECT_TRUE(SetCookie(cm.get(), https_url,
+                        "A=C; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
+  EXPECT_EQ("A=B", GetCookies(cm.get(), https_foo_url));
+
   // If a non-secure cookie is created from a URL with an insecure scheme, and
   // a secure cookie with the same name already exists, if the domain strings
   // domain-match, do not update the cookie.
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn
index 8ea242f8..0c2c199 100644
--- a/net/dns/BUILD.gn
+++ b/net/dns/BUILD.gn
@@ -31,7 +31,9 @@
     sources += [
       "address_sorter.h",
       "address_sorter_win.cc",
+      "dns_config.cc",
       "dns_config_service.cc",
+      "dns_config_service.h",
       "dns_config_service_win.cc",
       "dns_config_service_win.h",
       "dns_config_watcher_mac.cc",
@@ -197,7 +199,7 @@
 
   if (!is_nacl) {
     sources += [
-      "dns_config_service.h",
+      "dns_config.h",
       "host_cache.h",
       "host_resolver.h",
       "mapped_host_resolver.h",
diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc
index 6158b0a..c230b32 100644
--- a/net/dns/dns_client.cc
+++ b/net/dns/dns_client.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/rand_util.h"
 #include "net/dns/address_sorter.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_session.h"
 #include "net/dns/dns_socket_pool.h"
 #include "net/dns/dns_transaction.h"
diff --git a/net/dns/dns_config.cc b/net/dns/dns_config.cc
new file mode 100644
index 0000000..dfcdf89
--- /dev/null
+++ b/net/dns/dns_config.cc
@@ -0,0 +1,94 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/dns/dns_config.h"
+
+#include <utility>
+
+#include "base/values.h"
+
+namespace net {
+
+// Default values are taken from glibc resolv.h except timeout which is set to
+// |kDnsDefaultTimeoutMs|.
+DnsConfig::DnsConfig()
+    : unhandled_options(false),
+      append_to_multi_label_name(true),
+      randomize_ports(false),
+      ndots(1),
+      timeout(kDnsDefaultTimeout),
+      attempts(2),
+      rotate(false),
+      use_local_ipv6(false) {}
+
+DnsConfig::DnsConfig(const DnsConfig& other) = default;
+
+DnsConfig::~DnsConfig() = default;
+
+bool DnsConfig::Equals(const DnsConfig& d) const {
+  return EqualsIgnoreHosts(d) && (hosts == d.hosts);
+}
+
+bool DnsConfig::EqualsIgnoreHosts(const DnsConfig& d) const {
+  return (nameservers == d.nameservers) && (search == d.search) &&
+         (unhandled_options == d.unhandled_options) &&
+         (append_to_multi_label_name == d.append_to_multi_label_name) &&
+         (ndots == d.ndots) && (timeout == d.timeout) &&
+         (attempts == d.attempts) && (rotate == d.rotate) &&
+         (use_local_ipv6 == d.use_local_ipv6);
+}
+
+void DnsConfig::CopyIgnoreHosts(const DnsConfig& d) {
+  nameservers = d.nameservers;
+  search = d.search;
+  unhandled_options = d.unhandled_options;
+  append_to_multi_label_name = d.append_to_multi_label_name;
+  ndots = d.ndots;
+  timeout = d.timeout;
+  attempts = d.attempts;
+  rotate = d.rotate;
+  use_local_ipv6 = d.use_local_ipv6;
+}
+
+std::unique_ptr<base::Value> DnsConfig::ToValue() const {
+  auto dict = std::make_unique<base::DictionaryValue>();
+
+  auto list = std::make_unique<base::ListValue>();
+  for (size_t i = 0; i < nameservers.size(); ++i)
+    list->AppendString(nameservers[i].ToString());
+  dict->Set("nameservers", std::move(list));
+
+  list = std::make_unique<base::ListValue>();
+  for (size_t i = 0; i < search.size(); ++i)
+    list->AppendString(search[i]);
+  dict->Set("search", std::move(list));
+
+  dict->SetBoolean("unhandled_options", unhandled_options);
+  dict->SetBoolean("append_to_multi_label_name", append_to_multi_label_name);
+  dict->SetInteger("ndots", ndots);
+  dict->SetDouble("timeout", timeout.InSecondsF());
+  dict->SetInteger("attempts", attempts);
+  dict->SetBoolean("rotate", rotate);
+  dict->SetBoolean("use_local_ipv6", use_local_ipv6);
+  dict->SetInteger("num_hosts", hosts.size());
+  list = std::make_unique<base::ListValue>();
+  for (auto& server : dns_over_https_servers) {
+    base::Value val(base::Value::Type::DICTIONARY);
+    base::DictionaryValue* dict;
+    val.GetAsDictionary(&dict);
+    dict->SetString("server_template", server.server_template);
+    dict->SetBoolean("use_post", server.use_post);
+    list->GetList().push_back(std::move(val));
+  }
+  dict->Set("doh_servers", std::move(list));
+
+  return std::move(dict);
+}
+
+DnsConfig::DnsOverHttpsServerConfig::DnsOverHttpsServerConfig(
+    const std::string& server_template,
+    bool use_post)
+    : server_template(server_template), use_post(use_post) {}
+
+}  // namespace net
diff --git a/net/dns/dns_config.h b/net/dns/dns_config.h
new file mode 100644
index 0000000..c080356
--- /dev/null
+++ b/net/dns/dns_config.h
@@ -0,0 +1,94 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DNS_DNS_CONFIG_H_
+#define NET_DNS_DNS_CONFIG_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/time/time.h"
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_export.h"
+#include "net/dns/dns_hosts.h"
+
+namespace base {
+class Value;
+}
+
+namespace net {
+
+// Default to 1 second timeout (before exponential backoff).
+constexpr base::TimeDelta kDnsDefaultTimeout = base::TimeDelta::FromSeconds(1);
+
+// DnsConfig stores configuration of the system resolver.
+struct NET_EXPORT DnsConfig {
+  DnsConfig();
+  DnsConfig(const DnsConfig& other);
+  ~DnsConfig();
+
+  bool Equals(const DnsConfig& d) const;
+
+  bool EqualsIgnoreHosts(const DnsConfig& d) const;
+
+  void CopyIgnoreHosts(const DnsConfig& src);
+
+  // Returns a Value representation of |this|. For performance reasons, the
+  // Value only contains the number of hosts rather than the full list.
+  std::unique_ptr<base::Value> ToValue() const;
+
+  bool IsValid() const { return !nameservers.empty(); }
+
+  struct NET_EXPORT DnsOverHttpsServerConfig {
+    DnsOverHttpsServerConfig(const std::string& server_template, bool use_post);
+
+    std::string server_template;
+    bool use_post;
+  };
+
+  // List of name server addresses.
+  std::vector<IPEndPoint> nameservers;
+  // Suffix search list; used on first lookup when number of dots in given name
+  // is less than |ndots|.
+  std::vector<std::string> search;
+
+  DnsHosts hosts;
+
+  // True if there are options set in the system configuration that are not yet
+  // supported by DnsClient.
+  bool unhandled_options;
+
+  // AppendToMultiLabelName: is suffix search performed for multi-label names?
+  // True, except on Windows where it can be configured.
+  bool append_to_multi_label_name;
+
+  // Indicates that source port randomization is required. This uses additional
+  // resources on some platforms.
+  bool randomize_ports;
+
+  // Resolver options; see man resolv.conf.
+
+  // Minimum number of dots before global resolution precedes |search|.
+  int ndots;
+  // Time between retransmissions, see res_state.retrans.
+  base::TimeDelta timeout;
+  // Maximum number of attempts, see res_state.retry.
+  int attempts;
+  // Round robin entries in |nameservers| for subsequent requests.
+  bool rotate;
+
+  // Indicates system configuration uses local IPv6 connectivity, e.g.,
+  // DirectAccess. This is exposed for HostResolver to skip IPv6 probes,
+  // as it may cause them to return incorrect results.
+  bool use_local_ipv6;
+
+  // List of servers to query over HTTPS, queried in order
+  // (https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-12.txt).
+  std::vector<DnsOverHttpsServerConfig> dns_over_https_servers;
+};
+
+}  // namespace net
+
+#endif  // NET_DNS_DNS_CONFIG_H_
diff --git a/net/dns/dns_config_service.cc b/net/dns/dns_config_service.cc
index 6a291e99..96731cde 100644
--- a/net/dns/dns_config_service.cc
+++ b/net/dns/dns_config_service.cc
@@ -4,100 +4,13 @@
 
 #include "net/dns/dns_config_service.h"
 
-#include <utility>
+#include <string>
 
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/values.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/ip_pattern.h"
 
 namespace net {
 
-// Default values are taken from glibc resolv.h except timeout which is set to
-// |kDnsDefaultTimeoutMs|.
-DnsConfig::DnsConfig()
-    : unhandled_options(false),
-      append_to_multi_label_name(true),
-      randomize_ports(false),
-      ndots(1),
-      timeout(base::TimeDelta::FromMilliseconds(kDnsDefaultTimeoutMs)),
-      attempts(2),
-      rotate(false),
-      use_local_ipv6(false) {}
-
-DnsConfig::DnsConfig(const DnsConfig& other) = default;
-
-DnsConfig::~DnsConfig() = default;
-
-bool DnsConfig::Equals(const DnsConfig& d) const {
-  return EqualsIgnoreHosts(d) && (hosts == d.hosts);
-}
-
-bool DnsConfig::EqualsIgnoreHosts(const DnsConfig& d) const {
-  return (nameservers == d.nameservers) &&
-         (search == d.search) &&
-         (unhandled_options == d.unhandled_options) &&
-         (append_to_multi_label_name == d.append_to_multi_label_name) &&
-         (ndots == d.ndots) &&
-         (timeout == d.timeout) &&
-         (attempts == d.attempts) &&
-         (rotate == d.rotate) &&
-         (use_local_ipv6 == d.use_local_ipv6);
-}
-
-void DnsConfig::CopyIgnoreHosts(const DnsConfig& d) {
-  nameservers = d.nameservers;
-  search = d.search;
-  unhandled_options = d.unhandled_options;
-  append_to_multi_label_name = d.append_to_multi_label_name;
-  ndots = d.ndots;
-  timeout = d.timeout;
-  attempts = d.attempts;
-  rotate = d.rotate;
-  use_local_ipv6 = d.use_local_ipv6;
-}
-
-std::unique_ptr<base::Value> DnsConfig::ToValue() const {
-  auto dict = std::make_unique<base::DictionaryValue>();
-
-  auto list = std::make_unique<base::ListValue>();
-  for (size_t i = 0; i < nameservers.size(); ++i)
-    list->AppendString(nameservers[i].ToString());
-  dict->Set("nameservers", std::move(list));
-
-  list = std::make_unique<base::ListValue>();
-  for (size_t i = 0; i < search.size(); ++i)
-    list->AppendString(search[i]);
-  dict->Set("search", std::move(list));
-
-  dict->SetBoolean("unhandled_options", unhandled_options);
-  dict->SetBoolean("append_to_multi_label_name", append_to_multi_label_name);
-  dict->SetInteger("ndots", ndots);
-  dict->SetDouble("timeout", timeout.InSecondsF());
-  dict->SetInteger("attempts", attempts);
-  dict->SetBoolean("rotate", rotate);
-  dict->SetBoolean("use_local_ipv6", use_local_ipv6);
-  dict->SetInteger("num_hosts", hosts.size());
-  list = std::make_unique<base::ListValue>();
-  for (auto& server : dns_over_https_servers) {
-    base::Value val(base::Value::Type::DICTIONARY);
-    base::DictionaryValue* dict;
-    val.GetAsDictionary(&dict);
-    dict->SetString("server_template", server.server_template);
-    dict->SetBoolean("use_post", server.use_post);
-    list->GetList().push_back(std::move(val));
-  }
-  dict->Set("doh_servers", std::move(list));
-
-  return std::move(dict);
-}
-
-DnsConfig::DnsOverHttpsServerConfig::DnsOverHttpsServerConfig(
-    const std::string& server_template,
-    bool use_post)
-    : server_template(server_template), use_post(use_post) {}
-
 DnsConfigService::DnsConfigService()
     : watch_failed_(false),
       have_config_(false),
diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h
index 9b1cb0b..8846314 100644
--- a/net/dns/dns_config_service.h
+++ b/net/dns/dns_config_service.h
@@ -7,98 +7,18 @@
 
 #include <map>
 #include <memory>
-#include <string>
-#include <vector>
 
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-// Needed on shared build with MSVS2010 to avoid multiple definitions of
-// std::vector<IPEndPoint>.
-#include "net/base/address_list.h"
-#include "net/base/ip_endpoint.h"  // win requires size of IPEndPoint
 #include "net/base/net_export.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_hosts.h"
 #include "url/gurl.h"
 
-namespace base {
-class Value;
-}
-
 namespace net {
 
-// Default to 1 second timeout (before exponential backoff).
-const int64_t kDnsDefaultTimeoutMs = 1000;
-
-// DnsConfig stores configuration of the system resolver.
-struct NET_EXPORT DnsConfig {
-  DnsConfig();
-  DnsConfig(const DnsConfig& other);
-  ~DnsConfig();
-
-  bool Equals(const DnsConfig& d) const;
-
-  bool EqualsIgnoreHosts(const DnsConfig& d) const;
-
-  void CopyIgnoreHosts(const DnsConfig& src);
-
-  // Returns a Value representation of |this|. For performance reasons, the
-  // Value only contains the number of hosts rather than the full list.
-  std::unique_ptr<base::Value> ToValue() const;
-
-  bool IsValid() const {
-    return !nameservers.empty();
-  }
-
-  struct NET_EXPORT DnsOverHttpsServerConfig {
-    DnsOverHttpsServerConfig(const std::string& server_template, bool use_post);
-
-    std::string server_template;
-    bool use_post;
-  };
-
-  // List of name server addresses.
-  std::vector<IPEndPoint> nameservers;
-  // Suffix search list; used on first lookup when number of dots in given name
-  // is less than |ndots|.
-  std::vector<std::string> search;
-
-  DnsHosts hosts;
-
-  // True if there are options set in the system configuration that are not yet
-  // supported by DnsClient.
-  bool unhandled_options;
-
-  // AppendToMultiLabelName: is suffix search performed for multi-label names?
-  // True, except on Windows where it can be configured.
-  bool append_to_multi_label_name;
-
-  // Indicates that source port randomization is required. This uses additional
-  // resources on some platforms.
-  bool randomize_ports;
-
-  // Resolver options; see man resolv.conf.
-
-  // Minimum number of dots before global resolution precedes |search|.
-  int ndots;
-  // Time between retransmissions, see res_state.retrans.
-  base::TimeDelta timeout;
-  // Maximum number of attempts, see res_state.retry.
-  int attempts;
-  // Round robin entries in |nameservers| for subsequent requests.
-  bool rotate;
-
-  // Indicates system configuration uses local IPv6 connectivity, e.g.,
-  // DirectAccess. This is exposed for HostResolver to skip IPv6 probes,
-  // as it may cause them to return incorrect results.
-  bool use_local_ipv6;
-
-  // List of servers to query over HTTPS, queried in order
-  // (https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-12.txt).
-  std::vector<DnsOverHttpsServerConfig> dns_over_https_servers;
-};
-
 // Service for reading system DNS settings, on demand or when signalled by
 // internal watchers and NetworkChangeNotifier.
 class NET_EXPORT_PRIVATE DnsConfigService {
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc
index 06e9d7969..1b947c5b 100644
--- a/net/dns/dns_config_service_posix.cc
+++ b/net/dns/dns_config_service_posix.cc
@@ -22,6 +22,7 @@
 #include "build/build_config.h"
 #include "net/base/ip_address.h"
 #include "net/base/ip_endpoint.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_hosts.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/notify_watcher_mac.h"
@@ -186,7 +187,7 @@
   }
 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
   // Override timeout value to match default setting on Windows.
-  dns_config->timeout = base::TimeDelta::FromMilliseconds(kDnsDefaultTimeoutMs);
+  dns_config->timeout = kDnsDefaultTimeout;
   return result;
 #else  // defined(OS_ANDROID)
   dns_config->nameservers.clear();
diff --git a/net/dns/dns_config_service_posix.h b/net/dns/dns_config_service_posix.h
index d27c65c..81888cf 100644
--- a/net/dns/dns_config_service_posix.h
+++ b/net/dns/dns_config_service_posix.h
@@ -19,6 +19,7 @@
 #include "net/dns/dns_config_service.h"
 
 namespace net {
+struct DnsConfig;
 
 // Use DnsConfigService::CreateSystemService to use it outside of tests.
 namespace internal {
diff --git a/net/dns/dns_config_service_posix_unittest.cc b/net/dns/dns_config_service_posix_unittest.cc
index 241663f..82af9052 100644
--- a/net/dns/dns_config_service_posix_unittest.cc
+++ b/net/dns/dns_config_service_posix_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "net/base/ip_address.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_config_service_posix.h"
 #include "net/dns/dns_protocol.h"
 
diff --git a/net/dns/dns_config_service_win_unittest.cc b/net/dns/dns_config_service_win_unittest.cc
index 091c090a..da062f1 100644
--- a/net/dns/dns_config_service_win_unittest.cc
+++ b/net/dns/dns_config_service_win_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/memory/free_deleter.h"
 #include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
 #include "net/dns/dns_protocol.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc
index 85c7b09f..0e8eab84 100644
--- a/net/dns/dns_session.cc
+++ b/net/dns/dns_session.cc
@@ -20,7 +20,6 @@
 #include "base/time/time.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
-#include "net/dns/dns_config_service.h"
 #include "net/dns/dns_socket_pool.h"
 #include "net/dns/dns_util.h"
 #include "net/log/net_log_event_type.h"
diff --git a/net/dns/dns_session.h b/net/dns/dns_session.h
index 803a64d..6212ff47 100644
--- a/net/dns/dns_session.h
+++ b/net/dns/dns_session.h
@@ -18,7 +18,7 @@
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
 #include "net/base/rand_callback.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_socket_pool.h"
 
 namespace base {
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h
index ffdceb9..5ebcdeb 100644
--- a/net/dns/dns_test_util.h
+++ b/net/dns/dns_test_util.h
@@ -13,7 +13,7 @@
 #include <vector>
 
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 
 namespace net {
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index 228a35b..30d679c 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -40,6 +40,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/upload_bytes_element_reader.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_query.h"
 #include "net/dns/dns_response.h"
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 910e0160..779ae166 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -27,6 +27,7 @@
 #include "net/base/port_util.h"
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/base/url_util.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_query.h"
 #include "net/dns/dns_response.h"
diff --git a/net/dns/fuzzed_host_resolver.cc b/net/dns/fuzzed_host_resolver.cc
index d93c89f..8290c82a 100644
--- a/net/dns/fuzzed_host_resolver.cc
+++ b/net/dns/fuzzed_host_resolver.cc
@@ -21,7 +21,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_hosts.h"
 
 namespace net {
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc
index 77e55f3..aad5c6a 100644
--- a/net/dns/host_resolver.cc
+++ b/net/dns/host_resolver.cc
@@ -11,7 +11,6 @@
 #include "base/values.h"
 #include "net/base/net_errors.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
 #include "net/dns/host_cache.h"
 #include "net/dns/host_resolver_impl.h"
 
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index 0f9a85b..ebe4ba0 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -18,7 +18,7 @@
 #include "net/base/host_port_pair.h"
 #include "net/base/prioritized_dispatcher.h"
 #include "net/base/request_priority.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/host_cache.h"
 #include "net/dns/host_resolver_source.h"
 
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 1a9366be..3d29b9d2 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -59,7 +59,6 @@
 #include "net/base/url_util.h"
 #include "net/dns/address_sorter.h"
 #include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_reloader.h"
 #include "net/dns/dns_response.h"
diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h
index 955241e..5027c35 100644
--- a/net/dns/host_resolver_impl.h
+++ b/net/dns/host_resolver_impl.h
@@ -19,7 +19,7 @@
 #include "base/timer/timer.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/network_change_notifier.h"
-#include "net/dns/dns_config_service.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/host_cache.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/host_resolver_proc.h"
diff --git a/net/dns/mapped_host_resolver.h b/net/dns/mapped_host_resolver.h
index 850a2af6..8f40f74 100644
--- a/net/dns/mapped_host_resolver.h
+++ b/net/dns/mapped_host_resolver.h
@@ -12,6 +12,7 @@
 #include "net/base/completion_once_callback.h"
 #include "net/base/host_mapping_rules.h"
 #include "net/base/net_export.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/host_resolver.h"
 
 namespace net {
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index 437ec84..7699719b 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -3145,6 +3145,20 @@
 //  }
 EVENT_TYPE(COOKIE_STORE_COOKIE_REJECTED_HTTPONLY)
 
+// Event emitted on preservation of a cookie that would have been
+// overwritten, because cookie addition failed due to a conflict with a secure
+// cookie.
+//  {
+//    "name": <Name of the cookies>
+//    "domain": <Domain of the preserved and new cookies>
+//    "path": <Path of the preserved and new cookies>
+//    "securecookiedomain": <Domain of the secure cookie causing preservation>
+//    "securecookiepath": <Path of the secure cookie causing preservation>
+//    "preservedvalue": <Value of the preserved cookie>
+//    "discardedvalue": <Value of the new cookie whose addition failed>
+//  }
+EVENT_TYPE(COOKIE_STORE_COOKIE_PRESERVED_SKIPPED_SECURE)
+
 // Event emitted on setting store session persistence
 //  {
 //    "persistence" : <Session persistence setting for the store>
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc
index 2047f0e..70754b4f 100644
--- a/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "net/dns/dns_client.h"
+#include "net/dns/dns_config.h"
 #include "net/dns/dns_transaction.h"
 #include "net/dns/host_resolver_impl.h"
 #include "net/http/http_stream_factory_test_util.h"
diff --git a/printing/printing_context_android.cc b/printing/printing_context_android.cc
index 3c92d72..167ae20b 100644
--- a/printing/printing_context_android.cc
+++ b/printing/printing_context_android.cc
@@ -22,6 +22,7 @@
 #include "third_party/icu/source/i18n/unicode/ulocdata.h"
 
 using base::android::JavaParamRef;
+using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
 
 namespace printing {
@@ -41,9 +42,11 @@
                                     false);
 }
 
-void GetPageRanges(JNIEnv* env, jintArray int_arr, PageRanges* range_vector) {
+void GetPageRanges(JNIEnv* env,
+                   const JavaRef<jintArray>& int_arr,
+                   PageRanges* range_vector) {
   std::vector<int> pages;
-  base::android::JavaIntArrayToIntVector(env, int_arr, &pages);
+  base::android::JavaIntArrayToIntVector(env, int_arr.obj(), &pages);
   for (int page : pages) {
     PageRange range;
     range.from = page;
@@ -115,9 +118,9 @@
 
   ScopedJavaLocalRef<jintArray> intArr =
       Java_PrintingContext_getPages(env, j_printing_context_);
-  if (intArr.obj()) {
+  if (!intArr.is_null()) {
     PageRanges range_vector;
-    GetPageRanges(env, intArr.obj(), &range_vector);
+    GetPageRanges(env, intArr, &range_vector);
     settings_.set_ranges(range_vector);
   }
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 0dc358d..183a5b17 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -155,11 +155,6 @@
 #define SK_SUPPORT_LEGACY_TILED_BITMAPS
 #endif
 
-// remove after rebaselining svg layout tests
-#ifndef SK_SUPPORT_LEGACY_SVG_ARC_TO
-#define SK_SUPPORT_LEGACY_SVG_ARC_TO
-#endif
-
 // Max. verb count for paths rendered by the edge-AA tessellating path renderer.
 #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 100
 
@@ -171,8 +166,6 @@
 #define SK_SUPPORT_LEGACY_AAA_CHOICE
 #endif
 
-#define SK_LEGACY_COLORSPACE_XFORM_STEPS_IMPL
-
 #define SK_LEGACY_MAKE_COLOR_SPACE_IMPL
 
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index fd6fb9f..ff77ea3 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3099,6 +3099,21 @@
           "hard_timeout": 3600,
           "io_timeout": 3600
         },
+        "test": "chrome_all_tast_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-14.04",
+              "pool": "Chrome-CrOS-VM"
+            }
+          ],
+          "hard_timeout": 3600,
+          "io_timeout": 3600
+        },
         "test": "chrome_login_tast_tests"
       },
       {
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
index e76edb77..e3c8d8f 100644
--- a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
+++ b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
@@ -232,6 +232,10 @@
 # Flaky tests. crbug.com/880584
 -UnifiedAutoplaySettingBrowserTest.*
 
+# This seems to timeout only on the msan bot, but I suspect it could equally
+# occur on the non-msan bots. https://crbug.com/891383
+-UserAddingScreenTest.AddingSeveralUsers
+
 # Window Open API tests.  https://crbug.com/815379
 -WindowOpenApiTest.OpenLockedFullscreenWindow
 -WindowOpenApiTest.RemoveLockedFullscreenFromWindow
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index fa59232..ebd73ec 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -279,6 +279,10 @@
     "label": "//chrome:chrome",
     "type": "additional_compile_target",
   },
+  "chrome_all_tast_tests": {
+    "label": "//chromeos:chrome_all_tast_tests",
+    "type": "raw",
+  },
   "chrome_app_unittests": {
     "label": "//chrome/test:chrome_app_unittests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 3452e14c..a2ccb8a 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -430,6 +430,7 @@
 
     'chromeos_gtests_experimental': {
       'base_unittests': {},
+      'chrome_all_tast_tests': {},
       'chrome_login_tast_tests': {},
       'chromeos_unittests': {
         'args': [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index fd7af3b..6cecea8d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1047,25 +1047,6 @@
             ]
         }
     ],
-    "BundledConnectionHelp": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "HTTPHelpCenterEnabled",
-                    "enable_features": [
-                        "BundledConnectionHelp"
-                    ]
-                }
-            ]
-        }
-    ],
     "CCTModule": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f0a93dc..607089e 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2776,11 +2776,6 @@
 crbug.com/800898 external/wpt/FileAPI/url/url-in-tags-revoke.window.html [ Timeout ]
 crbug.com/800898 external/wpt/workers/worker-from-blob-url.window.html [ Timeout ]
 
-crbug.com/854474 external/wpt/console/console-label-conversion.any.html [ Skip ]
-crbug.com/854474 external/wpt/console/console-label-conversion.any.worker.html [ Skip ]
-crbug.com/854474 external/wpt/console/idlharness.any.html [ Skip ]
-crbug.com/854474 external/wpt/console/idlharness.any.worker.html [ Skip ]
-
 crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass Timeout ]
 crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.html [ Pass Timeout ]
 crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/animations/responsive/viewport-unit-transform-responsive.html b/third_party/WebKit/LayoutTests/animations/responsive/viewport-unit-transform-responsive.html
index 04fc896..d24693f 100644
--- a/third_party/WebKit/LayoutTests/animations/responsive/viewport-unit-transform-responsive.html
+++ b/third_party/WebKit/LayoutTests/animations/responsive/viewport-unit-transform-responsive.html
@@ -9,7 +9,9 @@
 </style>
 This box should be located in the center of the page.
 <div id="target"></div>
+<script src="../../resources/compositor-controls.js"></script>
 <script>
+setAnimationRequiresRaster();
 if (window.testRunner) {
   testRunner.useUnfortunateSynchronousResizeMode();
   testRunner.waitUntilDone();
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
index b6c5e90..83c7783 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -56293,9 +56293,9 @@
      {}
     ]
    ],
-   "css/css-shapes/shape-outside/values/shape-outside-inset-010.html": [
+   "css/css-shapes/shape-outside/values/shape-outside-inset-0010.html": [
     [
-     "/css/css-shapes/shape-outside/values/shape-outside-inset-010.html",
+     "/css/css-shapes/shape-outside/values/shape-outside-inset-0010.html",
      [
       [
        "/css/reference/ref-filled-green-100px-square-only.html",
@@ -109277,11 +109277,26 @@
      {}
     ]
    ],
+   "beacon/beacon-cors.sub.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "beacon/beacon-navigate-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "beacon/beacon-readablestream.window-expected.txt": [
     [
      {}
     ]
    ],
+   "beacon/beacon-redirect.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "beacon/headers/header-content-type-expected.txt": [
     [
      {}
@@ -109292,11 +109307,6 @@
      {}
     ]
    ],
-   "beacon/navigate.iFrame.sub.html": [
-    [
-     {}
-    ]
-   ],
    "beacon/resources/beacon.py": [
     [
      {}
@@ -158987,11 +158997,6 @@
      {}
     ]
    ],
-   "html/rendering/non-replaced-elements/flow-content-0/form-margin-quirk-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/rendering/non-replaced-elements/flow-content-0/support/dialog-framed.html": [
     [
      {}
@@ -282238,7 +282243,7 @@
    "testharness"
   ],
   "2dcontext/drawing-images-to-the-canvas/drawimage_svg_image_1.html": [
-   "385f1a5568eebe953663232ee745462f20bfda94",
+   "6208b8dc05629208ee3d68b233e1b6c107d1d12b",
    "testharness"
   ],
   "2dcontext/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm": [
@@ -289178,17 +289183,25 @@
    "testharness"
   ],
   "beacon/beacon-common.sub.js": [
-   "0a36283b26379e16ccfd2c33cf05e0395dc18331",
+   "ae2f169f272e9efbbea3b7464ea77c34fe65c6e1",
+   "support"
+  ],
+  "beacon/beacon-cors.sub.window-expected.txt": [
+   "7d9f711e6f208f710f2756fb043afa62c6b4368a",
    "support"
   ],
   "beacon/beacon-cors.sub.window.js": [
-   "f4bccf177e3b4585a5efe0b6cd0d6edc24fe48f9",
+   "411cd1c94924127ce95c27707d283e7ca342f367",
    "testharness"
   ],
   "beacon/beacon-error.window.js": [
    "b53353abc1ea29679216488ef17c9c9a010a434d",
    "testharness"
   ],
+  "beacon/beacon-navigate-expected.txt": [
+   "36c8b1023a0b7a6ce2f2e9589002ff3412330721",
+   "support"
+  ],
   "beacon/beacon-navigate.html": [
    "5df13905978dad65dea1f42606317897061d4aa4",
    "testharness"
@@ -289201,8 +289214,12 @@
    "fc7f81f884bdf47b6eb76f6d9b237bc38556efa4",
    "testharness"
   ],
+  "beacon/beacon-redirect.window-expected.txt": [
+   "e38d0c22b1fe901679f6b4dadd8bcd47d1bfe1da",
+   "support"
+  ],
   "beacon/beacon-redirect.window.js": [
-   "659759baa3f5c58b26b9ed042047348b67a23e44",
+   "53f229abff1744b5766efe808c00f9b656296391",
    "testharness"
   ],
   "beacon/headers/header-content-type-expected.txt": [
@@ -289253,10 +289270,6 @@
    "958daf4865d1d7c9dfb621a163e15a8862330d2b",
    "testharness"
   ],
-  "beacon/navigate.iFrame.sub.html": [
-   "f4c7846e522b553985cc0ad253e439bd6d315975",
-   "support"
-  ],
   "beacon/resources/beacon.py": [
    "5f2553d3c4d506f7e292cfb73d81930a83a12d76",
    "support"
@@ -335833,6 +335846,10 @@
    "3724971363b1fb563427c9abe7e5177b381a118c",
    "testharness"
   ],
+  "css/css-shapes/shape-outside/values/shape-outside-inset-0010.html": [
+   "b82abea82a603f9a523fd8ee0a4d61cd0b7349c6",
+   "reftest"
+  ],
   "css/css-shapes/shape-outside/values/shape-outside-inset-002.html": [
    "559738f71d8c19d0ab752be891c585a2b8a1479d",
    "testharness"
@@ -335873,10 +335890,6 @@
    "c131783d1ea3eb2992c30e54ca0d9b2c2943e188",
    "testharness"
   ],
-  "css/css-shapes/shape-outside/values/shape-outside-inset-010.html": [
-   "b82abea82a603f9a523fd8ee0a4d61cd0b7349c6",
-   "reftest"
-  ],
   "css/css-shapes/shape-outside/values/shape-outside-polygon-000.html": [
    "9ca058194a83149bc911727e8ac795cf261c7617",
    "testharness"
@@ -384101,10 +384114,6 @@
    "943f38c3e03e0c654d1105c2f42d49cca3f1432a",
    "reftest"
   ],
-  "html/rendering/non-replaced-elements/flow-content-0/form-margin-quirk-expected.txt": [
-   "e2ee2f7dabccad74c9c77cf656f1056792a309d9",
-   "support"
-  ],
   "html/rendering/non-replaced-elements/flow-content-0/form-margin-quirk.html": [
    "7f6618bb782a0460d286930f05866ea9b432a1cd",
    "testharness"
@@ -395778,7 +395787,7 @@
    "support"
   ],
   "interfaces/payment-request.idl": [
-   "843c66107b34bbb90aa64411487a09b2fa95e508",
+   "d930b57291e5301e4056d30192726023e9306512",
    "support"
   ],
   "interfaces/performance-timeline.idl": [
@@ -395870,7 +395879,7 @@
    "support"
   ],
   "interfaces/speech-api.idl": [
-   "1258b7f835c8b05f6f91908c1cb442127a53aaaf",
+   "f94637a8d21eb8a5940ce5ddfb6f6ca1af52f289",
    "support"
   ],
   "interfaces/storage.idl": [
@@ -417814,7 +417823,7 @@
    "support"
   ],
   "resources/idlharness.js": [
-   "00c59eda8adfeb8a1b5b8ab1ef60186517161ea4",
+   "950df6fa34b82a3f4afe2ab925d90a72ddcf3872",
    "support"
   ],
   "resources/idlharness.js.headers": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_svg_image_1.html b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_svg_image_1.html
index 385f1a5..6208b8d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_svg_image_1.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_svg_image_1.html
@@ -1,46 +1,31 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load a 100x100 image to a SVG image and draw it to a 100x100 canvas.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<div id="log"></div>
 <canvas id="dest" height="100" width="100"></canvas>
-
 <script>
-var sourceWidth = 100;
-var sourceHeight = 100;
-var smoothingEnabled = false;
-var destCanvas = document.getElementById('dest');
-var sourceImg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
-sourceImg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '../2x2.png');
-sourceImg.width = sourceWidth;
-sourceImg.height = sourceHeight;
-var destCtx = destCanvas.getContext('2d');
+async_test(t => {
+  var sourceImg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+  sourceImg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '../2x2.png');
+  sourceImg.width = 100;
+  sourceImg.height = 100;
 
-function checkPixel(x, y, expected, epsilon) {
-    var actual = destCtx.getImageData(x, y, 1, 1).data;
-    assert_true(actual.length === expected.length);
-    for (var i=0; i < actual.length; i++)
-        assert_approx_equals(actual[i], expected[i], epsilon);
-}
-
-var pixelTests = [
-    ['Pixel Top Left Image', 0, 0, [253, 140, 245, 255], 1],
-    ['Pixel Top Right Image', 0, 99, [253, 140, 245, 255], 1],
-    ['Pixel Bottom Left Image', 99, 0, [253, 140, 245, 255], 1],
-    ['Pixel Bottom Right Image', 99, 99, [253, 140, 245, 255], 1],
-];
-
-function runTest() {
+  window.onload = t.step_func_done(() => {
+    var destCanvas = document.getElementById('dest');
+    var destCtx = destCanvas.getContext('2d');
     destCtx.fillStyle = "#FF0000";
     destCtx.fillRect(0, 0,  destCanvas.width, destCanvas.height);
-    destCtx.imageSmoothingEnabled = smoothingEnabled;
+    destCtx.imageSmoothingEnabled = false;
     // 2 arguments, the dest origin is 0,0
     // The source canvas will copied to the 0,0 position of the destination canvas
     destCtx.drawImage(sourceImg, 0, 0);
-    generate_tests(checkPixel, pixelTests);
-}
-
-async_test(t => {
-        window.onload = function() {
-            t.step(runTest);
-            t.done();
-        }
-}, 'Load a 100x100 image to a SVG image and draw it to a 100x100 canvas.');
-</script>
\ No newline at end of file
+    _assertPixel(destCanvas, 0, 0, 253, 140, 245, 255);
+    _assertPixel(destCanvas, 0, 99, 253, 140, 245, 255);
+    _assertPixel(destCanvas, 99, 0, 253, 140, 245, 255);
+    _assertPixel(destCanvas, 99, 99, 253, 140, 245, 255);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-0010.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-010.html
rename to third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-0010.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl
index 843c661..d930b57 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl
@@ -49,7 +49,7 @@
   DOMString error;
   PaymentItem total;
   AddressErrors shippingAddressErrors;
-  PayerErrors payerErrors;
+  PayerErrorFields payerErrors;
   object paymentMethodErrors;
 };
 
@@ -169,13 +169,13 @@
 };
 
 dictionary PaymentValidationErrors {
-  PayerErrors payer;
+  PayerErrorFields payer;
   AddressErrors shippingAddress;
   DOMString error;
   object paymentMethod;
 };
 
-dictionary PayerErrors {
+dictionary PayerErrorFields {
   DOMString email;
   DOMString name;
   DOMString phone;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl
index 1258b7f8..f94637a8d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl
@@ -132,8 +132,7 @@
 };
 
 [Exposed=Window,
-  Constructor,
-  Constructor(DOMString text)]
+  Constructor(optional DOMString text)]
 interface SpeechSynthesisUtterance : EventTarget {
     attribute DOMString text;
     attribute DOMString lang;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index 00c59ed..950df6fa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -57,7 +57,6 @@
 }
 /// Helpers ///
 function constValue (cnt)
-//@{
 {
     if (cnt.type === "null") return null;
     if (cnt.type === "NaN") return NaN;
@@ -66,9 +65,7 @@
     return cnt.value;
 }
 
-//@}
 function minOverloadLength(overloads)
-//@{
 {
     // "The value of the Function object’s “length” property is
     // a Number determined as follows:
@@ -87,9 +84,7 @@
     .reduce(function(m, n) { return Math.min(m, n); });
 }
 
-//@}
 function throwOrReject(a_test, operation, fn, obj, args, message, cb)
-//@{
 {
     if (operation.idlType.generic !== "Promise") {
         assert_throws(new TypeError(), function() {
@@ -108,9 +103,7 @@
     }
 }
 
-//@}
 function awaitNCallbacks(n, cb, ctx)
-//@{
 {
     var counter = 0;
     return function() {
@@ -121,9 +114,7 @@
     };
 }
 
-//@}
 var fround =
-//@{
 (function(){
     if (Math.fround) return Math.fround;
 
@@ -133,12 +124,10 @@
         return arr[0];
     };
 })();
-//@}
 
 /// IdlHarnessError ///
 // Entry point
 self.IdlHarnessError = function(message)
-//@{
 {
     /**
      * Message to be printed as the error's toString invocation.
@@ -148,19 +137,15 @@
 
 IdlHarnessError.prototype = Object.create(Error.prototype);
 
-//@}
 IdlHarnessError.prototype.toString = function()
-//@{
 {
     return this.message;
 };
 
-//@}
 
 /// IdlArray ///
 // Entry point
 self.IdlArray = function()
-//@{
 {
     /**
      * A map from strings to the corresponding named IdlObject, such as
@@ -210,17 +195,13 @@
     this["inheritance"] = {};
 };
 
-//@}
 IdlArray.prototype.add_idls = function(raw_idls, options)
-//@{
 {
     /** Entry point.  See documentation at beginning of file. */
     this.internal_add_idls(WebIDL2.parse(raw_idls), options);
 };
 
-//@}
 IdlArray.prototype.add_untested_idls = function(raw_idls, options)
-//@{
 {
     /** Entry point.  See documentation at beginning of file. */
     var parsed_idls = WebIDL2.parse(raw_idls);
@@ -228,9 +209,7 @@
     this.internal_add_idls(parsed_idls, options);
 };
 
-//@}
 IdlArray.prototype.mark_as_untested = function (parsed_idls)
-//@{
 {
     for (var i = 0; i < parsed_idls.length; i++) {
         parsed_idls[i].untested = true;
@@ -241,21 +220,15 @@
         }
     }
 };
-//@}
 
-//@}
 IdlArray.prototype.is_excluded_by_options = function (name, options)
-//@{
 {
     return options &&
         (options.except && options.except.includes(name)
          || options.only && !options.only.includes(name));
 };
-//@}
 
-//@}
 IdlArray.prototype.add_dependency_idls = function(raw_idls, options)
-//@{
 {
     const parsed_idls = WebIDL2.parse(raw_idls);
     const new_options = { only: [] }
@@ -361,9 +334,7 @@
     }
 }
 
-//@}
 IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
-//@{
 {
     /**
      * Internal helper called by add_idls() and add_untested_idls().
@@ -501,9 +472,7 @@
     }.bind(this));
 };
 
-//@}
 IdlArray.prototype.add_objects = function(dict)
-//@{
 {
     /** Entry point.  See documentation at beginning of file. */
     for (var k in dict)
@@ -519,17 +488,13 @@
     }
 };
 
-//@}
 IdlArray.prototype.prevent_multiple_testing = function(name)
-//@{
 {
     /** Entry point.  See documentation at beginning of file. */
     this.members[name].prevent_multiple_testing = true;
 };
 
-//@}
 IdlArray.prototype.recursively_get_implements = function(interface_name)
-//@{
 {
     /**
      * Helper function for test().  Returns an array of things that implement
@@ -557,9 +522,7 @@
     return ret;
 };
 
-//@}
 IdlArray.prototype.recursively_get_includes = function(interface_name)
-//@{
 {
     /**
      * Helper function for test().  Returns an array of things that implement
@@ -587,9 +550,7 @@
     return ret;
 };
 
-//@}
 IdlArray.prototype.is_json_type = function(type)
-//@{
 {
     /**
      * Checks whether type is a JSON type as per
@@ -754,14 +715,12 @@
     throw new IdlHarnessError("Unexpected global object");
 }
 
-//@}
 /**
  * Asserts that the given error message is thrown for the given function.
  * @param {string|IdlHarnessError} error Expected Error message.
  * @param {Function} idlArrayFunc Function operating on an IdlArray that should throw.
  */
 IdlArray.prototype.assert_throws = function(error, idlArrayFunc)
-//@{
 {
     try {
         idlArrayFunc.call(this, this);
@@ -781,9 +740,7 @@
     throw new IdlHarnessError(`${idlArrayFunc} did not throw the expected IdlHarnessError`);
 }
 
-//@}
 IdlArray.prototype.test = function()
-//@{
 {
     /** Entry point.  See documentation at beginning of file. */
 
@@ -872,9 +829,7 @@
     }
 };
 
-//@}
 IdlArray.prototype.collapse_partials = function()
-//@{
 {
     const testedPartials = new Map();
     this.partials.forEach(function(parsed_idl)
@@ -955,9 +910,7 @@
     this.partials = [];
 }
 
-//@}
 IdlArray.prototype.assert_type_is = function(value, type)
-//@{
 {
     if (type.idlType in this.members
     && this.members[type.idlType] instanceof IdlTypedef) {
@@ -1176,12 +1129,10 @@
         throw new IdlHarnessError("Type " + type + " isn't an interface or dictionary");
     }
 };
-//@}
 
 /// IdlObject ///
 function IdlObject() {}
 IdlObject.prototype.test = function()
-//@{
 {
     /**
      * By default, this does nothing, so no actual tests are run for IdlObjects
@@ -1189,9 +1140,7 @@
      */
 };
 
-//@}
 IdlObject.prototype.has_extended_attribute = function(name)
-//@{
 {
     /**
      * This is only meaningful for things that support extended attributes,
@@ -1203,12 +1152,10 @@
     });
 };
 
-//@}
 
 /// IdlDictionary ///
 // Used for IdlArray.prototype.assert_type_is
 function IdlDictionary(obj)
-//@{
 {
     /**
      * obj is an object produced by the WebIDLParser.js "dictionary"
@@ -1231,7 +1178,6 @@
     this.base = obj.inheritance;
 }
 
-//@}
 IdlDictionary.prototype = Object.create(IdlObject.prototype);
 
 IdlDictionary.prototype.get_inheritance_stack = function() {
@@ -1240,7 +1186,6 @@
 
 /// IdlInterface ///
 function IdlInterface(obj, is_callback, is_mixin)
-//@{
 {
     /**
      * obj is an object produced by the WebIDLParser.js "interface" production.
@@ -1279,30 +1224,23 @@
     this._is_callback = is_callback;
     this._is_mixin = is_mixin;
 }
-//@}
 IdlInterface.prototype = Object.create(IdlObject.prototype);
 IdlInterface.prototype.is_callback = function()
-//@{
 {
     return this._is_callback;
 };
-//@}
 
 IdlInterface.prototype.is_mixin = function()
-//@{
 {
     return this._is_mixin;
 };
-//@}
 
 IdlInterface.prototype.has_constants = function()
-//@{
 {
     return this.members.some(function(member) {
         return member.type === "const";
     });
 };
-//@}
 
 IdlInterface.prototype.get_unscopables = function()
 {
@@ -1312,13 +1250,11 @@
 };
 
 IdlInterface.prototype.is_global = function()
-//@{
 {
     return this.extAttrs.some(function(attribute) {
         return attribute.name === "Global";
     });
 };
-//@}
 
 IdlInterface.prototype.has_to_json_regular_operation = function() {
     return this.members.some(function(m) {
@@ -1446,7 +1382,6 @@
 }
 
 IdlInterface.prototype.test = function()
-//@{
 {
     if (this.has_extended_attribute("NoInterfaceObject") || this.is_mixin())
     {
@@ -1478,10 +1413,8 @@
     // interface are still tested.
     this.test_members();
 };
-//@}
 
 IdlInterface.prototype.test_self = function()
-//@{
 {
     subsetTestByKey(this.name, test, function()
     {
@@ -1919,9 +1852,7 @@
     }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s @@unscopables property');
 };
 
-//@}
 IdlInterface.prototype.test_immutable_prototype = function(type, obj)
-//@{
 {
     if (typeof Object.setPrototypeOf !== "function") {
         return;
@@ -2023,9 +1954,7 @@
         "should return true");
 };
 
-//@}
 IdlInterface.prototype.test_member_const = function(member)
-//@{
 {
     if (!this.has_constants()) {
         throw new IdlHarnessError("Internal error: test_member_const called without any constants");
@@ -2084,9 +2013,7 @@
 };
 
 
-//@}
 IdlInterface.prototype.test_member_attribute = function(member)
-//@{
   {
     if (!shouldRunSubTest(this.name)) {
         return;
@@ -2179,9 +2106,7 @@
     }.bind(this));
 };
 
-//@}
 IdlInterface.prototype.test_member_operation = function(member)
-//@{
 {
     if (!shouldRunSubTest(this.name)) {
         return;
@@ -2274,9 +2199,7 @@
                   this.name + '.prototype[Symbol.unscopables].' + prop + ' must have the value `true`');
 };
 
-//@}
 IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)
-//@{
 {
     var done = a_test.done.bind(a_test);
     var operationUnforgeable = member.isUnforgeable;
@@ -2343,9 +2266,7 @@
     }
 }
 
-//@}
 IdlInterface.prototype.add_iterable_members = function(member)
-//@{
 {
     this.members.push(new IdlInterfaceMember(
         { type: "operation", name: "entries", idlType: "iterator", arguments: []}));
@@ -2385,9 +2306,7 @@
     }
 };
 
-//@}
 IdlInterface.prototype.test_member_iterable = function(member)
-//@{
 {
     var interfaceName = this.name;
     var isPairIterator = member.idlType.length === 2;
@@ -2413,9 +2332,7 @@
     }
 };
 
-//@}
 IdlInterface.prototype.test_member_stringifier = function(member)
-//@{
 {
     subsetTestByKey(this.name, test, function()
     {
@@ -2477,9 +2394,7 @@
     }.bind(this), this.name + " interface: stringifier");
 };
 
-//@}
 IdlInterface.prototype.test_members = function()
-//@{
 {
     for (var i = 0; i < this.members.length; i++)
     {
@@ -2556,9 +2471,7 @@
     }
 };
 
-//@}
 IdlInterface.prototype.test_object = function(desc)
-//@{
 {
     var obj, exception = null;
     try
@@ -2593,9 +2506,7 @@
     }
 };
 
-//@}
 IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
-//@{
 {
     // Only the object itself, not its members, are tested here, so if the
     // interface is untested, there is nothing to do.
@@ -2657,9 +2568,7 @@
     }.bind(this), "Stringification of " + desc);
 };
 
-//@}
 IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
-//@{
 {
     // TODO: Indexed and named properties, more checks on interface members
     this.already_tested = true;
@@ -2804,9 +2713,7 @@
     }
 };
 
-//@}
 IdlInterface.prototype.has_stringifier = function()
-//@{
 {
     if (this.name === "DOMException") {
         // toString is inherited from Error, so don't assume we have the
@@ -2823,9 +2730,7 @@
     return false;
 };
 
-//@}
 IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test)
-//@{
 {
     // This function tests WebIDL as of 2015-01-27.
     // TODO: Consider [Exposed].
@@ -2948,11 +2853,9 @@
 
     Promise.all(pendingPromises).then(a_test.done.bind(a_test));
 }
-//@}
 
 /// IdlInterfaceMember ///
 function IdlInterfaceMember(obj)
-//@{
 {
     /**
      * obj is an object produced by the WebIDLParser.js "ifMember" production.
@@ -2972,7 +2875,6 @@
     this.isUnscopable = this.has_extended_attribute("Unscopable");
 }
 
-//@}
 IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
 
 IdlInterfaceMember.prototype.is_to_json_regular_operation = function() {
@@ -2981,7 +2883,6 @@
 
 /// Internal helper functions ///
 function create_suitable_object(type)
-//@{
 {
     /**
      * type is an object produced by the WebIDLParser.js "type" production.  We
@@ -3017,12 +2918,10 @@
     }
     return null;
 }
-//@}
 
 /// IdlEnum ///
 // Used for IdlArray.prototype.assert_type_is
 function IdlEnum(obj)
-//@{
 {
     /**
      * obj is an object produced by the WebIDLParser.js "dictionary"
@@ -3036,14 +2935,12 @@
     this.values = obj.values;
 
 }
-//@}
 
 IdlEnum.prototype = Object.create(IdlObject.prototype);
 
 /// IdlTypedef ///
 // Used for IdlArray.prototype.assert_type_is
 function IdlTypedef(obj)
-//@{
 {
     /**
      * obj is an object produced by the WebIDLParser.js "typedef"
@@ -3057,13 +2954,11 @@
     this.idlType = obj.idlType;
 
 }
-//@}
 
 IdlTypedef.prototype = Object.create(IdlObject.prototype);
 
 /// IdlNamespace ///
 function IdlNamespace(obj)
-//@{
 {
     this.name = obj.name;
     this.extAttrs = obj.extAttrs;
@@ -3074,12 +2969,10 @@
     /** An array of IdlInterfaceMembers. */
     this.members = obj.members.map(m => new IdlInterfaceMember(m));
 }
-//@}
 
 IdlNamespace.prototype = Object.create(IdlObject.prototype);
 
 IdlNamespace.prototype.do_member_operation_asserts = function (memberHolderObject, member, a_test)
-//@{
 {
     var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
 
@@ -3108,10 +3001,8 @@
         "operation has wrong .length");
     a_test.done();
 }
-//@}
 
 IdlNamespace.prototype.test_member_operation = function(member)
-//@{
 {
     if (!shouldRunSubTest(this.name)) {
         return;
@@ -3136,10 +3027,8 @@
         this.do_member_operation_asserts(self[this.name], member, a_test);
     }.bind(this));
 };
-//@}
 
 IdlNamespace.prototype.test_member_attribute = function (member)
-//@{
 {
     if (!shouldRunSubTest(this.name)) {
         return;
@@ -3160,10 +3049,8 @@
         a_test.done();
     }.bind(this));
 };
-//@}
 
 IdlNamespace.prototype.test = function ()
-//@{
 {
     /**
      * TODO(lukebjerring): Assert:
@@ -3189,7 +3076,6 @@
         }
     };
 };
-//@}
 
 }());
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
index b7b110aa..99faa3c4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
@@ -20,28 +20,6 @@
         }]
       })" threw object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." ("InvalidStateError") expected object "TypeError" ("TypeError")
 FAIL addTransceiver() with valid rid value should succeed Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
-FAIL addTransceiver() with readonly ssrc set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          ssrc: 2
-        }]
-      })" threw object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." that is not a DOMException InvalidAccessError: property "code" is equal to 11, expected 15
-FAIL addTransceiver() with readonly rtx set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          rtx: {
-            ssrc: 2
-          }
-        }]
-      })" threw object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." that is not a DOMException InvalidAccessError: property "code" is equal to 11, expected 15
-FAIL addTransceiver() with readonly fec set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          fec: {
-            ssrc: 2
-          }
-        }]
-      })" threw object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." that is not a DOMException InvalidAccessError: property "code" is equal to 11, expected 15
 FAIL addTransceiver() with valid sendEncodings should succeed Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument.
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
index c0c5d782..6df05611 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https.html
@@ -354,56 +354,6 @@
     });
   }, `addTransceiver() with valid rid value should succeed`);
 
-  /*
-    5.1.  addTransceiver
-      7.  If any RTCRtpEncodingParameters dictionary in sendEncodings contains a
-          read-only parameter other than rid, throw an InvalidAccessError.
-
-      - The sendEncodings argument can be used to specify the number of offered
-        simulcast encodings, and optionally their RIDs and encoding parameters.
-        Aside from rid , all read-only parameters in the RTCRtpEncodingParameters
-        dictionaries, such as ssrc, must be left unset, or an error will be thrown.
-   */
-  test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
-
-    assert_throws('InvalidAccessError', () =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          ssrc: 2
-        }]
-      }));
-  }, `addTransceiver() with readonly ssrc set should throw InvalidAccessError`);
-
-  test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
-
-    assert_throws('InvalidAccessError', () =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          rtx: {
-            ssrc: 2
-          }
-        }]
-      }));
-  }, `addTransceiver() with readonly rtx set should throw InvalidAccessError`);
-
-  test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
-
-    assert_throws('InvalidAccessError', () =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          fec: {
-            ssrc: 2
-          }
-        }]
-      }));
-  }, `addTransceiver() with readonly fec set should throw InvalidAccessError`);
-
   test(t => {
     const pc = new RTCPeerConnection();
     t.add_cleanup(() => pc.close());
diff --git a/third_party/WebKit/LayoutTests/fast/events/autoscroll-iframe-no-scrolling.html b/third_party/WebKit/LayoutTests/fast/events/autoscroll-iframe-no-scrolling.html
index ff2e29b..ce07b80f 100644
--- a/third_party/WebKit/LayoutTests/fast/events/autoscroll-iframe-no-scrolling.html
+++ b/third_party/WebKit/LayoutTests/fast/events/autoscroll-iframe-no-scrolling.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <style>
   body {
     margin: 0px;
@@ -48,6 +49,7 @@
 "></iframe>
 
 <script>
+setAnimationRequiresRaster();
 var scrollable = document.getElementById('scrollable');
 
 function autoScroll(start_x, start_y, end_x, end_y) {
diff --git a/third_party/WebKit/LayoutTests/fast/events/autoscroll-over-scrollbar.html b/third_party/WebKit/LayoutTests/fast/events/autoscroll-over-scrollbar.html
index 2de7dab..2ef3e8f5 100644
--- a/third_party/WebKit/LayoutTests/fast/events/autoscroll-over-scrollbar.html
+++ b/third_party/WebKit/LayoutTests/fast/events/autoscroll-over-scrollbar.html
@@ -1,6 +1,7 @@
 <!DOCTYPE HTML>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <style>
   body {
     margin: 0px;
@@ -24,6 +25,7 @@
 </div>
 
 <script>
+setAnimationRequiresRaster();
 var scrollable = document.getElementById('scrollable');
 function autoScroll(start_x, start_y, end_x, end_y) {
   return new Promise((resolve, reject) => {
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click-hyperlink.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click-hyperlink.html
index 02cb3c76..1226aa9 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click-hyperlink.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click-hyperlink.html
@@ -1,6 +1,7 @@
 <html>
 <head>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script>
 window.jsTestIsAsync = true;
 if (window.testRunner)
@@ -33,6 +34,7 @@
 {
     if (!window.eventSender)
         return;
+    setAnimationRequiresRaster();
 
     eventSender.mouseMoveTo(testContainer.offsetLeft + 10, testContainer.offsetTop + 10);
     eventSender.mouseDown(MiddleMouseButton);
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click.html
index eb8ad4e..4709d84 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-click.html
@@ -9,6 +9,7 @@
 }
 </style>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 function start()
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-drag.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-drag.html
index 0ef958f..90718c76 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-drag.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-drag.html
@@ -9,6 +9,7 @@
 }
 </style>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 function start()
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-event-fired.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-event-fired.html
index bd6b9eb..3c7f4e6 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-event-fired.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-event-fired.html
@@ -9,6 +9,7 @@
 }
 </style>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 window.addEventListener('mousedown', function(event) {
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-in-iframe.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-in-iframe.html
index 24996b0..c2e2f3eb 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-in-iframe.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-in-iframe.html
@@ -1,6 +1,7 @@
 <html>
 <head>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 function start() {
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-latching.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-latching.html
index fe7ad71..20739a2 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-latching.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-latching.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <div id = "div" style="overflow: auto; width: 1400px">
 <table style="height:2000px; width: 1800px">
   <tbody>
@@ -14,6 +15,7 @@
 </table>
 </div>
 <script>
+setAnimationRequiresRaster();
 var testBubble = async_test("Tests that middleClickAutoscroll finds the correct ancestor layoutobject when starting in an unscrollable direction.")
 testBubble.step(function() {
   if (!window.eventSender)
@@ -26,12 +28,14 @@
   var endx = startx;
   var endy = starty + 100;
   var scrolledY = false;
+  // Middle-mouse drag down, from start to end.
   eventSender.mouseMoveTo(startx, starty);
-  eventSender.mouseDown(1);
+  eventSender.mouseDown(1 /* WebMouseEvent::Button::kMiddle */);
   eventSender.mouseMoveTo(endx, endy);
 
   window.onscroll = function() {
     if (!scrolledY) {
+      // First time we scroll, make sure it is downward.
       assert_not_equals(window.scrollY, 0);
       scrolledY = true;
       // Change the direction of the middle-click-autoscroll to rightward.
@@ -43,6 +47,8 @@
         assert_equals(div.scrollLeft, 0);
         eventSender.mouseUp(1);
         testBubble.done();
+        // TODO(crbug.com/888571): This call to testIFrame doesn't get hit after
+        // testBubble.done() gets called.
         testIFrame();
       }
     }
@@ -74,4 +80,4 @@
   };
 });
 }
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs-forbidden.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs-forbidden.html
index 5519373..8214c00d 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs-forbidden.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs-forbidden.html
@@ -17,6 +17,7 @@
 }
 </style>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 function start()
diff --git a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs.html b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs.html
index f1b882e..ba51d39c 100644
--- a/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs.html
+++ b/third_party/WebKit/LayoutTests/fast/events/middleClickAutoscroll-nested-divs.html
@@ -6,10 +6,11 @@
     height:300px;
     overflow:auto;
     border:2px solid red;
-    padding:10px";
+    padding:10px;
 }
 </style>
 <script src="../../resources/js-test.js"></script>
+<script src="../../resources/compositor-controls.js"></script>
 <script src="./resources/middleClickAutoscroll.js"></script>
 <script>
 function start()
diff --git a/third_party/WebKit/LayoutTests/fast/events/resources/middleClickAutoscroll.js b/third_party/WebKit/LayoutTests/fast/events/resources/middleClickAutoscroll.js
index f58baf64..c06905f 100644
--- a/third_party/WebKit/LayoutTests/fast/events/resources/middleClickAutoscroll.js
+++ b/third_party/WebKit/LayoutTests/fast/events/resources/middleClickAutoscroll.js
@@ -11,6 +11,9 @@
 
 function testPanScroll(param)
 {
+    // Make sure animations run. This requires compositor-controls.js.
+    setAnimationRequiresRaster();
+
     function finishTest()
     {
         if ($('container'))
@@ -36,23 +39,19 @@
         }
     }
 
-    var noModeScroll = false;
-    var scrolled = false;
+    var scrollStarted = false;
+    var scrollEnded = false;
 
     scrolledObject.onscroll = function() {
-        if (noModeScroll) {
-            testFailed('still autoscroll');
-            finishTest();
+        if (scrollStarted)
             return;
-        }
-
-        if (scrolled)
-            return;
-        scrolled = true;
+        scrollStarted = true;
+        scrollEnded = false;
         testPassed('autoscroll started');
         var cursorInfo = internals.getCurrentCursorInfo();
         debug("Mouse cursor shape: " + cursorInfo);
 
+        // Stop scrolling now
         if (window.eventSender) {
             if (param.clickOrDrag == 'click')
                 eventSender.mouseDown(middleButton);
@@ -61,18 +60,28 @@
     };
 
     scrollable.ownerDocument.onmouseup = function(e) {
-        if (!scrolled || e.button != middleButton)
+        // If we haven't started scrolling yet, do nothing.
+        if (!scrollStarted || e.button != middleButton)
             return;
-        noMoreScroll = true;
+        // Wait a while, then set scrollEnded to true
         window.setTimeout(function() {
-            testPassed('autoscroll stopped');
-            var cursorInfo = internals.getCurrentCursorInfo();
-            if (cursorInfo == "type=Pointer hotSpot=0,0" || cursorInfo == "type=IBeam hotSpot=0,0")
-                 testPassed('Mouse cursor cleared');
-            else
-                 testFailed('Mouse cursor shape: ' + cursorInfo);
+            scrollEnded = true;
+            // Wait a bit more and make sure it's still true (we didn't keep
+            // scrolling).
+            window.setTimeout(function() {
+                if (scrollEnded) {
+                    testPassed('autoscroll stopped');
+                } else {
+                    testFailed('autoscroll still scrolling');
+                }
+                var cursorInfo = internals.getCurrentCursorInfo();
+                if (cursorInfo == "type=Pointer hotSpot=0,0" || cursorInfo == "type=IBeam hotSpot=0,0")
+                     testPassed('Mouse cursor cleared');
+                else
+                     testFailed('Mouse cursor shape: ' + cursorInfo);
 
-            finishTest();
+                finishTest();
+            }, autoscrollInterval * 2);
         }, autoscrollInterval * 2);
     };
 
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchpad-fling.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchpad-fling.html
index 7a2e867..07ac9ce2 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchpad-fling.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchpad-fling.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <script src="../../../../resources/testharness.js"></script>
 <script src="../../../../resources/testharnessreport.js"></script>
+<script src="../../../../resources/compositor-controls.js"></script>
 <script src="../../../../resources/gesture-util.js"></script>
 
 <!-- This tests that the scrollbar thumb is deselected on a fling start -->
@@ -44,6 +45,7 @@
 </div>
 
 <script type="text/javascript">
+setAnimationRequiresRaster();
 internals.settings.setMockScrollbarsEnabled(true);
 
 promise_test (async () => {
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchscreen-fling.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchscreen-fling.html
index 8edfe2c..3d3e8a7b 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchscreen-fling.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/gesture-scrollbar-touchscreen-fling.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <script src="../../../../resources/testharness.js"></script>
 <script src="../../../../resources/testharnessreport.js"></script>
+<script src="../../../../resources/compositor-controls.js"></script>
 <script src="../../../../resources/gesture-util.js"></script>
 
 <!-- This tests that the scrollbar thumb is deselected on a fling start -->
@@ -44,6 +45,7 @@
 </div>
 
 <script type="text/javascript">
+setAnimationRequiresRaster();
 internals.settings.setMockScrollbarsEnabled(true);
 
 promise_test (async () => {
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
index 8e91822..123607b1 100644
--- a/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
+++ b/third_party/WebKit/LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-input-field.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <script src="../../../../resources/testharness.js"></script>
 <script src="../../../../resources/testharnessreport.js"></script>
+<script src="../../../../resources/compositor-controls.js"></script>
 <script src="../../../../resources/gesture-util.js"></script>
 <body style="margin:0">
   <div id="container" style="width: 500px; height: 200px; overflow-y: scroll; overflow-x: scroll">
@@ -12,6 +13,7 @@
 </body>
 
 <script type="text/javascript">
+setAnimationRequiresRaster();
 var gestureX = 100;
 var gestureY = 50;
 var box = document.getElementById("box");
@@ -21,7 +23,7 @@
 function calculateFullScroll() {
   fullyScrolled = box.scrollWidth - box.clientWidth;
 
-  // FIXME: Mac has a quirk where the text box text can actually be scrolled a little bit 
+  // FIXME: Mac has a quirk where the text box text can actually be scrolled a little bit
   // past the end. That is, scrollLeft = (scrollWidth - clientWidth) + 2 on Mac. Once
   // this is fixed we can remove this adjustment.
   box.scrollLeft = 100000;
diff --git a/third_party/WebKit/LayoutTests/hdr/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/hdr/color-jpeg-with-color-profile-expected.png
index 91f6da8d..f18cf63 100644
--- a/third_party/WebKit/LayoutTests/hdr/color-jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/hdr/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/scripted-task-queue-posttask.html b/third_party/WebKit/LayoutTests/http/tests/dom/scripted-task-queue-posttask.html
new file mode 100644
index 0000000..6d9e988
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/dom/scripted-task-queue-posttask.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<script>
+
+let resolved_promises = 0;
+
+function after_task() {
+  resolved_promises++;
+
+  if (resolved_promises == 10) {
+    done();
+  }
+}
+
+function queue_tasks(task_type) {
+  let task_queue = TaskQueue.default(task_type);
+  for (var i = 1; i < 11; i++) {
+    task_queue.postTask(function() {
+
+    }).then(after_task);
+  }
+}
+
+queue_tasks('user-interaction');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png
index 3478701..5498600 100644
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png
index 30451c9..fb2adf1e 100644
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png
+++ b/third_party/WebKit/LayoutTests/images/color-profile-image-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png
index 870a41a..13ffebd 100644
--- a/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png
+++ b/third_party/WebKit/LayoutTests/images/color-profile-image-svg-resource-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/size-failure.html b/third_party/WebKit/LayoutTests/images/size-failure.html
index 611c742b..a13c4c8 100644
--- a/third_party/WebKit/LayoutTests/images/size-failure.html
+++ b/third_party/WebKit/LayoutTests/images/size-failure.html
@@ -9,8 +9,8 @@
 window.onload = function() {
   if (!window.testRunner)
     return;
-  // Force a pixel dump to cover raterization issues if any.
-  testRunner.capturePixelsAsyncThen(function() {
+  // Force a full lifecycle update to cover rasterization issues if any.
+  testRunner.updateAllLifecyclePhasesAndCompositeThen(function() {
     testRunner.notifyDone();
   });
 };
diff --git a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png
index 463bec1..5cd5bb6a 100644
--- a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png
index dada128..1d2d9d5 100644
--- a/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png
+++ b/third_party/WebKit/LayoutTests/images/webp-color-profile-lossy-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/intersection-observer/v2/simple-occlusion-svg-foreign-object.html b/third_party/WebKit/LayoutTests/intersection-observer/v2/simple-occlusion-svg-foreign-object.html
new file mode 100644
index 0000000..a13938a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/intersection-observer/v2/simple-occlusion-svg-foreign-object.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../resources/intersection-observer-test-utils.js"></script>
+
+<style>
+body, html {
+  margin: 0;
+}
+pre, #log {
+  position: absolute;
+  top: 0;
+  left: 200px;
+}
+#target {
+  width: 100px;
+  height: 100px;
+  background-color: green;
+}
+#occluder {
+  width: 100px;
+  height: 100px;
+  background-color: blue;
+}
+</style>
+
+<div id="target"></div>
+<svg id="svg" style="display: block">
+  <foreignObject>
+    <div id="occluder"></div>
+  </foreignObject>
+</svg>
+
+<script>
+var entries = [];
+var target;
+var occluder;
+
+if (window.internals) {
+  internals.DisableIntersectionObserverThrottleDelay();
+}
+
+runTestCycle(function() {
+  target = document.getElementById("target");
+  occluder = document.getElementById("occluder");
+  assert_true(!!target, "target exists");
+  assert_true(!!occluder, "occluder exists");
+  var observer = new IntersectionObserver(function(changes) {
+    entries = entries.concat(changes)
+  }, {trackVisibility: true, delay: 100});
+  observer.observe(target);
+  entries = entries.concat(observer.takeRecords());
+  assert_equals(entries.length, 0, "No initial notifications.");
+  runTestCycle(step0, "First rAF.");
+}, "IntersectionObserverV2 in a single document using the implicit root, with an occluding element.");
+
+function step0() {
+  svg.style.marginTop = "-10px";
+  runTestCycle(step1, "svg.style.marginTop = '-10px'");
+  checkLastEntry(entries, 0, [0, 100, 0, 100, 0, 100, 0, 100, 0, 800, 0, 600, true, true]);
+}
+
+function step1() {
+  // Occluding elements with opacity=0 should not affect target visibility.
+  svg.style.opacity = "0";
+  runTestCycle(step2, "occluder.style.opacity = 0");
+  checkLastEntry(entries, 1, [0, 100, 0, 100, 0, 100, 0, 100, 0, 800, 0, 600, true, false]);
+}
+
+function step2() {
+  checkLastEntry(entries, 2, [0, 100, 0, 100, 0, 100, 0, 100, 0, 800, 0, 600, true, true]);
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/background/background-and-shadow.html b/third_party/WebKit/LayoutTests/paint/background/background-and-shadow.html
index f18c5e4..c1bd5800 100644
--- a/third_party/WebKit/LayoutTests/paint/background/background-and-shadow.html
+++ b/third_party/WebKit/LayoutTests/paint/background/background-and-shadow.html
@@ -27,7 +27,7 @@
 
 if (window.testRunner) {
   testRunner.waitUntilDone();
-  testRunner.capturePixelsAsyncThen(test);
+  testRunner.updateAllLifecyclePhasesAndCompositeThen(test);
 } else {
   setTimeout(test, 500);
 }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/background/background-resize-height.html b/third_party/WebKit/LayoutTests/paint/invalidation/background/background-resize-height.html
index 85fdc01..cb52db5 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/background/background-resize-height.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/background/background-resize-height.html
@@ -10,7 +10,7 @@
 {
     if (window.testRunner) {
         // This ensures finish of image decoding before running the test.
-        testRunner.capturePixelsAsyncThen(doTest);
+        testRunner.updateAllLifecyclePhasesAndCompositeThen(doTest);
     } else {
         doTest();
     }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html b/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html
index 12dd6c9..2b7e28c 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/background/obscured-background-no-repaint.html
@@ -72,7 +72,7 @@
             return;
 
         // Ensure the deferred decoder has decoded ../resources/apple.jpg.
-        testRunner.capturePixelsAsyncThen(function() {
+        testRunner.updateAllLifecyclePhasesAndCompositeThen(function() {
             internals.advanceImageAnimation(imgForAdvanceImageAnimation);
             testRunner.layoutAndPaintAsyncThen(function() {
                 internals.startTrackingRepaints(document);
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
index 9cce8f4..a1cf059 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
index ba2914f..ac7cb62 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index eb0a7fe5..d078b034 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 8e91e0cd..bb880ee9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index eb0a7fe5..d078b034 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
index 8348412..50b605b4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index b41ad5ca..41cd85f 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 0a97fc3e..6181f2d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
index 34b1906..5fbdafb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png
index 4eb73661..7b71843 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
index 1659705..c613221 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
index 160a4c97..cb7c834 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 1eacd18e..b5c052c 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 8b447521..3da4ddb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
index de512bbb0..b639c3ec 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
index abb5efc..68a45519 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 019c987..8958cfc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index 10590138..57b9ea4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png
new file mode 100644
index 0000000..7d3b5fbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
new file mode 100644
index 0000000..1a31637b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
new file mode 100644
index 0000000..7d3b5fbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png
new file mode 100644
index 0000000..b990a7a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
new file mode 100644
index 0000000..bee225a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
new file mode 100644
index 0000000..bc63788
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
new file mode 100644
index 0000000..d59c692
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png
new file mode 100644
index 0000000..fb0d3ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png
new file mode 100644
index 0000000..a9da061b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
new file mode 100644
index 0000000..34e09e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-retina/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
index bc27d09..e0de947 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
index f8cb60f..db361df9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
index 3f2ff3d..b9c550d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
index 08578fc6..d2e8254 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index 179d5f6..7d3b5fbf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 682d773..1a31637b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index 179d5f6..7d3b5fbf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
index 2dc0351..b990a7a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index 1958a56a..bee225a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 45593ca..bc63788 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index f98f8b4c..d59c692 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
index 407a741..fb0d3ff 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-image/img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
index f0509ba..a9da061b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 028bbf5..34e09e6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
index c1a31a79..f999e54c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
index 6c9b36ff..c8af289 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index 6c9b36ff..c8af289 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
index 27e2d13..d2a33ef23 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-expected.png
index 668c7dc..f7522883 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
index 19836d1..bacd8fff 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
index 8cad0e7..33e921a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index 5d8f57a1..9fdab925 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index b63e0630..a69e709 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
index 6c3010f..606a2ba 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-suite/test-expected.png
index 2c01450..5669961b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-suite/test-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-suite/test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
index 78a51d0..e980abc 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
index 6f57839..d144aaaa 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
index 1e0a2fe..55a4fb4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
index 09986b3..b5e8d3fc 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
index 6a1fdee..73b164c49 100644
--- a/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/images/color-profile-layer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
index 973cef02..caa9bdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-inner-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
index 1071d5c1..837ef4c8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
index 973cef02..caa9bdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
index c9491029..dbb25e1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
index eb6d47e..835cae3 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/extend-namespace-01-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
index 5a2db0f..9caedb9d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/W3C-SVG-1.1/paths-data-03-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
index 3fb071a..cd7fed7 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/use-on-symbol-inside-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
index 9187eb1..18af370 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
index 7564826d..0f9200da 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
index 7564826d..0f9200da 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-background-image-cross-fade-png-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
index cbad7802..f746b29 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-canvas-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-expected.png
index c77dc5fb..38eddda 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
index e283656..a7eaf60 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-filter-all-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
index d76e0369..945d627 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-image-shape-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
index e74b203..643fd57 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-munsell-adobe-to-srgb-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
index a414d65..8f2e14e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
index 95dffd2..3b367c8c 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-suite/test-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-suite/test-expected.png
index e4836b2d..07f962b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-suite/test-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-suite/test-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
index e7945062..63723587 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/png-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/printing/webgl-oversized-printing.html b/third_party/WebKit/LayoutTests/printing/webgl-oversized-printing.html
index b82776f..b9ed418 100644
--- a/third_party/WebKit/LayoutTests/printing/webgl-oversized-printing.html
+++ b/third_party/WebKit/LayoutTests/printing/webgl-oversized-printing.html
@@ -19,9 +19,9 @@
     testRunner.setPrinting();
     testRunner.waitUntilDone();
     testRunner.capturePixelsAsyncThen(function() {
-        testRunner.clearPrinting();
-        testPassed("Printed without crashing.");
-        testRunner.notifyDone();
+      testRunner.clearPrinting();
+      testPassed("Printed without crashing.");
+      testRunner.notifyDone();
     });
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/resources/compositor-controls.js b/third_party/WebKit/LayoutTests/resources/compositor-controls.js
new file mode 100644
index 0000000..97574f99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/resources/compositor-controls.js
@@ -0,0 +1,19 @@
+// To make sure animation events get processed, periodic lifecycle phase runs
+// will include rasterization. See
+// https://chromium.googlesource.com/chromium/src/+/master/docs/testing/writing_layout_tests.md
+// for more information.
+function setAnimationRequiresRaster() {
+  if (window.testRunner) {
+    testRunner.setAnimationRequiresRaster(true);
+  }
+}
+
+function updateAllLifecyclePhasesAndCompositeAsyncThen(callback) {
+  setTimeout(function() {
+    if (!window.testRunner) {
+      callback();
+    } else {
+      testRunner.updateAllLifecyclePhasesAndCompositeThen(callback);
+    }
+  },0);
+}
diff --git a/third_party/WebKit/LayoutTests/resources/gesture-util.js b/third_party/WebKit/LayoutTests/resources/gesture-util.js
index 0484df3..c59560c8 100644
--- a/third_party/WebKit/LayoutTests/resources/gesture-util.js
+++ b/third_party/WebKit/LayoutTests/resources/gesture-util.js
@@ -1,10 +1,13 @@
 function waitForCompositorCommit() {
   return new Promise((resolve) => {
-    // For now, we just rAF twice. It would be nice to have a proper mechanism
-    // for this.
-    window.requestAnimationFrame(() => {
-      window.requestAnimationFrame(resolve);
-    });
+    if (window.testRunner) {
+      testRunner.capturePixelsAsyncThen(resolve);
+    } else {
+      // Fall back to just rAF twice.
+      window.requestAnimationFrame(() => {
+        window.requestAnimationFrame(resolve);
+      });
+    }
   });
 }
 
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png
index d531c23a..724c4c6 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
index 4c58ea6..73be2eb 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/color-profile-image-profile-match-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
index fb6c0a22..f17b4de9 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/exif-orientation-height-image-document-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png
index 150214e..3cb69e14 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
index f9dfff0..8b345df30 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/jpeg-yuv-progressive-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png
index 6c5af75..b5deaa6 100644
--- a/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/exotic-color-space/images/rgb-png-with-cmyk-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png
index 8985181a..98f4e326 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cHRM_color_spin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png
index f4574e7..38fd7e76e6 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-jpeg-with-color-profile-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-expected.png
index 6019fd8..4272612 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png
index a1adeae..6ffa5b9 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-animate-rotate-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png
index 8d5326b..f8e11a3 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-cover-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png
index 8677b9d..d14b02c 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-repeat-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
index 0e9f6dd..c1bd0d56 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-background-image-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png
index c9981eb1a..394fc2d 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-fade-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-image-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
index 65d073c..9b03f579 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-border-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-clip-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-clip-expected.png
index 698ab2f..4a6d733 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-clip-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-clip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-iframe-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-iframe-expected.png
index 568259d..38fb2934 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
index 86fd329..52c0e0f 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
index f63c13d3d..1f219c47 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-canvas-pattern-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png
index 1af1b946..20942d0b 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png
index b1a1039..f5ea9c3c 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-pseudo-content-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png
index f94a834..596f7fc 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-image-svg-resource-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
index e358a8f..78d2926 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-object-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-object-expected.png
index f38d369..feabb59 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-object-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-expected.png
index 1b1a4d0..773b09f 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png
index d9008b97..f2de994b6e 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/color-profile-svg-foreign-object-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png
index 7ea62500..fae815da 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossless-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png
index cd3e1c5..8905b3a 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png
index 04aa174..3a6fa1f 100644
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png
+++ b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/webp-color-profile-lossy-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
index 137b243..c12b32d6 100644
--- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-addTransceiver.https-expected.txt
@@ -20,28 +20,6 @@
         }]
       })" did not throw
 PASS addTransceiver() with valid rid value should succeed
-FAIL addTransceiver() with readonly ssrc set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          ssrc: 2
-        }]
-      })" did not throw
-FAIL addTransceiver() with readonly rtx set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          rtx: {
-            ssrc: 2
-          }
-        }]
-      })" did not throw
-FAIL addTransceiver() with readonly fec set should throw InvalidAccessError assert_throws: function "() =>
-      pc.addTransceiver('audio', {
-        sendEncodings: [{
-          fec: {
-            ssrc: 2
-          }
-        }]
-      })" did not throw
 PASS addTransceiver() with valid sendEncodings should succeed
 Harness: the test ran to completion.
 
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 6eb3e4b..f19508d 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -6907,6 +6907,14 @@
     getter onaudioprocess
     method constructor
     setter onaudioprocess
+interface ScriptedTaskQueue
+    attribute @@toStringTag
+    method constructor
+    method postTask
+interface ScriptedTaskQueueController
+    attribute @@toStringTag
+    method constructor
+    method default
 interface ScrollTimeline : AnimationTimeline
     attribute @@toStringTag
     getter endScrollOffset
@@ -10497,6 +10505,7 @@
     attribute textInputController
     attribute top
     attribute window
+    getter TaskQueue
     getter TrustedTypes
     getter applicationCache
     getter caches
@@ -10700,6 +10709,7 @@
     method webkitRequestAnimationFrame
     method webkitRequestFileSystem
     method webkitResolveLocalFileSystemURL
+    setter TaskQueue
     setter clientInformation
     setter cookieStore
     setter defaultStatus
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h
index 690de322..fb5425c 100644
--- a/third_party/blink/public/platform/task_type.h
+++ b/third_party/blink/public/platform/task_type.h
@@ -127,6 +127,10 @@
   // Tasks used for DedicatedWorker's requestAnimationFrame.
   kWorkerAnimation = 51,
 
+  // For tasks started with the experimental Scheduling API
+  kExperimentalWebSchedulingUserInteraction = 53,
+  kExperimentalWebSchedulingBestEffort = 54,
+
   ///////////////////////////////////////
   // Not-speced tasks should use one of the following task types
   ///////////////////////////////////////
@@ -198,7 +202,7 @@
   kWorkerThreadTaskQueueV8 = 47,
   kWorkerThreadTaskQueueCompositor = 48,
 
-  kCount = 53,
+  kCount = 55,
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_layer_tree_view.h b/third_party/blink/public/platform/web_layer_tree_view.h
index 4a2e6d84..130a21fc 100644
--- a/third_party/blink/public/platform/web_layer_tree_view.h
+++ b/third_party/blink/public/platform/web_layer_tree_view.h
@@ -152,13 +152,10 @@
   virtual void CompositeAndReadbackAsync(
       base::OnceCallback<void(const SkBitmap&)> callback) {}
 
-  // Synchronously run all lifecycle phases and compositor update with no
-  // raster. Should only be called by layout tests running in synchronous
-  // single-threaded mode.
-  virtual void SynchronouslyCompositeNoRasterForTesting() {}
-
-  // Synchronously rasterizes and composites a frame.
-  virtual void CompositeWithRasterForTesting() {}
+  // Synchronously performs the complete set of document lifecycle phases,
+  // including updates to the compositor state, optionally including
+  // rasterization.
+  virtual void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) {}
 
   // Prevents updates to layer tree from becoming visible.
   virtual std::unique_ptr<cc::ScopedDeferCommits> DeferCommits() {
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h
index 025c15bf..ebbeed1e 100644
--- a/third_party/blink/public/web/web_widget.h
+++ b/third_party/blink/public/web/web_widget.h
@@ -103,12 +103,10 @@
   virtual void UpdateLifecycle(
       LifecycleUpdate requested_update = LifecycleUpdate::kAll) {}
 
-  // Performs the complete set of document lifecycle phases, including updates
-  // to the compositor state except rasterization.
-  virtual void UpdateAllLifecyclePhasesAndCompositeForTesting() {}
-
-  // Synchronously rasterizes and composites a frame.
-  virtual void CompositeWithRasterForTesting() {}
+  // Synchronously performs the complete set of document lifecycle phases,
+  // including updates to the compositor state, optionally including
+  // rasterization.
+  virtual void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) {}
 
   // Called to paint the rectangular region within the WebWidget
   // onto the specified canvas at (viewPort.x,viewPort.y).
diff --git a/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index 389eeacf1..de8f9a8 100644
--- a/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -160,6 +160,8 @@
   "$bindings_core_v8_output_dir/v8_create_script_callback.h",
   "$bindings_core_v8_output_dir/v8_create_url_callback.cc",
   "$bindings_core_v8_output_dir/v8_create_url_callback.h",
+  "$bindings_core_v8_output_dir/v8_task_queue_post_callback.cc",
+  "$bindings_core_v8_output_dir/v8_task_queue_post_callback.h",
   "$bindings_core_v8_output_dir/v8_void_function.cc",
   "$bindings_core_v8_output_dir/v8_void_function.h",
 ]
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc b/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
index 25efed8..278b2ec 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
@@ -94,7 +94,7 @@
     if (LocalFrame* frame = dom_window->GetFrame()) {
       return mojom::blink::UserActivationSnapshot::New(
           frame->HasBeenActivated(),
-          Frame::HasTransientUserActivation(frame, false));
+          LocalFrame::HasTransientUserActivation(frame, false));
     }
   }
   return nullptr;
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 335bd84..3707776 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -126,6 +126,8 @@
                     "policy/policy.idl",
                     "dom/processing_instruction.idl",
                     "dom/range.idl",
+                    "dom/scripted_task_queue.idl",
+                    "dom/scripted_task_queue_controller.idl",
                     "dom/static_range.idl",
                     "dom/text.idl",
                     "dom/tree_walker.idl",
diff --git a/third_party/blink/renderer/core/dom/BUILD.gn b/third_party/blink/renderer/core/dom/BUILD.gn
index aa22eeb9..a2dbb332 100644
--- a/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/third_party/blink/renderer/core/dom/BUILD.gn
@@ -226,6 +226,10 @@
     "scripted_animation_controller.h",
     "scripted_idle_task_controller.cc",
     "scripted_idle_task_controller.h",
+    "scripted_task_queue.cc",
+    "scripted_task_queue.h",
+    "scripted_task_queue_controller.cc",
+    "scripted_task_queue_controller.h",
     "shadow_root.cc",
     "shadow_root.h",
     "shadow_root_v0.cc",
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue.cc b/third_party/blink/renderer/core/dom/scripted_task_queue.cc
new file mode 100644
index 0000000..ce70145f
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue.cc
@@ -0,0 +1,156 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/scripted_task_queue.h"
+
+#include <memory>
+#include <utility>
+
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_task_queue_post_callback.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
+
+namespace blink {
+
+namespace {
+
+class TaskQueuePostCallbackWrapper {
+ public:
+  static std::unique_ptr<TaskQueuePostCallbackWrapper> Create(
+      int id,
+      ScriptedTaskQueue* task_queue) {
+    return std::unique_ptr<TaskQueuePostCallbackWrapper>(
+        new TaskQueuePostCallbackWrapper(id, task_queue));
+  }
+
+  void TaskFired() {
+    if (task_queue_)
+      task_queue_->CallbackFired(id_);
+  }
+
+ private:
+  TaskQueuePostCallbackWrapper(int id, ScriptedTaskQueue* task_queue)
+      : id_(id), task_queue_(task_queue) {}
+
+  int id_;
+  WeakPersistent<ScriptedTaskQueue> task_queue_;
+};
+
+}  // namespace
+
+class ScriptedTaskQueue::WrappedCallback
+    : public GarbageCollected<WrappedCallback> {
+  WTF_MAKE_NONCOPYABLE(WrappedCallback);
+
+ public:
+  WrappedCallback(V8TaskQueuePostCallback* callback,
+                  ScriptPromiseResolver* resolver)
+      : callback_(callback), resolver_(resolver) {}
+
+  void Trace(Visitor* visitor) {
+    visitor->Trace(callback_);
+    visitor->Trace(resolver_);
+  }
+
+  void Invoke() {
+    callback_->InvokeAndReportException(nullptr);
+    resolver_->Resolve();
+  }
+
+  void Reject() { resolver_->Reject(); }
+
+ private:
+  TraceWrapperMember<V8TaskQueuePostCallback> callback_;
+  Member<ScriptPromiseResolver> resolver_;
+};
+
+ScriptedTaskQueue::ScriptedTaskQueue(ExecutionContext* context,
+                                     TaskType task_type)
+    : PausableObject(context) {
+  task_runner_ = GetExecutionContext()->GetTaskRunner(task_type);
+  PauseIfNeeded();
+}
+
+void ScriptedTaskQueue::Trace(blink::Visitor* visitor) {
+  visitor->Trace(pending_tasks_);
+  ScriptWrappable::Trace(visitor);
+  PausableObject::Trace(visitor);
+}
+
+ScriptPromise ScriptedTaskQueue::postTask(ScriptState* script_state,
+                                          V8TaskQueuePostCallback* callback,
+                                          AbortSignal* signal) {
+  CallbackId id = next_callback_id_++;
+
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+
+  if (signal) {
+    if (signal->aborted()) {
+      resolver->Reject();
+      return resolver->Promise();
+    }
+
+    signal->AddAlgorithm(
+        WTF::Bind(&ScriptedTaskQueue::AbortTask, WrapPersistent(this), id));
+  }
+
+  pending_tasks_.Set(id, new WrappedCallback(callback, resolver));
+
+  auto callback_wrapper = TaskQueuePostCallbackWrapper::Create(id, this);
+  task_runner_->PostTask(FROM_HERE,
+                         WTF::Bind(&TaskQueuePostCallbackWrapper::TaskFired,
+                                   std::move(callback_wrapper)));
+
+  return resolver->Promise();
+}
+
+void ScriptedTaskQueue::CallbackFired(CallbackId id) {
+  if (paused_) {
+    paused_tasks_.push_back(id);
+    return;
+  }
+
+  auto task_iter = pending_tasks_.find(id);
+  if (task_iter == pending_tasks_.end())
+    return;
+
+  task_iter->value->Invoke();
+  // Can't use the iterator here since running the task
+  // might invalidate it.
+  pending_tasks_.erase(id);
+}
+
+void ScriptedTaskQueue::AbortTask(CallbackId id) {
+  auto task_iter = pending_tasks_.find(id);
+  if (task_iter == pending_tasks_.end())
+    return;
+
+  task_iter->value->Reject();
+  pending_tasks_.erase(id);
+}
+
+void ScriptedTaskQueue::ContextDestroyed(ExecutionContext*) {
+  pending_tasks_.clear();
+  paused_tasks_.clear();
+}
+
+void ScriptedTaskQueue::Pause() {
+  paused_ = true;
+}
+
+void ScriptedTaskQueue::Unpause() {
+  paused_ = false;
+
+  for (auto& task_id : paused_tasks_) {
+    auto callback_wrapper = TaskQueuePostCallbackWrapper::Create(task_id, this);
+    task_runner_->PostTask(FROM_HERE,
+                           WTF::Bind(&TaskQueuePostCallbackWrapper::TaskFired,
+                                     std::move(callback_wrapper)));
+  }
+
+  paused_tasks_.clear();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue.h b/third_party/blink/renderer/core/dom/scripted_task_queue.h
new file mode 100644
index 0000000..d5b3bdb
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue.h
@@ -0,0 +1,61 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/dom/pausable_object.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class AbortSignal;
+class ScriptState;
+class V8TaskQueuePostCallback;
+
+// This class corresponds to the ScriptedTaskQueue interface.
+class CORE_EXPORT ScriptedTaskQueue final : public ScriptWrappable,
+                                            public PausableObject {
+  DEFINE_WRAPPERTYPEINFO();
+  USING_GARBAGE_COLLECTED_MIXIN(ScriptedTaskQueue);
+
+ public:
+  static ScriptedTaskQueue* Create(ExecutionContext* context,
+                                   TaskType task_type) {
+    return new ScriptedTaskQueue(context, task_type);
+  }
+
+  using CallbackId = int;
+
+  ScriptPromise postTask(ScriptState*,
+                         V8TaskQueuePostCallback* callback,
+                         AbortSignal*);
+
+  void CallbackFired(CallbackId id);
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  explicit ScriptedTaskQueue(ExecutionContext*, TaskType);
+
+  // PausableObject interface.
+  void ContextDestroyed(ExecutionContext*) override;
+  void Pause() override;
+  void Unpause() override;
+
+  void AbortTask(CallbackId id);
+
+  class WrappedCallback;
+  HeapHashMap<CallbackId, TraceWrapperMember<WrappedCallback>> pending_tasks_;
+  Vector<CallbackId> paused_tasks_;
+  CallbackId next_callback_id_ = 1;
+  bool paused_ = false;
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_H_
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue.idl b/third_party/blink/renderer/core/dom/scripted_task_queue.idl
new file mode 100644
index 0000000..6eeb70b
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue.idl
@@ -0,0 +1,9 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+callback TaskQueuePostCallback = void ();
+
+[RuntimeEnabled=WorkerTaskQueue] interface ScriptedTaskQueue {
+    [CallWith=ScriptState] Promise<any> postTask(TaskQueuePostCallback callback, optional AbortSignal signal = null);
+};
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue_controller.cc b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.cc
new file mode 100644
index 0000000..b25ead23
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.cc
@@ -0,0 +1,59 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/scripted_task_queue_controller.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/scripted_task_queue.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+const char ScriptedTaskQueueController::kSupplementName[] =
+    "ScriptedTaskQueueController";
+
+ScriptedTaskQueueController* ScriptedTaskQueueController::From(
+    Document& document) {
+  ScriptedTaskQueueController* task_queue_controller =
+      Supplement<Document>::From<ScriptedTaskQueueController>(document);
+  if (!task_queue_controller) {
+    task_queue_controller = new ScriptedTaskQueueController(&document);
+    Supplement<Document>::ProvideTo(document, task_queue_controller);
+  }
+  return task_queue_controller;
+}
+
+ScriptedTaskQueueController::ScriptedTaskQueueController(
+    ExecutionContext* context)
+    : ContextLifecycleObserver(context) {}
+
+void ScriptedTaskQueueController::Trace(blink::Visitor* visitor) {
+  visitor->Trace(task_queues_);
+  Supplement<Document>::Trace(visitor);
+  ScriptWrappable::Trace(visitor);
+  ContextLifecycleObserver::Trace(visitor);
+}
+
+ScriptedTaskQueue* ScriptedTaskQueueController::defaultQueue(
+    const String& queue_name) {
+  auto iter = task_queues_.find(queue_name);
+  if (iter != task_queues_.end()) {
+    return iter->value.Get();
+  }
+
+  TaskType task_type = TaskType::kExperimentalWebSchedulingBestEffort;
+  if (queue_name == "user-interaction")
+    task_type = TaskType::kExperimentalWebSchedulingUserInteraction;
+  else if (queue_name != "best-effort")
+    NOTREACHED();
+
+  auto* task_queue =
+      ScriptedTaskQueue::Create(GetExecutionContext(), task_type);
+  task_queues_.insert(queue_name, task_queue);
+
+  return task_queue;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue_controller.h b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.h
new file mode 100644
index 0000000..8e690c0
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_CONTROLLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_CONTROLLER_H_
+
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class Document;
+
+class ScriptedTaskQueue;
+
+// This class corresponds to the ScriptedTaskQueueController interface.
+class CORE_EXPORT ScriptedTaskQueueController final
+    : public ScriptWrappable,
+      public ContextLifecycleObserver,
+      public Supplement<Document> {
+  DEFINE_WRAPPERTYPEINFO();
+  USING_GARBAGE_COLLECTED_MIXIN(ScriptedTaskQueueController);
+
+ public:
+  static const char kSupplementName[];
+
+  static ScriptedTaskQueueController* From(Document&);
+
+  ScriptedTaskQueue* defaultQueue(const String&);
+
+  void Trace(blink::Visitor*) override;
+
+ private:
+  explicit ScriptedTaskQueueController(ExecutionContext*);
+
+  HeapHashMap<String, TraceWrapperMember<ScriptedTaskQueue>> task_queues_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SCRIPTED_TASK_QUEUE_CONTROLLER_H_
diff --git a/third_party/blink/renderer/core/dom/scripted_task_queue_controller.idl b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.idl
new file mode 100644
index 0000000..be7e627
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/scripted_task_queue_controller.idl
@@ -0,0 +1,9 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+enum MainThreadTaskQueueType { "user-interaction", "best-effort" };
+
+[RuntimeEnabled=WorkerTaskQueue] interface ScriptedTaskQueueController {
+    [ImplementedAs=defaultQueue] ScriptedTaskQueue default(MainThreadTaskQueueType queue_type);
+};
diff --git a/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc b/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
index df4f5ea..f2aa169 100644
--- a/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
+++ b/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
@@ -20,7 +20,7 @@
 
 TEST(UserGestureIndicatorTest, ConstructedWithNewUserGesture) {
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
 
   EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
   EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
@@ -30,7 +30,7 @@
 
 TEST(UserGestureIndicatorTest, ConstructedWithUserGesture) {
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(nullptr);
+      LocalFrame::NotifyUserActivation(nullptr);
 
   EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
   EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
@@ -51,7 +51,7 @@
 TEST(UserGestureIndicatorTest, DestructUserGestureIndicator) {
   {
     std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-        Frame::NotifyUserActivation(nullptr);
+        LocalFrame::NotifyUserActivation(nullptr);
 
     EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
     EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
@@ -66,7 +66,7 @@
 TEST(UserGestureIndicatorTest, ScopedNewUserGestureIndicators) {
   // Root GestureIndicator and GestureToken.
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
 
   EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
   EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
@@ -74,7 +74,8 @@
     // Construct inner UserGestureIndicator.
     // It should share GestureToken with the root indicator.
     std::unique_ptr<UserGestureIndicator> inner_user_gesture =
-        Frame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
+        LocalFrame::NotifyUserActivation(nullptr,
+                                         UserGestureToken::kNewGesture);
 
     EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
     EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
@@ -94,7 +95,7 @@
 
 TEST(UserGestureIndicatorTest, MultipleGesturesWithTheSameToken) {
   std::unique_ptr<UserGestureIndicator> indicator =
-      Frame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
   EXPECT_TRUE(UserGestureIndicator::ProcessingUserGesture());
   EXPECT_NE(nullptr, UserGestureIndicator::CurrentToken());
   {
@@ -116,7 +117,7 @@
   {
     // Token times out after 1 second.
     std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-        Frame::NotifyUserActivation(nullptr);
+        LocalFrame::NotifyUserActivation(nullptr);
     scoped_refptr<UserGestureToken> token = user_gesture_scope->CurrentToken();
     EXPECT_TRUE(token->HasGestures());
     clock.Advance(TimeDelta::FromSecondsD(0.75));
@@ -131,7 +132,7 @@
 
     {
       std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-          Frame::NotifyUserActivation(nullptr);
+          LocalFrame::NotifyUserActivation(nullptr);
       token = user_gesture_scope->CurrentToken();
       EXPECT_TRUE(token->HasGestures());
       clock.Advance(TimeDelta::FromSecondsD(0.75));
diff --git a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
index 4d665a4..ea1691d 100644
--- a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
@@ -74,7 +74,7 @@
   Settings* const settings = frame.GetSettings();
   const bool default_value =
       (settings && settings->GetJavaScriptCanAccessClipboard()) ||
-      Frame::HasTransientUserActivation(&frame);
+      LocalFrame::HasTransientUserActivation(&frame);
   if (!frame.GetContentSettingsClient())
     return default_value;
   return frame.GetContentSettingsClient()->AllowWriteToClipboard(default_value);
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 06c0624..3a57e97 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -672,7 +672,7 @@
     return false;
 
   bool has_user_gesture =
-      Frame::HasTransientUserActivation(web_frame_->GetFrame());
+      LocalFrame::HasTransientUserActivation(web_frame_->GetFrame());
   webview->Client()->NavigateBackForwardSoon(offset, has_user_gesture);
   return true;
 }
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 585734c6..ab84e7e 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -568,8 +568,9 @@
   v8::Local<v8::Context> context =
       web_view_helper.LocalMainFrame()->MainWorldScriptContext();
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      main_frame->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(main_frame->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   ScriptExecutionCallbackHelper callback_helper(context);
   v8::Local<v8::Function> function =
       v8::Function::New(context, callback).ToLocalChecked();
@@ -7328,7 +7329,7 @@
   frame_request.SetTriggeringEventInfo(
       WebTriggeringEventInfo::kFromTrustedEvent);
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   web_frame_client.IgnoreNavigations();
   ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
       ->Loader()
@@ -8137,7 +8138,7 @@
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   Document* document = frame->GetDocument();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Element* div_fullscreen = document->getElementById("div1");
   Fullscreen::RequestFullscreen(*div_fullscreen);
   EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document));
@@ -8176,7 +8177,7 @@
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   Document* document = frame->GetDocument();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Element* div_fullscreen = document->getElementById("div1");
   Fullscreen::RequestFullscreen(*div_fullscreen);
   EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document));
@@ -8245,7 +8246,7 @@
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   Document* document = frame->GetDocument();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*document->documentElement());
   EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document));
   web_view_impl->DidEnterFullscreen();
@@ -8295,7 +8296,7 @@
           ->GetFrame();
   Document* document = frame->GetDocument();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Element* div_fullscreen = document->getElementById("div1");
   Fullscreen::RequestFullscreen(*div_fullscreen);
   web_view_impl->DidEnterFullscreen();
@@ -8337,7 +8338,7 @@
 
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(top_doc->GetFrame());
+        LocalFrame::NotifyUserActivation(top_doc->GetFrame());
     Fullscreen::RequestFullscreen(*top_body);
   }
   web_view_impl->DidEnterFullscreen();
@@ -8345,7 +8346,7 @@
 
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(iframe_doc->GetFrame());
+        LocalFrame::NotifyUserActivation(iframe_doc->GetFrame());
     Fullscreen::RequestFullscreen(*iframe_body);
   }
   web_view_impl->DidEnterFullscreen();
@@ -8391,7 +8392,7 @@
 
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement());
   web_view_impl->DidEnterFullscreen();
   web_view_impl->UpdateAllLifecyclePhases();
@@ -8430,7 +8431,7 @@
                           ->GetLayoutView();
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement());
   web_view_impl->DidEnterFullscreen();
   web_view_impl->UpdateAllLifecyclePhases();
@@ -8496,7 +8497,7 @@
   {
     LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(frame);
+        LocalFrame::NotifyUserActivation(frame);
     Fullscreen::RequestFullscreen(*frame->GetDocument()->body());
   }
 
@@ -8559,7 +8560,7 @@
 
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
   Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement());
   web_view_impl->DidEnterFullscreen();
   web_view_impl->UpdateAllLifecyclePhases();
@@ -8603,7 +8604,7 @@
 
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   HTMLVideoElement* video =
       ToHTMLVideoElement(frame->GetDocument()->getElementById("video"));
   EXPECT_TRUE(video->UsesOverlayFullscreenVideo());
@@ -12153,8 +12154,8 @@
 
   // Simulate an input element focus leading to Element::focus() call with a
   // user gesture.
-  Frame::NotifyUserActivation(local_frame->GetFrame(),
-                              UserGestureToken::kNewGesture);
+  LocalFrame::NotifyUserActivation(local_frame->GetFrame(),
+                                   UserGestureToken::kNewGesture);
   local_frame->ExecuteScript(
       WebScriptSource("window.focus();"
                       "document.querySelector('input').focus();"));
@@ -13005,7 +13006,7 @@
   LocalFrame* frame = ToLocalFrame(WebView().GetPage()->MainFrame());
   Element* element = frame->GetDocument()->body();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*element);
   WebView().DidEnterFullscreen();
 
diff --git a/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc b/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
index 86c15381..5cc3f254 100644
--- a/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
@@ -75,7 +75,8 @@
   }
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   GetInputMethodController().SetComposition(
       String(text), ImeTextSpanVectorBuilder::Build(ime_text_spans),
@@ -112,7 +113,8 @@
     const WebRange& replacement_range,
     int relative_caret_position) {
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) {
     return plugin->CommitText(text, ime_text_spans, replacement_range,
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index 9f6539c..7d00e155 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -411,14 +411,11 @@
       *page_, *page_->DeprecatedLocalMainFrame(), requested_update);
 }
 
-void WebPagePopupImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() {
-  if (layer_tree_view_)
-    layer_tree_view_->SynchronouslyCompositeNoRasterForTesting();
-}
-
-void WebPagePopupImpl::CompositeWithRasterForTesting() {
-  if (layer_tree_view_)
-    layer_tree_view_->CompositeWithRasterForTesting();
+void WebPagePopupImpl::UpdateAllLifecyclePhasesAndCompositeForTesting(
+    bool do_raster) {
+  if (layer_tree_view_) {
+    layer_tree_view_->UpdateAllLifecyclePhasesAndCompositeForTesting(do_raster);
+  }
 }
 
 void WebPagePopupImpl::PaintContent(cc::PaintCanvas* canvas,
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
index 38dbb53d..486da7e 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.h
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -85,8 +85,7 @@
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
   void BeginFrame(base::TimeTicks last_frame_time) override;
   void UpdateLifecycle(LifecycleUpdate requested_update) override;
-  void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
-  void CompositeWithRasterForTesting() override;
+  void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override;
   void WillCloseLayerTreeView() override;
   void PaintContent(cc::PaintCanvas*, const WebRect&) override;
   void Resize(const WebSize&) override;
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
index 228e92e..db6cf1d 100644
--- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -557,7 +557,7 @@
   std::unique_ptr<UserGestureIndicator> gesture_indicator;
   if (popups_allowed) {
     gesture_indicator =
-        Frame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+        LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
   }
 
   v8::HandleScope handle_scope(ToIsolate(frame));
diff --git a/third_party/blink/renderer/core/exported/web_scoped_user_gesture.cc b/third_party/blink/renderer/core/exported/web_scoped_user_gesture.cc
index 2af9d44..c15319b 100644
--- a/third_party/blink/renderer/core/exported/web_scoped_user_gesture.cc
+++ b/third_party/blink/renderer/core/exported/web_scoped_user_gesture.cc
@@ -43,7 +43,7 @@
 }
 
 WebScopedUserGesture::WebScopedUserGesture(WebLocalFrame* frame) {
-  indicator_ = Frame::NotifyUserActivation(
+  indicator_ = LocalFrame::NotifyUserActivation(
       frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr,
       UserGestureToken::kNewGesture);
 }
diff --git a/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc b/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
index 02bf71a..a2ea828 100644
--- a/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
+++ b/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
@@ -38,13 +38,13 @@
 namespace blink {
 
 bool WebUserGestureIndicator::IsProcessingUserGesture(WebLocalFrame* frame) {
-  return Frame::HasTransientUserActivation(
+  return LocalFrame::HasTransientUserActivation(
       frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr);
 }
 
 bool WebUserGestureIndicator::IsProcessingUserGestureThreadSafe(
     WebLocalFrame* frame) {
-  return Frame::HasTransientUserActivation(
+  return LocalFrame::HasTransientUserActivation(
       frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true);
 }
 
@@ -54,7 +54,7 @@
 bool WebUserGestureIndicator::ConsumeUserGesture(
     WebLocalFrame* frame,
     UserActivationUpdateSource update_source) {
-  return Frame::ConsumeTransientUserActivation(
+  return LocalFrame::ConsumeTransientUserActivation(
       frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true,
       update_source);
 
diff --git a/third_party/blink/renderer/core/exported/web_user_gesture_token_test.cc b/third_party/blink/renderer/core/exported/web_user_gesture_token_test.cc
index 15ce2e8..5c532fd 100644
--- a/third_party/blink/renderer/core/exported/web_user_gesture_token_test.cc
+++ b/third_party/blink/renderer/core/exported/web_user_gesture_token_test.cc
@@ -49,7 +49,8 @@
 
   {
     std::unique_ptr<UserGestureIndicator> indicator =
-        Frame::NotifyUserActivation(nullptr, UserGestureToken::kNewGesture);
+        LocalFrame::NotifyUserActivation(nullptr,
+                                         UserGestureToken::kNewGesture);
     EXPECT_TRUE(WebUserGestureIndicator::IsProcessingUserGesture(nullptr));
     token = WebUserGestureIndicator::CurrentUserGestureToken();
   }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index c6c7154..6df0cc2 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1623,14 +1623,11 @@
   }
 }
 
-void WebViewImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() {
-  if (layer_tree_view_)
-    layer_tree_view_->SynchronouslyCompositeNoRasterForTesting();
-}
-
-void WebViewImpl::CompositeWithRasterForTesting() {
-  // This should not be called directly on WebViewImpl.
-  NOTREACHED();
+void WebViewImpl::UpdateAllLifecyclePhasesAndCompositeForTesting(
+    bool do_raster) {
+  if (layer_tree_view_) {
+    layer_tree_view_->UpdateAllLifecyclePhasesAndCompositeForTesting(do_raster);
+  }
 }
 
 void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const WebRect& rect) {
@@ -1816,7 +1813,7 @@
       break;
     case WebInputEvent::kMouseDown:
       event_type = EventTypeNames::mousedown;
-      gesture_indicator = Frame::NotifyUserActivation(
+      gesture_indicator = LocalFrame::NotifyUserActivation(
           node->GetDocument().GetFrame(), UserGestureToken::kNewGesture);
       mouse_capture_gesture_token_ = gesture_indicator->CurrentToken();
       break;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index b1399b1..72e55d9 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -119,8 +119,7 @@
   void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
 
   void UpdateLifecycle(LifecycleUpdate requested_update) override;
-  void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
-  void CompositeWithRasterForTesting() override;
+  void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override;
   void PaintContent(cc::PaintCanvas*, const WebRect&) override;
   void PaintContentIgnoringCompositing(cc::PaintCanvas*,
                                        const WebRect&) override;
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index f701e233..c81ef4a 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -2347,7 +2347,7 @@
   LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
   Element* element = frame->GetDocument()->documentElement();
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*element);
   web_view_impl->DidEnterFullscreen();
   web_view_impl->UpdateAllLifecyclePhases();
@@ -2377,7 +2377,7 @@
   Element* element = frame->GetDocument()->getElementById("fullscreenElement");
   ASSERT_TRUE(element);
   std::unique_ptr<UserGestureIndicator> gesture =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
   Fullscreen::RequestFullscreen(*element);
   web_view_impl->DidEnterFullscreen();
   web_view_impl->UpdateAllLifecyclePhases();
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
index c3c6c4f..c24553a 100644
--- a/third_party/blink/renderer/core/frame/frame.cc
+++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -188,11 +188,6 @@
     node->user_activation_state_.Activate();
 }
 
-void Frame::NotifyUserActivation() {
-  ToLocalFrame(this)->Client()->NotifyUserActivation();
-  NotifyUserActivationInLocalTree();
-}
-
 bool Frame::ConsumeTransientUserActivationInLocalTree() {
   bool was_active = user_activation_state_.IsActive();
 
@@ -206,57 +201,6 @@
   return was_active;
 }
 
-bool Frame::ConsumeTransientUserActivation(
-    UserActivationUpdateSource update_source) {
-  if (update_source == UserActivationUpdateSource::kRenderer)
-    ToLocalFrame(this)->Client()->ConsumeUserActivation();
-  return ConsumeTransientUserActivationInLocalTree();
-}
-
-// static
-std::unique_ptr<UserGestureIndicator> Frame::NotifyUserActivation(
-    LocalFrame* frame,
-    UserGestureToken::Status status) {
-  if (frame)
-    frame->NotifyUserActivation();
-  return std::make_unique<UserGestureIndicator>(status);
-}
-
-// static
-std::unique_ptr<UserGestureIndicator> Frame::NotifyUserActivation(
-    LocalFrame* frame,
-    UserGestureToken* token) {
-  if (frame)
-    frame->NotifyUserActivation();
-  return std::make_unique<UserGestureIndicator>(token);
-}
-
-// static
-bool Frame::HasTransientUserActivation(LocalFrame* frame,
-                                       bool checkIfMainThread) {
-  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
-    return frame ? frame->HasTransientUserActivation() : false;
-  }
-
-  return checkIfMainThread
-             ? UserGestureIndicator::ProcessingUserGestureThreadSafe()
-             : UserGestureIndicator::ProcessingUserGesture();
-}
-
-// static
-bool Frame::ConsumeTransientUserActivation(
-    LocalFrame* frame,
-    bool checkIfMainThread,
-    UserActivationUpdateSource update_source) {
-  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
-    return frame ? frame->ConsumeTransientUserActivation(update_source) : false;
-  }
-
-  return checkIfMainThread
-             ? UserGestureIndicator::ConsumeUserGestureThreadSafe()
-             : UserGestureIndicator::ConsumeUserGesture();
-}
-
 bool Frame::DeprecatedIsFeatureEnabled(
     mojom::FeaturePolicyFeature feature) const {
   return GetSecurityContext()->IsFeatureEnabled(feature,
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h
index ac602f8..036e509 100644
--- a/third_party/blink/renderer/core/frame/frame.h
+++ b/third_party/blink/renderer/core/frame/frame.h
@@ -185,41 +185,6 @@
     return has_received_user_gesture_before_nav_;
   }
 
-  // Creates a |UserGestureIndicator| that contains a |UserGestureToken| with
-  // the given status.  Also activates the user activation state of the
-  // |LocalFrame| (provided it's non-null) and all its ancestors.
-  //
-  // TODO(mustaq): Move the user activation entry-points to LocalFrame.
-  static std::unique_ptr<UserGestureIndicator> NotifyUserActivation(
-      LocalFrame*,
-      UserGestureToken::Status = UserGestureToken::kPossiblyExistingGesture);
-  static std::unique_ptr<UserGestureIndicator> NotifyUserActivation(
-      LocalFrame*,
-      UserGestureToken*);
-
-  // Returns the transient user activation state of the |LocalFrame|, provided
-  // it is non-null.  Otherwise returns |false|.
-  //
-  // The |checkIfMainThread| parameter determines if the token based gestures
-  // (legacy code) must be used in a thread-safe manner.
-  //
-  // TODO(mustaq): clarify/enforce the relation between the two params after
-  // null-frame main-thread cases (crbug.com/730690) have been removed.
-  static bool HasTransientUserActivation(LocalFrame*,
-                                         bool checkIfMainThread = false);
-
-  // Consumes the transient user activation state of the |LocalFrame|, provided
-  // the frame pointer is non-null and the state hasn't been consumed since
-  // activation.  Returns |true| if succesfully consumed the state.
-  //
-  // The |checkIfMainThread| parameter determines if the token based gestures
-  // (legacy code) must be used in a thread-safe manner.
-  static bool ConsumeTransientUserActivation(
-      LocalFrame*,
-      bool checkIfMainThread = false,
-      UserActivationUpdateSource update_source =
-          UserActivationUpdateSource::kRenderer);
-
   bool IsAttached() const {
     return lifecycle_.GetState() == FrameLifecycle::kAttached;
   }
@@ -291,7 +256,6 @@
 
   bool has_received_user_gesture_before_nav_ = false;
 
-
   // This is set to true if this is a subframe, and the frame element in the
   // parent frame's document becomes inert. This should always be false for
   // the main frame.
@@ -300,20 +264,6 @@
   TouchAction inherited_effective_touch_action_ = TouchAction::kTouchActionAuto;
 
  private:
-  // Activates the user activation state of this frame and all its ancestors.
-  //
-  // TODO(mustaq): Move the user activation (private) entry-points to
-  // LocalFrame.
-  void NotifyUserActivation();
-
-  bool HasTransientUserActivation() {
-    return user_activation_state_.IsActive();
-  }
-
-  // Consumes and returns the transient user activation of current Frame, after
-  // updating all ancestor/descendant frames.
-  bool ConsumeTransientUserActivation(UserActivationUpdateSource update_source);
-
   Member<FrameClient> client_;
   const Member<WindowProxyManager> window_proxy_manager_;
   FrameLifecycle lifecycle_;
diff --git a/third_party/blink/renderer/core/frame/frame_test.cc b/third_party/blink/renderer/core/frame/frame_test.cc
index 5de0224..e3b394a 100644
--- a/third_party/blink/renderer/core/frame/frame_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_test.cc
@@ -53,7 +53,7 @@
 TEST_F(FrameTest, NoGesture) {
   // A nullptr LocalFrame* will not set user gesture state.
   std::unique_ptr<UserGestureIndicator> holder =
-      Frame::NotifyUserActivation(nullptr);
+      LocalFrame::NotifyUserActivation(nullptr);
   EXPECT_FALSE(GetDocument().GetFrame()->HasBeenActivated());
 }
 
@@ -62,26 +62,27 @@
   // token will not override it.
   {
     std::unique_ptr<UserGestureIndicator> holder =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
   }
   {
     std::unique_ptr<UserGestureIndicator> holder =
-        Frame::NotifyUserActivation(nullptr);
+        LocalFrame::NotifyUserActivation(nullptr);
     EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
   }
 }
 
 TEST_F(FrameTest, NewGesture) {
   // UserGestureToken::Status doesn't impact Document gesture state.
-  std::unique_ptr<UserGestureIndicator> holder = Frame::NotifyUserActivation(
-      GetDocument().GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> holder =
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
 }
 
 TEST_F(FrameTest, NavigateDifferentDomain) {
   std::unique_ptr<UserGestureIndicator> holder =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
   EXPECT_FALSE(
       GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation());
@@ -96,7 +97,7 @@
 
 TEST_F(FrameTest, NavigateSameDomainMultipleTimes) {
   std::unique_ptr<UserGestureIndicator> holder =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
   EXPECT_FALSE(
       GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation());
@@ -132,7 +133,7 @@
 
 TEST_F(FrameTest, NavigateSameDomainDifferentDomain) {
   std::unique_ptr<UserGestureIndicator> holder =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
   EXPECT_FALSE(
       GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation());
@@ -168,19 +169,23 @@
 
   // Initially both sticky and transient bits are false.
   EXPECT_FALSE(GetDocument().GetFrame()->HasBeenActivated());
-  EXPECT_FALSE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+  EXPECT_FALSE(
+      LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
 
-  Frame::NotifyUserActivation(GetDocument().GetFrame());
+  LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
 
   // Now both sticky and transient bits are true, hence consumable.
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
-  EXPECT_TRUE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
-  EXPECT_TRUE(Frame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
+  EXPECT_TRUE(LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
+  EXPECT_TRUE(
+      LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
 
   // After consumption, only the transient bit resets to false.
   EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
-  EXPECT_FALSE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
-  EXPECT_FALSE(Frame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
+  EXPECT_FALSE(
+      LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
+  EXPECT_FALSE(
+      LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 8296c76..43bc62d2 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -54,6 +54,7 @@
 #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
 #include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
 #include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
+#include "third_party/blink/renderer/core/dom/scripted_task_queue_controller.h"
 #include "third_party/blink/renderer/core/dom/sink_document.h"
 #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
@@ -625,7 +626,7 @@
   if (!RuntimeEnabledFeatures::UserActivationV2Enabled() && token &&
       token->HasGestures() && document()) {
     gesture_indicator =
-        Frame::NotifyUserActivation(document()->GetFrame(), token);
+        LocalFrame::NotifyUserActivation(document()->GetFrame(), token);
   }
 
   event->EntangleMessagePorts(document());
@@ -1044,6 +1045,13 @@
   return promise;
 }
 
+ScriptedTaskQueueController* LocalDOMWindow::taskQueue() const {
+  if (Document* document = this->document()) {
+    return ScriptedTaskQueueController::From(*document);
+  }
+  return nullptr;
+}
+
 double LocalDOMWindow::devicePixelRatio() const {
   if (!GetFrame())
     return 0.0;
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 8fa54f3d..8043f0b 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -62,6 +62,7 @@
 class Navigator;
 class PostMessageTimer;
 class Screen;
+class ScriptedTaskQueueController;
 class ScriptPromise;
 class ScriptState;
 class ScrollToOptions;
@@ -220,6 +221,8 @@
   // Acessibility Object Model
   ScriptPromise getComputedAccessibleNode(ScriptState*, Element*);
 
+  ScriptedTaskQueueController* taskQueue() const;
+
   // WebKit animation extensions
   int requestAnimationFrame(V8FrameRequestCallback*);
   int webkitRequestAnimationFrame(V8FrameRequestCallback*);
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index e25ac44..3ca32dc 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1040,7 +1040,7 @@
   // Navigating window.opener cross origin, without user activation. See
   // crbug.com/813643.
   if (Client()->Opener() == target_frame &&
-      !HasTransientUserActivation(this, false /* checkIfMainThread */) &&
+      !HasTransientUserActivation(this, false /* check_if_main_thread */) &&
       !target_frame.GetSecurityContext()->GetSecurityOrigin()->CanAccess(
           SecurityOrigin::Create(destination_url).get())) {
     UseCounter::Count(this, WebFeature::kOpenerNavigationWithoutGesture);
@@ -1121,7 +1121,7 @@
       if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) &&
           !GetSecurityContext()->IsSandboxed(
               kSandboxTopNavigationByUserActivation) &&
-          !Frame::HasTransientUserActivation(this)) {
+          !LocalFrame::HasTransientUserActivation(this)) {
         // With only 'allow-top-navigation-by-user-activation' (but not
         // 'allow-top-navigation'), top navigation requires a user gesture.
         reason =
@@ -1448,4 +1448,65 @@
   GetSecurityContext()->ReportFeaturePolicyViolation(feature);
 }
 
+// static
+std::unique_ptr<UserGestureIndicator> LocalFrame::NotifyUserActivation(
+    LocalFrame* frame,
+    UserGestureToken::Status status) {
+  if (frame)
+    frame->NotifyUserActivation();
+  return std::make_unique<UserGestureIndicator>(status);
+}
+
+// static
+std::unique_ptr<UserGestureIndicator> LocalFrame::NotifyUserActivation(
+    LocalFrame* frame,
+    UserGestureToken* token) {
+  DCHECK(!RuntimeEnabledFeatures::UserActivationV2Enabled());
+  if (frame)
+    frame->NotifyUserActivation();
+  return std::make_unique<UserGestureIndicator>(token);
+}
+
+// static
+bool LocalFrame::HasTransientUserActivation(LocalFrame* frame,
+                                            bool check_if_main_thread) {
+  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
+    return frame ? frame->HasTransientUserActivation() : false;
+  }
+
+  return check_if_main_thread
+             ? UserGestureIndicator::ProcessingUserGestureThreadSafe()
+             : UserGestureIndicator::ProcessingUserGesture();
+}
+
+// static
+bool LocalFrame::ConsumeTransientUserActivation(
+    LocalFrame* frame,
+    bool check_if_main_thread,
+    UserActivationUpdateSource update_source) {
+  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
+    return frame ? frame->ConsumeTransientUserActivation(update_source) : false;
+  }
+
+  return check_if_main_thread
+             ? UserGestureIndicator::ConsumeUserGestureThreadSafe()
+             : UserGestureIndicator::ConsumeUserGesture();
+}
+
+void LocalFrame::NotifyUserActivation() {
+  Client()->NotifyUserActivation();
+  NotifyUserActivationInLocalTree();
+}
+
+bool LocalFrame::HasTransientUserActivation() {
+  return user_activation_state_.IsActive();
+}
+
+bool LocalFrame::ConsumeTransientUserActivation(
+    UserActivationUpdateSource update_source) {
+  if (update_source == UserActivationUpdateSource::kRenderer)
+    Client()->ConsumeUserActivation();
+  return ConsumeTransientUserActivationInLocalTree();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index f83a473d..4b52f9e 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -198,6 +198,38 @@
   CoreProbeSink* GetProbeSink() { return probe_sink_.Get(); }
   scoped_refptr<InspectorTaskRunner> GetInspectorTaskRunner();
 
+  // Activates the user activation states of the |LocalFrame| (provided it's
+  // non-null) and all its ancestors.  Also creates a |UserGestureIndicator|
+  // that contains a |UserGestureToken| with the given status.
+  static std::unique_ptr<UserGestureIndicator> NotifyUserActivation(
+      LocalFrame*,
+      UserGestureToken::Status = UserGestureToken::kPossiblyExistingGesture);
+
+  // Similar to above, but used only in old UAv1-specific code.
+  static std::unique_ptr<UserGestureIndicator> NotifyUserActivation(
+      LocalFrame*,
+      UserGestureToken*);
+
+  // Returns the transient user activation state of the |LocalFrame|, provided
+  // it is non-null.  Otherwise returns |false|.
+  //
+  // The |check_if_main_thread| parameter determines if the token based gestures
+  // (legacy UAv1 code) must be used in a thread-safe manner.
+  static bool HasTransientUserActivation(LocalFrame*,
+                                         bool check_if_main_thread = false);
+
+  // Consumes the transient user activation state of the |LocalFrame|, provided
+  // the frame pointer is non-null and the state hasn't been consumed since
+  // activation.  Returns |true| if successfully consumed the state.
+  //
+  // The |check_if_main_thread| parameter determines if the token based gestures
+  // (legacy code) must be used in a thread-safe manner.
+  static bool ConsumeTransientUserActivation(
+      LocalFrame*,
+      bool check_if_main_thread = false,
+      UserActivationUpdateSource update_source =
+          UserActivationUpdateSource::kRenderer);
+
   // =========================================================================
   // All public functions below this point are candidates to move out of
   // LocalFrame into another class.
@@ -413,6 +445,16 @@
   ukm::UkmRecorder* GetUkmRecorder() override;
   ukm::SourceId GetUkmSourceId() override;
 
+  // Activates the user activation states of this frame and all its ancestors.
+  void NotifyUserActivation();
+
+  // Returns the transient user activation state of this frame
+  bool HasTransientUserActivation();
+
+  // Consumes and returns the transient user activation state of this frame,
+  // after updating all ancestor/descendant frames.
+  bool ConsumeTransientUserActivation(UserActivationUpdateSource update_source);
+
   std::unique_ptr<FrameScheduler> frame_scheduler_;
 
   // Holds all PauseSubresourceLoadingHandles allowing either |this| to delete
diff --git a/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
index 980585a..04828c64 100644
--- a/third_party/blink/renderer/core/frame/pausable_script_executor.cc
+++ b/third_party/blink/renderer/core/frame/pausable_script_executor.cc
@@ -54,7 +54,7 @@
   std::unique_ptr<UserGestureIndicator> indicator;
   if (user_gesture_) {
     indicator =
-        Frame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+        LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
   }
 
   Vector<v8::Local<v8::Value>> results;
diff --git a/third_party/blink/renderer/core/frame/user_activation.cc b/third_party/blink/renderer/core/frame/user_activation.cc
index 8aaaacc2..5d575f1 100644
--- a/third_party/blink/renderer/core/frame/user_activation.cc
+++ b/third_party/blink/renderer/core/frame/user_activation.cc
@@ -11,7 +11,7 @@
 UserActivation* UserActivation::CreateSnapshot(LocalDOMWindow* window) {
   LocalFrame* frame = window->GetFrame();
   return new UserActivation(frame ? frame->HasBeenActivated() : false,
-                            Frame::HasTransientUserActivation(frame));
+                            LocalFrame::HasTransientUserActivation(frame));
 }
 
 UserActivation* UserActivation::CreateLive(LocalDOMWindow* window) {
@@ -41,7 +41,7 @@
   LocalFrame* frame = window_ ? window_->GetFrame() : nullptr;
   if (!frame)
     return is_active_;
-  return Frame::HasTransientUserActivation(frame);
+  return LocalFrame::HasTransientUserActivation(frame);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index 587d396..6504ff5 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -67,6 +67,13 @@
   return local_root_;
 }
 
+void WebFrameWidgetBase::UpdateAllLifecyclePhasesAndCompositeForTesting(
+    bool do_raster) {
+  if (WebLayerTreeView* layer_tree_view = GetLayerTreeView()) {
+    layer_tree_view->UpdateAllLifecyclePhasesAndCompositeForTesting(do_raster);
+  }
+}
+
 WebDragOperation WebFrameWidgetBase::DragTargetDragEnter(
     const WebDragData& web_drag_data,
     const WebFloatPoint& point_in_viewport,
@@ -187,11 +194,6 @@
   CancelDrag();
 }
 
-void WebFrameWidgetBase::CompositeWithRasterForTesting() {
-  if (auto* layer_tree_view = GetLayerTreeView())
-    layer_tree_view->CompositeWithRasterForTesting();
-}
-
 void WebFrameWidgetBase::CancelDrag() {
   // It's possible for us this to be callback while we're not doing a drag if
   // it's from a previous page that got unloaded.
@@ -319,12 +321,12 @@
       if (!GetPage() || !GetPage()->GetPointerLockController().GetElement())
         break;
       gesture_indicator =
-          Frame::NotifyUserActivation(GetPage()
-                                          ->GetPointerLockController()
-                                          .GetElement()
-                                          ->GetDocument()
-                                          .GetFrame(),
-                                      UserGestureToken::kNewGesture);
+          LocalFrame::NotifyUserActivation(GetPage()
+                                               ->GetPointerLockController()
+                                               .GetElement()
+                                               ->GetDocument()
+                                               .GetFrame(),
+                                           UserGestureToken::kNewGesture);
       pointer_lock_gesture_token_ = gesture_indicator->CurrentToken();
       break;
     case WebInputEvent::kMouseUp:
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index 2c096d0..cd1feac9 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -71,6 +71,7 @@
   // WebFrameWidget implementation.
   void Close() override;
   WebLocalFrame* LocalRoot() const override;
+  void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override;
   WebDragOperation DragTargetDragEnter(const WebDragData&,
                                        const WebFloatPoint& point_in_viewport,
                                        const WebFloatPoint& screen_point,
@@ -90,7 +91,6 @@
                          const WebFloatPoint& screen_point,
                          WebDragOperation) override;
   void DragSourceSystemDragEnded() override;
-  void CompositeWithRasterForTesting() override;
 
   WebLocalFrame* FocusedWebLocalFrameInWidget() const override;
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index eeee21c..293bc24 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -315,11 +315,6 @@
   UpdateLayerTreeBackgroundColor();
 }
 
-void WebFrameWidgetImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() {
-  if (layer_tree_view_)
-    layer_tree_view_->SynchronouslyCompositeNoRasterForTesting();
-}
-
 void WebFrameWidgetImpl::PaintContent(cc::PaintCanvas* canvas,
                                       const WebRect& rect) {
   // Out-of-process iframes require compositing.
@@ -489,7 +484,7 @@
         break;
       case WebInputEvent::kMouseDown:
         event_type = EventTypeNames::mousedown;
-        gesture_indicator = Frame::NotifyUserActivation(
+        gesture_indicator = LocalFrame::NotifyUserActivation(
             node->GetDocument().GetFrame(), UserGestureToken::kNewGesture);
         mouse_capture_gesture_token_ = gesture_indicator->CurrentToken();
         break;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index a2a5d40..d1c25b14 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -84,7 +84,6 @@
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
   void BeginFrame(base::TimeTicks last_frame_time) override;
   void UpdateLifecycle(LifecycleUpdate requested_update) override;
-  void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
   void PaintContent(cc::PaintCanvas*, const WebRect&) override;
   void LayoutAndPaintAsync(base::OnceClosure callback) override;
   void CompositeAndReadbackAsync(
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 690a3bf..76b761b0 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1093,7 +1093,8 @@
     plugin_lookup_context_node = ContextMenuNodeInner();
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   WebPluginContainerImpl* plugin_container =
       GetFrame()->GetWebPluginContainer(plugin_lookup_context_node);
@@ -1108,7 +1109,8 @@
   DCHECK(GetFrame());
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   WebPluginContainerImpl* plugin_container =
       GetFrame()->GetWebPluginContainer();
@@ -2109,7 +2111,8 @@
       static_cast<const KURL&>(url).GetString().Substring(
           strlen("javascript:")));
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetFrame(),
+                                       UserGestureToken::kNewGesture);
   v8::HandleScope handle_scope(ToIsolate(GetFrame()));
   v8::Local<v8::Value> result =
       GetFrame()->GetScriptController().ExecuteScriptInMainWorldAndReturnValue(
@@ -2223,7 +2226,7 @@
 }
 
 void WebLocalFrameImpl::NotifyUserActivation() {
-  Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+  LocalFrame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
 }
 
 void WebLocalFrameImpl::BlinkFeatureUsageReport(const std::set<int>& features) {
@@ -2296,7 +2299,7 @@
   // gesture usage by chaining postMessages across multiple processes.
   std::unique_ptr<UserGestureIndicator> gesture_indicator;
   if (!RuntimeEnabledFeatures::UserActivationV2Enabled() && has_user_gesture) {
-    gesture_indicator = Frame::NotifyUserActivation(GetFrame());
+    gesture_indicator = LocalFrame::NotifyUserActivation(GetFrame());
     UserGestureIndicator::SetWasForwardedCrossProcess();
   }
 
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 27558a3..49442002 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -71,10 +71,6 @@
   web_view_->UpdateLifecycle(requested_update);
 }
 
-void WebViewFrameWidget::UpdateAllLifecyclePhasesAndCompositeForTesting() {
-  web_view_->UpdateAllLifecyclePhasesAndCompositeForTesting();
-}
-
 void WebViewFrameWidget::PaintContent(cc::PaintCanvas* canvas,
                                       const WebRect& view_port) {
   web_view_->PaintContent(canvas, view_port);
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 1659cf7e..08d8b29 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -50,7 +50,6 @@
   void BeginFrame(base::TimeTicks last_frame_time) override;
   void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
   void UpdateLifecycle(LifecycleUpdate requested_update) override;
-  void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
   void PaintContent(cc::PaintCanvas*, const WebRect& view_port) override;
   void LayoutAndPaintAsync(base::OnceClosure callback) override;
   void CompositeAndReadbackAsync(
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl
index 57211eb6..b142a293c 100644
--- a/third_party/blink/renderer/core/frame/window.idl
+++ b/third_party/blink/renderer/core/frame/window.idl
@@ -129,6 +129,8 @@
     [NewObject] MediaQueryList matchMedia(DOMString query);
     [SameObject, Replaceable] readonly attribute Screen screen;
 
+    [RuntimeEnabled=WorkerTaskQueue, SameObject, Replaceable] readonly attribute ScriptedTaskQueueController TaskQueue;
+
     // browsing context
     void moveTo(long x, long y);
     void moveBy(long x, long y);
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 31ee757..a3699bd 100644
--- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -225,7 +225,7 @@
   // true:
 
   //  The algorithm is triggered by a user activation.
-  if (Frame::HasTransientUserActivation(document.GetFrame()))
+  if (LocalFrame::HasTransientUserActivation(document.GetFrame()))
     return true;
 
   //  The algorithm is triggered by a user generated orientation change.
diff --git a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
index 74db3c1..a20f301 100644
--- a/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
+++ b/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
@@ -62,7 +62,7 @@
 void ChooserOnlyTemporalInputTypeView::HandleDOMActivateEvent(Event& event) {
   Document& document = GetElement().GetDocument();
   if (GetElement().IsDisabledOrReadOnly() || !GetElement().GetLayoutObject() ||
-      !Frame::HasTransientUserActivation(document.GetFrame()) ||
+      !LocalFrame::HasTransientUserActivation(document.GetFrame()) ||
       GetElement().OpenShadowRoot())
     return;
 
diff --git a/third_party/blink/renderer/core/html/forms/color_input_type.cc b/third_party/blink/renderer/core/html/forms/color_input_type.cc
index ad33b11e..020384bc 100644
--- a/third_party/blink/renderer/core/html/forms/color_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/color_input_type.cc
@@ -150,7 +150,7 @@
     return;
 
   Document& document = GetElement().GetDocument();
-  if (!Frame::HasTransientUserActivation(document.GetFrame()))
+  if (!LocalFrame::HasTransientUserActivation(document.GetFrame()))
     return;
 
   ChromeClient* chrome_client = GetChromeClient();
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 794ec67..c6210186 100644
--- a/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -149,7 +149,8 @@
   if (GetElement().IsDisabledFormControl())
     return;
 
-  if (!Frame::HasTransientUserActivation(GetElement().GetDocument().GetFrame()))
+  if (!LocalFrame::HasTransientUserActivation(
+          GetElement().GetDocument().GetFrame()))
     return;
 
   if (ChromeClient* chrome_client = GetChromeClient()) {
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc
index 1316705..06846322 100644
--- a/third_party/blink/renderer/core/html/forms/html_form_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -487,7 +487,7 @@
     FrameLoadRequest frame_load_request =
         submission->CreateFrameLoadRequest(&GetDocument());
     frame_load_request.GetResourceRequest().SetHasUserGesture(
-        Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+        LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
     // TODO(dgozman): we lose information about triggering event and desired
     // navigation policy here.
     ToRemoteFrame(target_frame)->Navigate(frame_load_request);
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc
index 464037d..833ea0c 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -1065,7 +1065,7 @@
 
   NotifyFormStateChanged();
 
-  if (Frame::HasTransientUserActivation(GetDocument().GetFrame()) &&
+  if (LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()) &&
       GetDocument().IsActive()) {
     GetDocument()
         .GetPage()
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
index c06cabb4..f80b533 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -299,7 +299,8 @@
 }
 
 base::Optional<DOMExceptionCode> AutoplayPolicy::RequestPlay() {
-  if (!Frame::HasTransientUserActivation(element_->GetDocument().GetFrame())) {
+  if (!LocalFrame::HasTransientUserActivation(
+          element_->GetDocument().GetFrame())) {
     autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kMethod);
     if (IsGestureNeededForPlayback()) {
       autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
@@ -350,8 +351,8 @@
 }
 
 void AutoplayPolicy::TryUnlockingUserGesture() {
-  if (IsLockedPendingUserGesture() &&
-      Frame::HasTransientUserActivation(element_->GetDocument().GetFrame())) {
+  if (IsLockedPendingUserGesture() && LocalFrame::HasTransientUserActivation(
+                                          element_->GetDocument().GetFrame())) {
     UnlockUserGesture();
   }
 }
diff --git a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
index 5f71c91..4c15dda 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
@@ -39,7 +39,7 @@
 
   int64_t result = 0;
 
-  if (Frame::HasTransientUserActivation(frame, false))
+  if (LocalFrame::HasTransientUserActivation(frame, false))
     result |= 0x01;
   if (frame->HasBeenActivated())
     result |= 0x02;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
index 93c16ae..040bd9c 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
@@ -205,7 +205,7 @@
   EXPECT_NE(Video(), nullptr);
   SimulateReadyState(HTMLMediaElement::kHaveMetadata);
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*Video());
   Fullscreen::DidEnterFullscreen(GetDocument());
 
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
index bd081d81..5c9b880 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -317,7 +317,7 @@
   RuntimeEnabledFeatures::SetMediaEngagementBypassAutoplayPoliciesEnabled(true);
   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
       AutoplayPolicy::Type::kDocumentUserActivationRequired);
-  Frame::NotifyUserActivation(Media()->GetDocument().GetFrame());
+  LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
 
   Media()->Play();
 
@@ -334,7 +334,7 @@
   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
       AutoplayPolicy::Type::kDocumentUserActivationRequired);
   SimulateHighMediaEngagement();
-  Frame::NotifyUserActivation(Media()->GetDocument().GetFrame());
+  LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
 
   Media()->Play();
 
@@ -364,7 +364,7 @@
   // - MEI doesn't matter as it's not used by the policy.
   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
       AutoplayPolicy::Type::kUserGestureRequired);
-  Frame::NotifyUserActivation(Media()->GetDocument().GetFrame());
+  LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
 
   Media()->Play();
 
@@ -378,7 +378,7 @@
   // - MEI doesn't matter as it's not used by the policy.
   Media()->GetDocument().GetSettings()->SetAutoplayPolicy(
       AutoplayPolicy::Type::kNoUserGestureRequired);
-  Frame::NotifyUserActivation(Media()->GetDocument().GetFrame());
+  LocalFrame::NotifyUserActivation(Media()->GetDocument().GetFrame());
 
   Media()->Play();
 
diff --git a/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc b/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
index 7efa11b..cf2a9aa 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
@@ -102,7 +102,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(0);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*VideoElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), VideoElement());
@@ -129,7 +129,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(0);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
@@ -163,7 +163,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(1);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
@@ -209,7 +209,7 @@
   exception_state.ClearException();
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   SimulateBecamePersistentVideo(true);
@@ -242,7 +242,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(1);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
@@ -264,7 +264,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(0);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
@@ -290,7 +290,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(0);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
@@ -312,7 +312,7 @@
   EXPECT_CALL(GetMockChromeClient(), ExitFullscreen(_)).Times(0);
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(GetDocument().GetFrame());
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   Fullscreen::RequestFullscreen(*DivElement());
   SimulateDidEnterFullscreen();
   EXPECT_EQ(FullscreenElement(), DivElement());
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index 4f695be4..085a823 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -651,7 +651,7 @@
   }
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(frame_);
+      LocalFrame::NotifyUserActivation(frame_);
   frame_->LocalFrameRoot()
       .GetEventHandler()
       .last_mouse_down_user_gesture_token_ =
@@ -1046,7 +1046,7 @@
                       .GetEventHandler()
                       .last_mouse_down_user_gesture_token_));
   } else {
-    gesture_indicator = Frame::NotifyUserActivation(frame_);
+    gesture_indicator = LocalFrame::NotifyUserActivation(frame_);
   }
 
   WebInputEventResult event_result = DispatchMousePointerEvent(
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index 6f7d66c4..83a2ff8 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -206,7 +206,7 @@
   Node* tapped_node = current_hit_test.InnerNode();
   Element* tapped_element = current_hit_test.InnerElement();
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(
+      LocalFrame::NotifyUserActivation(
           tapped_node ? tapped_node->GetDocument().GetFrame() : nullptr);
 
   mouse_event_manager_->SetClickElement(tapped_element);
@@ -361,7 +361,7 @@
   }
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(
+      LocalFrame::NotifyUserActivation(
           inner_node ? inner_node->GetDocument().GetFrame() : nullptr);
   return SendContextMenuEventForGesture(targeted_event);
 }
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index 4d9cb5a..f39d657 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -199,7 +199,7 @@
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator;
   if (!is_modifier)
-    gesture_indicator = Frame::NotifyUserActivation(frame_);
+    gesture_indicator = LocalFrame::NotifyUserActivation(frame_);
 
   // In IE, access keys are special, they are handled after default keydown
   // processing, but cannot be canceled - this is hard to match.  On Mac OS X,
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager.cc b/third_party/blink/renderer/core/input/pointer_event_manager.cc
index 94806693..2faa7369 100644
--- a/third_party/blink/renderer/core/input/pointer_event_manager.cc
+++ b/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -554,7 +554,7 @@
   if (event.GetType() == WebInputEvent::kPointerUp &&
       !non_hovering_pointers_canceled_ && pointer_event_target.target_frame) {
     user_gesture_holder_ =
-        Frame::NotifyUserActivation(pointer_event_target.target_frame);
+        LocalFrame::NotifyUserActivation(pointer_event_target.target_frame);
   }
 
   WebInputEventResult result =
diff --git a/third_party/blink/renderer/core/inspector/dev_tools_host.cc b/third_party/blink/renderer/core/inspector/dev_tools_host.cc
index ccd906e..c7c1687 100644
--- a/third_party/blink/renderer/core/inspector/dev_tools_host.cc
+++ b/third_party/blink/renderer/core/inspector/dev_tools_host.cc
@@ -134,7 +134,7 @@
     return;
   ScriptState::Scope scope(script_state);
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(frontend_frame_);
+      LocalFrame::NotifyUserActivation(frontend_frame_);
   v8::MicrotasksScope microtasks(script_state->GetIsolate(),
                                  v8::MicrotasksScope::kRunMicrotasks);
   ScriptSourceCode source_code(expression, ScriptSourceLocationType::kInternal,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
index 61f68b3..02842569 100644
--- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -72,6 +72,13 @@
   return value;
 }
 
+std::unique_ptr<TracedValue> GetNavigationTracingData(Document* document) {
+  std::unique_ptr<TracedValue> data = TracedValue::Create();
+
+  data->SetString("navigationId",
+                  IdentifiersFactory::LoaderId(document->Loader()));
+  return data;
+}
 }  //  namespace
 
 String ToHexString(const void* p) {
@@ -204,9 +211,10 @@
 void InspectorTraceEvents::PaintTiming(Document* document,
                                        const char* name,
                                        double timestamp) {
-  TRACE_EVENT_MARK_WITH_TIMESTAMP1("loading,rail,devtools.timeline", name,
+  TRACE_EVENT_MARK_WITH_TIMESTAMP2("loading,rail,devtools.timeline", name,
                                    TraceEvent::ToTraceTimestamp(timestamp),
-                                   "frame", ToTraceValue(document->GetFrame()));
+                                   "frame", ToTraceValue(document->GetFrame()),
+                                   "data", GetNavigationTracingData(document));
 }
 
 void InspectorTraceEvents::FrameStartedLoading(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/inspector/thread_debugger.cc b/third_party/blink/renderer/core/inspector/thread_debugger.cc
index 4781c23..fb403af 100644
--- a/third_party/blink/renderer/core/inspector/thread_debugger.cc
+++ b/third_party/blink/renderer/core/inspector/thread_debugger.cc
@@ -154,8 +154,8 @@
 void ThreadDebugger::beginUserGesture() {
   ExecutionContext* ec = CurrentExecutionContext(isolate_);
   Document* document = ec && ec->IsDocument() ? ToDocument(ec) : nullptr;
-  user_gesture_indicator_ =
-      Frame::NotifyUserActivation(document ? document->GetFrame() : nullptr);
+  user_gesture_indicator_ = LocalFrame::NotifyUserActivation(
+      document ? document->GetFrame() : nullptr);
 }
 
 void ThreadDebugger::endUserGesture() {
diff --git a/third_party/blink/renderer/core/loader/document_load_timing.cc b/third_party/blink/renderer/core/loader/document_load_timing.cc
index 5ad8548e..44c0f18 100644
--- a/third_party/blink/renderer/core/loader/document_load_timing.cc
+++ b/third_party/blink/renderer/core/loader/document_load_timing.cc
@@ -27,6 +27,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -99,6 +100,8 @@
                   document_loader_ ? document_loader_->Url().GetString() : "");
   data->SetBoolean("isLoadingMainFrame",
                    GetFrame() ? GetFrame()->IsMainFrame() : false);
+  data->SetString("navigationId",
+                  IdentifiersFactory::LoaderId(document_loader_));
   return data;
 }
 
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 7736b13..158596fe 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -991,8 +991,14 @@
 
   if (ShouldSendClientHint(mojom::WebClientHintsType::kRtt, hints_preferences,
                            enabled_hints)) {
-    unsigned long rtt = GetNetworkStateNotifier().RoundRtt(
-        request.Url().Host(), GetNetworkStateNotifier().HttpRtt());
+    base::Optional<TimeDelta> http_rtt =
+        GetNetworkStateNotifier().GetWebHoldbackHttpRtt();
+    if (!http_rtt) {
+      http_rtt = GetNetworkStateNotifier().HttpRtt();
+    }
+
+    unsigned long rtt =
+        GetNetworkStateNotifier().RoundRtt(request.Url().Host(), http_rtt);
     request.AddHTTPHeaderField(
         blink::kClientHintsHeaderMapping[static_cast<size_t>(
             mojom::WebClientHintsType::kRtt)],
@@ -1001,9 +1007,14 @@
 
   if (ShouldSendClientHint(mojom::WebClientHintsType::kDownlink,
                            hints_preferences, enabled_hints)) {
-    double mbps = GetNetworkStateNotifier().RoundMbps(
-        request.Url().Host(),
-        GetNetworkStateNotifier().DownlinkThroughputMbps());
+    base::Optional<double> throughput_mbps =
+        GetNetworkStateNotifier().GetWebHoldbackDownlinkThroughputMbps();
+    if (!throughput_mbps) {
+      throughput_mbps = GetNetworkStateNotifier().DownlinkThroughputMbps();
+    }
+
+    double mbps = GetNetworkStateNotifier().RoundMbps(request.Url().Host(),
+                                                      throughput_mbps);
     request.AddHTTPHeaderField(
         blink::kClientHintsHeaderMapping[static_cast<size_t>(
             mojom::WebClientHintsType::kDownlink)],
@@ -1012,11 +1023,16 @@
 
   if (ShouldSendClientHint(mojom::WebClientHintsType::kEct, hints_preferences,
                            enabled_hints)) {
+    base::Optional<WebEffectiveConnectionType> holdback_ect =
+        GetNetworkStateNotifier().GetWebHoldbackEffectiveType();
+    if (!holdback_ect)
+      holdback_ect = GetNetworkStateNotifier().EffectiveType();
+
     request.AddHTTPHeaderField(
         blink::kClientHintsHeaderMapping[static_cast<size_t>(
             mojom::WebClientHintsType::kEct)],
         AtomicString(NetworkStateNotifier::EffectiveConnectionTypeToString(
-            GetNetworkStateNotifier().EffectiveType())));
+            holdback_ect.value())));
   }
 }
 
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index d40b6b4a..d055dba 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -228,7 +228,7 @@
       ClientRedirectPolicy::kNotClientRedirect,
       base::UnguessableToken::Create(), nullptr /* navigation_params */,
       nullptr /* extra_data */);
-  if (Frame::HasTransientUserActivation(frame_))
+  if (LocalFrame::HasTransientUserActivation(frame_))
     provisional_document_loader_->SetHadTransientUserActivation();
   provisional_document_loader_->StartLoading();
 
@@ -780,7 +780,8 @@
   const KURL& url = resource_request.Url();
   Document* origin_document = request.OriginDocument();
 
-  resource_request.SetHasUserGesture(Frame::HasTransientUserActivation(frame_));
+  resource_request.SetHasUserGesture(
+      LocalFrame::HasTransientUserActivation(frame_));
 
   if (!PrepareRequestForThisFrame(request))
     return;
@@ -897,14 +898,15 @@
     return;
   }
 
-  bool has_transient_activation = Frame::HasTransientUserActivation(frame_);
+  bool has_transient_activation =
+      LocalFrame::HasTransientUserActivation(frame_);
   // TODO(csharrison): In M71 when UserActivation v2 should ship, we can remove
   // the check that the pages are equal, because consumption should not be
   // shared across pages. After that, we can also get rid of consumption call
   // in RenderFrameImpl::OpenURL.
   if (frame_->IsMainFrame() && origin_document &&
       frame_->GetPage() == origin_document->GetPage()) {
-    Frame::ConsumeTransientUserActivation(frame_);
+    LocalFrame::ConsumeTransientUserActivation(frame_);
   }
 
   policy = Client()->DecidePolicyForNavigation(
@@ -995,7 +997,8 @@
 
   FrameLoadRequest request(passed_request);
   ResourceRequest& resource_request = request.GetResourceRequest();
-  resource_request.SetHasUserGesture(Frame::HasTransientUserActivation(frame_));
+  resource_request.SetHasUserGesture(
+      LocalFrame::HasTransientUserActivation(frame_));
 
   if (frame_load_type == WebFrameLoadType::kStandard)
     frame_load_type = DetermineFrameLoadType(request);
diff --git a/third_party/blink/renderer/core/loader/image_loader.h b/third_party/blink/renderer/core/loader/image_loader.h
index 10e6da2..6719ef2 100644
--- a/third_party/blink/renderer/core/loader/image_loader.h
+++ b/third_party/blink/renderer/core/loader/image_loader.h
@@ -254,13 +254,10 @@
     enum State { kPendingMicrotask, kPendingLoad, kDispatched };
 
     DecodeRequest(ImageLoader*, ScriptPromiseResolver*);
-    DecodeRequest(DecodeRequest&&) = default;
     ~DecodeRequest() = default;
 
     void Trace(blink::Visitor*);
 
-    DecodeRequest& operator=(DecodeRequest&&) = default;
-
     uint64_t request_id() const { return request_id_; }
     State state() const { return state_; }
     ScriptPromise promise() { return resolver_->Promise(); }
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.cc b/third_party/blink/renderer/core/loader/navigation_scheduler.cc
index 3669988..ba1dd26 100644
--- a/third_party/blink/renderer/core/loader/navigation_scheduler.cc
+++ b/third_party/blink/renderer/core/loader/navigation_scheduler.cc
@@ -383,7 +383,7 @@
   // create a new back/forward item. See https://webkit.org/b/42861 for the
   // original motivation for this.
   if (!target_frame->GetDocument()->LoadEventFinished() &&
-      !Frame::HasTransientUserActivation(target_frame))
+      !LocalFrame::HasTransientUserActivation(target_frame))
     return true;
 
   // Navigation of a subframe during loading of an ancestor frame does not
diff --git a/third_party/blink/renderer/core/loader/scheduled_navigation.cc b/third_party/blink/renderer/core/loader/scheduled_navigation.cc
index 935da8d..6b2b9e5 100644
--- a/third_party/blink/renderer/core/loader/scheduled_navigation.cc
+++ b/third_party/blink/renderer/core/loader/scheduled_navigation.cc
@@ -22,7 +22,7 @@
       origin_document_(origin_document),
       replaces_current_item_(replaces_current_item),
       is_location_change_(is_location_change) {
-  if (Frame::HasTransientUserActivation(
+  if (LocalFrame::HasTransientUserActivation(
           origin_document ? origin_document->GetFrame() : nullptr))
     user_gesture_token_ = UserGestureIndicator::CurrentToken();
 }
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
index 3af72afc..f3ab620 100644
--- a/third_party/blink/renderer/core/page/create_window.cc
+++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -318,7 +318,8 @@
             network::mojom::RequestContextFrameType::kAuxiliary);
   probe::windowOpen(opener_frame.GetDocument(),
                     request.GetResourceRequest().Url(), request.FrameName(),
-                    features, Frame::HasTransientUserActivation(&opener_frame));
+                    features,
+                    LocalFrame::HasTransientUserActivation(&opener_frame));
   created = false;
 
   Frame* window =
@@ -419,7 +420,7 @@
   // Records HasUserGesture before the value is invalidated inside
   // createWindow(LocalFrame& openerFrame, ...).
   // This value will be set in ResourceRequest loaded in a new LocalFrame.
-  bool has_user_gesture = Frame::HasTransientUserActivation(&opener_frame);
+  bool has_user_gesture = LocalFrame::HasTransientUserActivation(&opener_frame);
 
   // We pass the opener frame for the lookupFrame in case the active frame is
   // different from the opener frame, and the name references a frame relative
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index a1d141f..a7c06afc 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -243,9 +243,10 @@
   DCHECK(drag_data);
   document_under_mouse_ =
       local_root.DocumentAtPoint(LayoutPoint(drag_data->ClientPosition()));
-  std::unique_ptr<UserGestureIndicator> gesture = Frame::NotifyUserActivation(
-      document_under_mouse_ ? document_under_mouse_->GetFrame() : nullptr,
-      UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> gesture =
+      LocalFrame::NotifyUserActivation(
+          document_under_mouse_ ? document_under_mouse_->GetFrame() : nullptr,
+          UserGestureToken::kNewGesture);
   if ((drag_destination_action_ & kDragDestinationActionDHTML) &&
       document_is_handling_drag_) {
     bool prevented_default = false;
@@ -296,7 +297,7 @@
       // origin rather than the origin of the dragged data URL?
       resource_request.SetRequestorOrigin(
           SecurityOrigin::Create(KURL(drag_data->AsURL())));
-      resource_request.SetHasUserGesture(Frame::HasTransientUserActivation(
+      resource_request.SetHasUserGesture(LocalFrame::HasTransientUserActivation(
           document_under_mouse_ ? document_under_mouse_->GetFrame() : nullptr));
       page_->MainFrame()->Navigate(FrameLoadRequest(nullptr, resource_request));
     }
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
index a9f19d78..482e7955 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
@@ -44,18 +44,14 @@
     this.element.classList.add('heap-snapshot-view');
     this._profile = profile;
     this._linkifier = new Components.Linkifier();
+    const profileType = profile.profileType();
 
-    profile.profileType().addEventListener(
-        Profiler.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
-    profile.profileType().addEventListener(
-        Profiler.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
+    profileType.addEventListener(Profiler.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
+    profileType.addEventListener(Profiler.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
 
-    const isHeapTimeline = profile.profileType().id === Profiler.TrackingHeapSnapshotProfileType.TypeId;
-    if (isHeapTimeline) {
-      this._trackingOverviewGrid = new Profiler.HeapTimelineOverview(profile);
-      this._trackingOverviewGrid.addEventListener(
-          Profiler.HeapTimelineOverview.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
-    }
+    const isHeapTimeline = profileType.id === Profiler.TrackingHeapSnapshotProfileType.TypeId;
+    if (isHeapTimeline)
+      this._createOverview();
 
     this._parentDataDisplayDelegate = dataDisplayDelegate;
 
@@ -174,6 +170,35 @@
       existingProfile.addEventListener(Profiler.ProfileHeader.Events.ProfileTitleChanged, this._updateControls, this);
   }
 
+  _createOverview() {
+    const profileType = this._profile.profileType();
+    this._trackingOverviewGrid = new Profiler.HeapTimelineOverview();
+    this._trackingOverviewGrid.addEventListener(
+        Profiler.HeapTimelineOverview.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
+    if (!this._profile.fromFile() && profileType.profileBeingRecorded() === this._profile) {
+      profileType.addEventListener(
+          Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
+      profileType.addEventListener(
+          Profiler.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
+    }
+  }
+
+  _onStopTracking() {
+    this._profile.profileType().removeEventListener(
+        Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
+    this._profile.profileType().removeEventListener(
+        Profiler.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
+  }
+
+  /**
+   * @param {!Common.Event} event
+   */
+  _onHeapStatsUpdate(event) {
+    const samples = event.data;
+    if (samples)
+      this._trackingOverviewGrid.setSamples(event.data);
+  }
+
   /**
    * @return {!UI.SearchableView}
    */
@@ -233,7 +258,16 @@
     if (this._profile.profileType().id === Profiler.TrackingHeapSnapshotProfileType.TypeId &&
         this._profile.fromFile()) {
       const samples = await heapSnapshotProxy.getSamples();
-      this._trackingOverviewGrid.setSamples(samples);
+      if (samples) {
+        console.assert(samples.timestamps.length);
+        const profileSamples = new Profiler.HeapTimelineOverview.Samples();
+        profileSamples.sizes = samples.sizes;
+        profileSamples.ids = samples.lastAssignedIds;
+        profileSamples.timestamps = samples.timestamps;
+        profileSamples.max = samples.sizes;
+        profileSamples.totalTime = Math.max(samples.timestamps.peekLast(), 10000);
+        this._trackingOverviewGrid.setSamples(profileSamples);
+      }
     }
 
     const list = this._profiles();
@@ -709,8 +743,11 @@
       this._allocationStackView.clear();
       this._allocationDataGrid.dispose();
     }
-    if (this._trackingOverviewGrid)
-      this._trackingOverviewGrid.dispose();
+    this._onStopTracking();
+    if (this._trackingOverviewGrid) {
+      this._trackingOverviewGrid.removeEventListener(
+          Profiler.HeapTimelineOverview.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
+    }
   }
 };
 
@@ -1242,7 +1279,7 @@
     if (!heapProfilerModel)
       return null;
     this.setProfileBeingRecorded(new Profiler.HeapProfileHeader(heapProfilerModel, this, undefined));
-    this._profileSamples = new Profiler.TrackingHeapSnapshotProfileType.Samples();
+    this._profileSamples = new Profiler.HeapTimelineOverview.Samples();
     this.profileBeingRecorded()._profileSamples = this._profileSamples;
     this._recording = true;
     this.addProfile(/** @type {!Profiler.ProfileHeader} */ (this.profileBeingRecorded()));
@@ -1327,24 +1364,6 @@
 /**
  * @unrestricted
  */
-Profiler.TrackingHeapSnapshotProfileType.Samples = class {
-  constructor() {
-    /** @type {!Array.<number>} */
-    this.sizes = [];
-    /** @type {!Array.<number>} */
-    this.ids = [];
-    /** @type {!Array.<number>} */
-    this.timestamps = [];
-    /** @type {!Array.<number>} */
-    this.max = [];
-    /** @type {number} */
-    this.totalTime = 30000;
-  }
-};
-
-/**
- * @unrestricted
- */
 Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
   /**
    * @param {?SDK.HeapProfilerModel} heapProfilerModel
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
index b3577d6..6b38265 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
@@ -6,10 +6,7 @@
  * @unrestricted
  */
 Profiler.HeapTimelineOverview = class extends UI.VBox {
-  /**
-   * @param {!Profiler.HeapProfileHeader} heapProfileHeader
-   */
-  constructor(heapProfileHeader) {
+  constructor() {
     super();
     this.element.id = 'heap-recording-view';
     this.element.classList.add('heap-tracking-overview');
@@ -23,55 +20,20 @@
     this._overviewCalculator = new Profiler.HeapTimelineOverview.OverviewCalculator();
     this._overviewGrid.addEventListener(PerfUI.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this);
 
-    this._profileSamples = heapProfileHeader.fromFile() ? new Profiler.TrackingHeapSnapshotProfileType.Samples() :
-                                                          heapProfileHeader._profileSamples;
-    this._profileType = heapProfileHeader.profileType();
-    if (!heapProfileHeader.fromFile() && heapProfileHeader.profileType().profileBeingRecorded() === heapProfileHeader) {
-      this._profileType.addEventListener(
-          Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
-      this._profileType.addEventListener(
-          Profiler.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
-    }
     this._windowLeft = 0.0;
     this._windowRight = 1.0;
     this._overviewGrid.setWindow(this._windowLeft, this._windowRight);
     this._yScale = new Profiler.HeapTimelineOverview.SmoothScale();
     this._xScale = new Profiler.HeapTimelineOverview.SmoothScale();
-  }
 
-  dispose() {
-    this._onStopTracking();
-  }
-
-  _onStopTracking() {
-    this._profileType.removeEventListener(
-        Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
-    this._profileType.removeEventListener(
-        Profiler.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
+    this._profileSamples = new Profiler.HeapTimelineOverview.Samples();
   }
 
   /**
-   * @param {!Common.Event} event
-   */
-  _onHeapStatsUpdate(event) {
-    this._profileSamples = event.data;
-    this._scheduleUpdate();
-  }
-
-  /**
-   * @param {?HeapSnapshotModel.Samples} samples
+   * @param {!Profiler.HeapTimelineOverview.Samples} samples
    */
   setSamples(samples) {
-    if (!samples)
-      return;
-    console.assert(!this._profileSamples.timestamps.length, 'Should only call this method when loading from file.');
-    console.assert(samples.timestamps.length);
-    this._profileSamples = new Profiler.TrackingHeapSnapshotProfileType.Samples();
-    this._profileSamples.sizes = samples.sizes;
-    this._profileSamples.ids = samples.lastAssignedIds;
-    this._profileSamples.timestamps = samples.timestamps;
-    this._profileSamples.max = samples.sizes;
-    this._profileSamples.totalTime = /** @type{number} */ (samples.timestamps.peekLast());
+    this._profileSamples = samples;
     this.update();
   }
 
@@ -299,6 +261,24 @@
 };
 
 /**
+ * @unrestricted
+ */
+Profiler.HeapTimelineOverview.Samples = class {
+  constructor() {
+    /** @type {!Array<number>} */
+    this.sizes = [];
+    /** @type {!Array<number>} */
+    this.ids = [];
+    /** @type {!Array<number>} */
+    this.timestamps = [];
+    /** @type {!Array<number>} */
+    this.max = [];
+    /** @type {number} */
+    this.totalTime = 30000;
+  }
+};
+
+/**
  * @implements {PerfUI.TimelineGrid.Calculator}
  * @unrestricted
  */
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index dc9eff99..7f8f89d 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2402,7 +2402,7 @@
 bool AXNodeObject::OnNativeIncrementAction() {
   LocalFrame* frame = GetDocument() ? GetDocument()->GetFrame() : nullptr;
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
   AlterSliderOrSpinButtonValue(true);
   return true;
 }
@@ -2410,7 +2410,7 @@
 bool AXNodeObject::OnNativeDecrementAction() {
   LocalFrame* frame = GetDocument() ? GetDocument()->GetFrame() : nullptr;
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
   AlterSliderOrSpinButtonValue(false);
   return true;
 }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index f472ebe..67362208 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2852,8 +2852,8 @@
     return false;
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(document->GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(document->GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   Element* element = GetElement();
   if (!element && GetNode())
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 2753e204..8035e49 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -1403,7 +1403,7 @@
   permission_service_->RequestPermission(
       CreatePermissionDescriptor(
           mojom::blink::PermissionName::ACCESSIBILITY_EVENTS),
-      Frame::HasTransientUserActivation(document_->GetFrame()),
+      LocalFrame::HasTransientUserActivation(document_->GetFrame()),
       WTF::Bind(&AXObjectCacheImpl::OnPermissionStatusChange,
                 WrapPersistent(this)));
 }
diff --git a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
index 333d7bc3..ecacd7ad 100644
--- a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
+++ b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
@@ -82,8 +82,8 @@
   ExecutionContext* context = ExecutionContext::From(script_state);
   Document* doc = ToDocumentOrNull(context);
 
-  if (require_gesture_ &&
-      !Frame::ConsumeTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+  if (require_gesture_ && !LocalFrame::ConsumeTransientUserActivation(
+                              doc ? doc->GetFrame() : nullptr)) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
         DOMException::Create(
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index 5e56ac7a..d7e658a 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -168,7 +168,8 @@
   // If the algorithm is not allowed to show a popup, reject promise with a
   // SecurityError and abort these steps.
   Document* doc = ToDocumentOrNull(context);
-  if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+  if (!LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                  : nullptr)) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
         DOMException::Create(
diff --git a/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc b/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc
index f3bcda2..5a8ee47fd 100644
--- a/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc
+++ b/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc
@@ -147,7 +147,7 @@
         script_state, DOMException::Create(DOMExceptionCode::kAbortError));
   }
 
-  if (!Frame::HasTransientUserActivation(window.GetFrame())) {
+  if (!LocalFrame::HasTransientUserActivation(window.GetFrame())) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
         DOMException::Create(
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
index 2c6c6e7f..8a939d6 100644
--- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
+++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -216,7 +216,7 @@
   // visible.
   if (RuntimeEnabledFeatures::UserActivationV2Enabled() && GetFrame() &&
       GetPage() && GetPage()->IsPageVisible() && HasUserActivation(gamepads_)) {
-    Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
+    LocalFrame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
   }
 
   return gamepads_.Get();
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc
index d170d78..ee827711 100644
--- a/third_party/blink/renderer/modules/geolocation/geolocation.cc
+++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -87,7 +87,8 @@
 
 static void ReportGeolocationViolation(ExecutionContext* context) {
   Document* doc = ToDocumentOrNull(context);
-  if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+  if (!LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                  : nullptr)) {
     PerformanceMonitor::ReportGenericViolation(
         context, PerformanceMonitor::kDiscouragedAPIUse,
         "Only request geolocation information in response to a user gesture.",
@@ -464,7 +465,7 @@
                                                   invalidator);
   geolocation_service_->CreateGeolocation(
       MakeRequest(&geolocation_, invalidator),
-      Frame::HasTransientUserActivation(GetFrame()));
+      LocalFrame::HasTransientUserActivation(GetFrame()));
 
   geolocation_.set_connection_error_handler(WTF::Bind(
       &Geolocation::OnGeolocationConnectionError, WrapWeakPersistent(this)));
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
index cf3cd3b..6f9fd45d 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
@@ -63,7 +63,7 @@
   void SimulateEnterFullscreen() {
     {
       std::unique_ptr<UserGestureIndicator> gesture =
-          Frame::NotifyUserActivation(GetDocument().GetFrame());
+          LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
       Fullscreen::RequestFullscreen(*video_);
     }
 
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc
index bd53ac6..04eb76ab 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc
@@ -55,7 +55,7 @@
   void SimulateEnterFullscreen() {
     {
       std::unique_ptr<UserGestureIndicator> gesture =
-          Frame::NotifyUserActivation(GetDocument().GetFrame());
+          LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
       Fullscreen::RequestFullscreen(GetVideoElement());
     }
 
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
index b591afc..4b2a317 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
@@ -202,7 +202,7 @@
 
   void SimulateEnterFullscreen() {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     Fullscreen::RequestFullscreen(Video());
     test::RunPendingTasks();
   }
@@ -405,7 +405,7 @@
   void PlayVideo() {
     {
       std::unique_ptr<UserGestureIndicator> gesture =
-          Frame::NotifyUserActivation(GetDocument().GetFrame());
+          LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
       Video().Play();
     }
     test::RunPendingTasks();
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
index 66992a77f..19e4d98 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
@@ -228,7 +228,8 @@
 
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(video_element_->GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(
+            video_element_->GetDocument().GetFrame());
 
     bool should_be_fullscreen =
         current_screen_orientation_ == video_orientation;
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
index ee2a82d..a63306b 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
@@ -220,7 +220,7 @@
 void MediaControlsRotateToFullscreenDelegateTest::PlayVideo() {
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     GetVideo().Play();
   }
   test::RunPendingTasks();
@@ -307,7 +307,7 @@
   // Should start observing visibility when played.
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     GetVideo().Play();
   }
   test::RunPendingTasks();
@@ -328,7 +328,7 @@
   // Should resume observing visibility when playback resumes.
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     GetVideo().Play();
   }
   test::RunPendingTasks();
@@ -622,7 +622,7 @@
   // video (in this case document.body).
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     Fullscreen::RequestFullscreen(*GetDocument().body());
   }
   test::RunPendingTasks();
@@ -653,7 +653,7 @@
   // Start in fullscreen.
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     GetMediaControls().EnterFullscreen();
   }
   // n.b. omit to call Fullscreen::From(GetDocument()).DidEnterFullscreen() so
@@ -684,7 +684,7 @@
   // Start in fullscreen.
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     GetMediaControls().EnterFullscreen();
   }
   // n.b. omit to call Fullscreen::From(GetDocument()).DidEnterFullscreen() so
@@ -716,7 +716,7 @@
   // video (in this case document.body).
   {
     std::unique_ptr<UserGestureIndicator> gesture =
-        Frame::NotifyUserActivation(GetDocument().GetFrame());
+        LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
     Fullscreen::RequestFullscreen(*GetDocument().body());
   }
   test::RunPendingTasks();
diff --git a/third_party/blink/renderer/modules/mediasession/media_session.cc b/third_party/blink/renderer/modules/mediasession/media_session.cc
index 1ba9605..51169bd 100644
--- a/third_party/blink/renderer/modules/mediasession/media_session.cc
+++ b/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -219,7 +219,8 @@
   DCHECK(GetExecutionContext()->IsDocument());
   Document* document = ToDocument(GetExecutionContext());
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(document ? document->GetFrame() : nullptr);
+      LocalFrame::NotifyUserActivation(document ? document->GetFrame()
+                                                : nullptr);
 
   auto iter = action_handlers_.find(MojomActionToActionName(action));
   if (iter == action_handlers_.end())
diff --git a/third_party/blink/renderer/modules/notifications/notification.cc b/third_party/blink/renderer/modules/notifications/notification.cc
index 6e277ad9..41afb93 100644
--- a/third_party/blink/renderer/modules/notifications/notification.cc
+++ b/third_party/blink/renderer/modules/notifications/notification.cc
@@ -231,8 +231,9 @@
   ExecutionContext* context = GetExecutionContext();
   Document* document = context->IsDocument() ? ToDocument(context) : nullptr;
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(document ? document->GetFrame() : nullptr,
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(
+          document ? document->GetFrame() : nullptr,
+          UserGestureToken::kNewGesture);
   ScopedWindowFocusAllowedIndicator window_focus_allowed(GetExecutionContext());
   DispatchEvent(*Event::Create(EventTypeNames::click));
 
@@ -418,7 +419,8 @@
   Document* doc = ToDocumentOrNull(context);
 
   probe::breakableLocation(context, "Notification.requestPermission");
-  if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+  if (!LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                  : nullptr)) {
     PerformanceMonitor::ReportGenericViolation(
         context, PerformanceMonitor::kDiscouragedAPIUse,
         "Only request notification permission in response to a user gesture.",
diff --git a/third_party/blink/renderer/modules/notifications/notification_manager.cc b/third_party/blink/renderer/modules/notifications/notification_manager.cc
index 60fd902..b1ea6ac0 100644
--- a/third_party/blink/renderer/modules/notifications/notification_manager.cc
+++ b/third_party/blink/renderer/modules/notifications/notification_manager.cc
@@ -82,7 +82,7 @@
   Document* doc = ToDocumentOrNull(context);
   permission_service_->RequestPermission(
       CreatePermissionDescriptor(mojom::blink::PermissionName::NOTIFICATIONS),
-      Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
+      LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
       WTF::Bind(
           &NotificationManager::OnPermissionRequestComplete,
           WrapPersistent(this), WrapPersistent(resolver),
diff --git a/third_party/blink/renderer/modules/payments/payment_instruments.cc b/third_party/blink/renderer/modules/payments/payment_instruments.cc
index 3c0e57ec..448095c 100644
--- a/third_party/blink/renderer/modules/payments/payment_instruments.cc
+++ b/third_party/blink/renderer/modules/payments/payment_instruments.cc
@@ -250,7 +250,8 @@
       ->RequestPermission(
           CreatePermissionDescriptor(
               mojom::blink::PermissionName::PAYMENT_HANDLER),
-          Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
+          LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                     : nullptr),
           WTF::Bind(&PaymentInstruments::OnRequestPermission,
                     WrapPersistent(this), WrapPersistent(resolver),
                     instrument_key,
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc
index c4c9212..3ed6c7f 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -800,7 +800,7 @@
 
   // TODO(crbug.com/825270): Reject with SecurityError DOMException if triggered
   // without user activation.
-  bool is_user_gesture = Frame::HasTransientUserActivation(GetFrame());
+  bool is_user_gesture = LocalFrame::HasTransientUserActivation(GetFrame());
   if (!is_user_gesture) {
     UseCounter::Count(GetExecutionContext(),
                       WebFeature::kPaymentRequestShowWithoutGesture);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h
index 49e9948fae..a6c67fe 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h
@@ -33,7 +33,7 @@
   P2PQuicTransportConfig(const P2PQuicTransportConfig&) = delete;
   P2PQuicTransportConfig& operator=(const P2PQuicTransportConfig&) = delete;
   P2PQuicTransportConfig(P2PQuicTransportConfig&&) = default;
-  P2PQuicTransportConfig& operator=(P2PQuicTransportConfig&&) = default;
+  P2PQuicTransportConfig& operator=(P2PQuicTransportConfig&&) = delete;
   ~P2PQuicTransportConfig() = default;
 
   //  The standard case is an ICE transport. It's lifetime will be managed by
diff --git a/third_party/blink/renderer/modules/permissions/permissions.cc b/third_party/blink/renderer/modules/permissions/permissions.cc
index f1d94b4..001b7c4 100644
--- a/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -188,8 +188,8 @@
   GetService(ExecutionContext::From(script_state))
       .RequestPermission(
           std::move(descriptor),
-          Frame::HasTransientUserActivation(frame,
-                                            true /* checkIfMainThread */),
+          LocalFrame::HasTransientUserActivation(
+              frame, true /* check_if_main_thread */),
           WTF::Bind(&Permissions::TaskComplete, WrapPersistent(this),
                     WrapPersistent(resolver),
                     WTF::Passed(std::move(descriptor_copy))));
@@ -262,8 +262,8 @@
   GetService(ExecutionContext::From(script_state))
       .RequestPermissions(
           std::move(internal_permissions),
-          Frame::HasTransientUserActivation(frame,
-                                            true /* checkIfMainThread */),
+          LocalFrame::HasTransientUserActivation(
+              frame, true /* check_if_main_thread */),
           WTF::Bind(&Permissions::BatchTaskComplete, WrapPersistent(this),
                     WrapPersistent(resolver),
                     WTF::Passed(std::move(internal_permissions_copy)),
diff --git a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
index 52700d6c..ce26c89 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
@@ -84,7 +84,7 @@
   // `kFrameDetached`.
   LocalFrame* frame = element.GetFrame();
   DCHECK(frame);
-  if (!Frame::ConsumeTransientUserActivation(frame)) {
+  if (!LocalFrame::ConsumeTransientUserActivation(frame)) {
     return ScriptPromise::RejectWithDOMException(
         script_state, DOMException::Create(DOMExceptionCode::kNotAllowedError,
                                            kUserGestureRequired));
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request.cc b/third_party/blink/renderer/modules/presentation/presentation_request.cc
index 4942ca7..446b7e8 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_request.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_request.cc
@@ -155,7 +155,7 @@
       context_settings->GetPresentationRequiresUserGesture();
 
   if (is_user_gesture_required &&
-      !Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr))
+      !LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr))
     return ScriptPromise::RejectWithDOMException(
         script_state,
         DOMException::Create(
diff --git a/third_party/blink/renderer/modules/push_messaging/push_manager.cc b/third_party/blink/renderer/modules/push_messaging/push_manager.cc
index 6ec4b296..0237409 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_manager.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_manager.cc
@@ -80,13 +80,14 @@
                                "Document is detached from window."));
     PushController::ClientFrom(frame).Subscribe(
         registration_->WebRegistration(), web_options,
-        Frame::HasTransientUserActivation(frame, true /* checkIfMainThread */),
+        LocalFrame::HasTransientUserActivation(frame,
+                                               true /* check_if_main_thread */),
         std::make_unique<PushSubscriptionCallbacks>(resolver, registration_));
   } else {
     PushProvider()->Subscribe(
         registration_->WebRegistration(), web_options,
-        Frame::HasTransientUserActivation(nullptr,
-                                          true /* checkIfMainThread */),
+        LocalFrame::HasTransientUserActivation(nullptr,
+                                               true /* check_if_main_thread */),
         std::make_unique<PushSubscriptionCallbacks>(resolver, registration_));
   }
 
diff --git a/third_party/blink/renderer/modules/quota/storage_manager.cc b/third_party/blink/renderer/modules/quota/storage_manager.cc
index 297e370..fb30bf3 100644
--- a/third_party/blink/renderer/modules/quota/storage_manager.cc
+++ b/third_party/blink/renderer/modules/quota/storage_manager.cc
@@ -69,7 +69,8 @@
   GetPermissionService(ExecutionContext::From(script_state))
       .RequestPermission(
           CreatePermissionDescriptor(PermissionName::DURABLE_STORAGE),
-          Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
+          LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                     : nullptr),
           WTF::Bind(&StorageManager::PermissionRequestComplete,
                     WrapPersistent(this), WrapPersistent(resolver)));
 
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index 4f855bd..c1811a2 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -184,7 +184,7 @@
     return promise;
   }
 
-  if (!Frame::HasTransientUserActivation(media_element_->GetFrame())) {
+  if (!LocalFrame::HasTransientUserActivation(media_element_->GetFrame())) {
     resolver->Reject(DOMException::Create(
         DOMExceptionCode::kInvalidAccessError,
         "RemotePlayback::prompt() requires user gesture."));
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
index fa7b972..f283e8f 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
@@ -97,8 +97,9 @@
   EXPECT_CALL(*resolve, Call(testing::_)).Times(0);
   EXPECT_CALL(*reject, Call(testing::_)).Times(1);
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      &page_holder->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(&page_holder->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   remote_playback->prompt(scope.GetScriptState())
       .Then(resolve->Bind(), reject->Bind());
   CancelPrompt(remote_playback);
@@ -130,8 +131,9 @@
 
   SetState(remote_playback, WebRemotePlaybackState::kConnected);
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      &page_holder->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(&page_holder->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   remote_playback->prompt(scope.GetScriptState())
       .Then(resolve->Bind(), reject->Bind());
   CancelPrompt(remote_playback);
@@ -163,8 +165,9 @@
 
   SetState(remote_playback, WebRemotePlaybackState::kConnected);
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      &page_holder->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(&page_holder->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   remote_playback->prompt(scope.GetScriptState())
       .Then(resolve->Bind(), reject->Bind());
 
@@ -239,8 +242,9 @@
   EXPECT_CALL(*resolve, Call(testing::_)).Times(0);
   EXPECT_CALL(*reject, Call(testing::_)).Times(1);
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      &page_holder->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(&page_holder->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   remote_playback->prompt(scope.GetScriptState())
       .Then(resolve->Bind(), reject->Bind());
   HTMLMediaElementRemotePlayback::SetBooleanAttribute(
@@ -314,8 +318,9 @@
   EXPECT_CALL(*resolve, Call(testing::_)).Times(0);
   EXPECT_CALL(*reject, Call(testing::_)).Times(1);
 
-  std::unique_ptr<UserGestureIndicator> indicator = Frame::NotifyUserActivation(
-      &page_holder->GetFrame(), UserGestureToken::kNewGesture);
+  std::unique_ptr<UserGestureIndicator> indicator =
+      LocalFrame::NotifyUserActivation(&page_holder->GetFrame(),
+                                       UserGestureToken::kNewGesture);
   remote_playback->prompt(scope.GetScriptState())
       .Then(resolve->Bind(), reject->Bind());
 
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc
index 4de99ecb..17ab044 100644
--- a/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -398,7 +398,8 @@
   // allowed outside a user gesture so that the presented content may be
   // updated.
   if (first_present) {
-    if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+    if (!LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                    : nullptr)) {
       DOMException* exception =
           DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                "API can only be initiated by a user gesture.");
@@ -934,7 +935,7 @@
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator;
   if (reason == device::mojom::blink::VRDisplayEventReason::MOUNTED)
-    gesture_indicator = Frame::NotifyUserActivation(doc->GetFrame());
+    gesture_indicator = LocalFrame::NotifyUserActivation(doc->GetFrame());
 
   base::AutoReset<bool> in_activate(&in_display_activate_, true);
 
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc
index 90e7869..5ed838aa 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -368,7 +368,7 @@
       return true;
     case AutoplayPolicy::Type::kUserGestureRequired:
     case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
-      return Frame::HasTransientUserActivation(GetDocument()->GetFrame());
+      return LocalFrame::HasTransientUserActivation(GetDocument()->GetFrame());
     case AutoplayPolicy::Type::kDocumentUserActivationRequired:
       return AutoplayPolicy::IsDocumentAllowedToPlay(*GetDocument());
   }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc b/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
index c57484b..b9b40ca 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
@@ -259,8 +259,8 @@
 // Creates an AudioContext with a user gesture inside a x-origin child frame.
 TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Child) {
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   AudioContext* audio_context = AudioContext::Create(
       ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
@@ -288,8 +288,8 @@
 // Creates an AudioContext with a user gesture inside a main frame.
 TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Main) {
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(GetDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   AudioContext* audio_context = AudioContext::Create(
       GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
@@ -320,8 +320,8 @@
       ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
   RejectPendingResolvers(audio_context);
@@ -355,8 +355,8 @@
       GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(GetDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
 
   audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
   RejectPendingResolvers(audio_context);
@@ -435,8 +435,8 @@
       ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->NotifySourceNodeStart();
   RecordAutoplayStatus(audio_context);
 
@@ -466,8 +466,8 @@
       GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(GetDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->NotifySourceNodeStart();
   RecordAutoplayStatus(audio_context);
 
@@ -498,8 +498,8 @@
   audio_context->NotifySourceNodeStart();
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
   RejectPendingResolvers(audio_context);
   RecordAutoplayStatus(audio_context);
@@ -534,8 +534,8 @@
   audio_context->NotifySourceNodeStart();
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(GetDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
   RejectPendingResolvers(audio_context);
   RecordAutoplayStatus(audio_context);
@@ -566,8 +566,8 @@
       ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->NotifySourceNodeStart();
   audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
   RejectPendingResolvers(audio_context);
@@ -602,8 +602,8 @@
       GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
 
   std::unique_ptr<UserGestureIndicator> user_gesture_scope =
-      Frame::NotifyUserActivation(GetDocument().GetFrame(),
-                                  UserGestureToken::kNewGesture);
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
+                                       UserGestureToken::kNewGesture);
   audio_context->NotifySourceNodeStart();
   audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
   RejectPendingResolvers(audio_context);
@@ -629,8 +629,8 @@
 // document previous received a user gesture.
 TEST_P(AudioContextAutoplayTest,
        AutoplayMetrics_DocumentReceivedGesture_Child) {
-  Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                              UserGestureToken::kNewGesture);
+  LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                   UserGestureToken::kNewGesture);
 
   AudioContext* audio_context = AudioContext::Create(
       ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
@@ -666,8 +666,8 @@
 // document previous received a user gesture.
 TEST_P(AudioContextAutoplayTest,
        AutoplayMetrics_DocumentReceivedGesture_Main) {
-  Frame::NotifyUserActivation(ChildDocument().GetFrame(),
-                              UserGestureToken::kNewGesture);
+  LocalFrame::NotifyUserActivation(ChildDocument().GetFrame(),
+                                   UserGestureToken::kNewGesture);
 
   AudioContext* audio_context = AudioContext::Create(
       GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
index 33a8b5b..a53693b 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
+++ b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
@@ -46,7 +46,7 @@
   Document* doc = ToDocumentOrNull(GetExecutionContext());
   permission_service_->RequestPermission(
       CreateMidiPermissionDescriptor(options_.hasSysex() && options_.sysex()),
-      Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
+      LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr),
       WTF::Bind(&MIDIAccessInitializer::OnPermissionsUpdated,
                 WrapPersistent(this)));
 
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share.cc b/third_party/blink/renderer/modules/webshare/navigator_share.cc
index dca964a..d6b4b1f 100644
--- a/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -120,7 +120,8 @@
     return ScriptPromise::Reject(script_state, error);
   }
 
-  if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+  if (!LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame()
+                                                  : nullptr)) {
     DOMException* error = DOMException::Create(
         DOMExceptionCode::kNotAllowedError,
         "Must be handling a user gesture to perform a share request.");
diff --git a/third_party/blink/renderer/modules/webusb/usb.cc b/third_party/blink/renderer/modules/webusb/usb.cc
index b911b99..1a65f8e 100644
--- a/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/third_party/blink/renderer/modules/webusb/usb.cc
@@ -149,7 +149,7 @@
 
   EnsureServiceConnection();
 
-  if (!Frame::HasTransientUserActivation(frame)) {
+  if (!LocalFrame::HasTransientUserActivation(frame)) {
     return ScriptPromise::RejectWithDOMException(
         script_state,
         DOMException::Create(
diff --git a/third_party/blink/renderer/modules/xr/xr_device.cc b/third_party/blink/renderer/modules/xr/xr_device.cc
index 92cd3cb..ca21b737 100644
--- a/third_party/blink/renderer/modules/xr/xr_device.cc
+++ b/third_party/blink/renderer/modules/xr/xr_device.cc
@@ -117,7 +117,7 @@
 
   // TODO(ijamardo): Should we just exit if there is not document?
   bool has_user_activation =
-      Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr);
+      LocalFrame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr);
 
   // Check if the current page state prevents the requested session from being
   // created.
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index 4ed0e53..3143b251 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -631,7 +631,7 @@
     return;
 
   std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      Frame::NotifyUserActivation(frame);
+      LocalFrame::NotifyUserActivation(frame);
 
   XRInputSourceEvent* event =
       CreateInputSourceEvent(EventTypeNames::selectend, input_source);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 87af6ac1..c6daad5a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -466,6 +466,8 @@
     case TaskType::kWorkerThreadTaskQueueDefault:
     case TaskType::kWorkerThreadTaskQueueV8:
     case TaskType::kWorkerThreadTaskQueueCompositor:
+    case TaskType::kExperimentalWebSchedulingUserInteraction:
+    case TaskType::kExperimentalWebSchedulingBestEffort:
     case TaskType::kCount:
       // Not a valid frame-level TaskType.
       return base::nullopt;
@@ -495,6 +497,14 @@
       return frame_task_queue_controller_->LoadingControlTaskQueue();
     case TaskType::kInternalInspector:
       return frame_task_queue_controller_->InspectorTaskQueue();
+    case TaskType::kExperimentalWebSchedulingUserInteraction:
+      return frame_task_queue_controller_->ExperimentalWebSchedulingTaskQueue(
+          FrameTaskQueueController::WebSchedulingTaskQueueType::
+              kWebSchedulingUserVisiblePriority);
+    case TaskType::kExperimentalWebSchedulingBestEffort:
+      return frame_task_queue_controller_->ExperimentalWebSchedulingTaskQueue(
+          FrameTaskQueueController::WebSchedulingTaskQueueType::
+              kWebSchedulingBestEffortPriority);
     default:
       // Non-loading task queue.
       DCHECK_LT(static_cast<size_t>(type),
@@ -858,6 +868,16 @@
     }
   }
 
+  if (task_queue->queue_type() ==
+      MainThreadTaskQueue::QueueType::kWebSchedulingUserInteraction) {
+    return TaskQueue::QueuePriority::kNormalPriority;
+  }
+
+  if (task_queue->queue_type() ==
+      MainThreadTaskQueue::QueueType::kWebSchedulingBestEffort) {
+    return TaskQueue::QueuePriority::kLowPriority;
+  }
+
   return task_queue->queue_type() ==
                  MainThreadTaskQueue::QueueType::kFrameLoadingControl
              ? TaskQueue::QueuePriority::kHighPriority
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index af60f2d..13bd6f5 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/trace_event/trace_event_argument.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
@@ -65,6 +66,16 @@
 }
 
 scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::ExperimentalWebSchedulingTaskQueue(
+    WebSchedulingTaskQueueType task_queue_type) {
+  if (!web_scheduling_task_queues_[task_queue_type])
+    CreateWebSchedulingTaskQueue(task_queue_type);
+
+  DCHECK(web_scheduling_task_queues_[task_queue_type]);
+  return web_scheduling_task_queues_[task_queue_type];
+}
+
+scoped_refptr<MainThreadTaskQueue>
 FrameTaskQueueController::NonLoadingTaskQueue(
     MainThreadTaskQueue::QueueTraits queue_traits) {
   if (!non_loading_task_queues_.Contains(queue_traits.Key()))
@@ -89,6 +100,42 @@
   TaskQueueCreated(loading_task_queue_);
 }
 
+void FrameTaskQueueController::CreateWebSchedulingTaskQueue(
+    WebSchedulingTaskQueueType task_queue_type) {
+  DCHECK(RuntimeEnabledFeatures::WorkerTaskQueueEnabled());
+  DCHECK(!web_scheduling_task_queues_[task_queue_type]);
+  // |main_thread_scheduler_impl_| can be null in unit tests.
+  DCHECK(main_thread_scheduler_impl_);
+
+  MainThreadTaskQueue::QueueType main_thread_queue_type =
+      MainThreadTaskQueue::QueueType::kDefault;
+  switch (task_queue_type) {
+    case kWebSchedulingUserVisiblePriority:
+      main_thread_queue_type =
+          MainThreadTaskQueue::QueueType::kWebSchedulingUserInteraction;
+      break;
+    case kWebSchedulingBestEffortPriority:
+      main_thread_queue_type =
+          MainThreadTaskQueue::QueueType::kWebSchedulingBestEffort;
+      break;
+    case kWebSchedulingPriorityCount:
+      NOTREACHED();
+  }
+
+  scoped_refptr<MainThreadTaskQueue> task_queue =
+      main_thread_scheduler_impl_->NewTaskQueue(
+          MainThreadTaskQueue::QueueCreationParams(main_thread_queue_type)
+              .SetCanBePaused(true)
+              .SetCanBeFrozen(true)
+              .SetCanBeDeferred(task_queue_type !=
+                                kWebSchedulingUserVisiblePriority)
+              .SetCanBeThrottled(true)
+              .SetFrameScheduler(frame_scheduler_impl_));
+
+  TaskQueueCreated(task_queue);
+  web_scheduling_task_queues_[task_queue_type] = task_queue;
+}
+
 void FrameTaskQueueController::CreateLoadingControlTaskQueue() {
   DCHECK(!loading_control_task_queue_);
   // |main_thread_scheduler_impl_| can be null in unit tests.
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
index 7d7a81d..18235bf 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
@@ -72,6 +72,15 @@
   // Return the inspector task queue and create it if it doesn't exist.
   scoped_refptr<MainThreadTaskQueue> InspectorTaskQueue();
 
+  enum WebSchedulingTaskQueueType : unsigned {
+    kWebSchedulingUserVisiblePriority,
+    kWebSchedulingBestEffortPriority,
+    kWebSchedulingPriorityCount
+  };
+  // Return the Scheduling API task queue for the given priority.
+  scoped_refptr<MainThreadTaskQueue> ExperimentalWebSchedulingTaskQueue(
+      WebSchedulingTaskQueueType);
+
   // Return the non-loading task queue associated with the given queue traits,
   // and created it if it doesn't exist.
   scoped_refptr<MainThreadTaskQueue> NonLoadingTaskQueue(
@@ -104,6 +113,7 @@
 
   void CreateLoadingTaskQueue();
   void CreateLoadingControlTaskQueue();
+  void CreateWebSchedulingTaskQueue(WebSchedulingTaskQueueType task_queue_type);
   void CreateNonLoadingTaskQueue(MainThreadTaskQueue::QueueTraits);
 
   void TaskQueueCreated(const scoped_refptr<MainThreadTaskQueue>&);
@@ -129,6 +139,9 @@
   // behavior as far as virtual time is concerned.
   scoped_refptr<MainThreadTaskQueue> inspector_task_queue_;
 
+  scoped_refptr<MainThreadTaskQueue>
+      web_scheduling_task_queues_[kWebSchedulingPriorityCount];
+
   using NonLoadingTaskQueueMap =
       WTF::HashMap<MainThreadTaskQueue::QueueTraitsKeyType,
                    scoped_refptr<MainThreadTaskQueue>>;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
index fd16f3b..61804744 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
@@ -55,6 +55,10 @@
       return "cleanup_tq";
     case MainThreadTaskQueue::QueueType::kOther:
       return "other_tq";
+    case MainThreadTaskQueue::QueueType::kWebSchedulingUserInteraction:
+      return "web_scheduling_user_interaction_tq";
+    case MainThreadTaskQueue::QueueType::kWebSchedulingBestEffort:
+      return "web_scheduling_background_tq";
     case MainThreadTaskQueue::QueueType::kCount:
       NOTREACHED();
       return nullptr;
@@ -82,6 +86,8 @@
     case QueueType::kFrameDeferrable:
     case QueueType::kFramePausable:
     case QueueType::kFrameUnpausable:
+    case QueueType::kWebSchedulingUserInteraction:
+    case QueueType::kWebSchedulingBestEffort:
       return QueueClass::kTimer;
     case QueueType::kCompositor:
     case QueueType::kInput:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index 2e2a2d6..8c277499 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -60,9 +60,12 @@
 
     kCleanup = 20,
 
+    kWebSchedulingUserInteraction = 21,
+    kWebSchedulingBestEffort = 22,
+
     // Used to group multiple types when calculating Expected Queueing Time.
-    kOther = 21,
-    kCount = 22
+    kOther = 23,
+    kCount = 24
   };
 
   // Returns name of the given queue type. Returned string has application
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
index 208d6c7..f81e030a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -61,6 +61,10 @@
       return "IdleTask";
     case TaskType::kMiscPlatformAPI:
       return "MiscPlatformAPI";
+    case TaskType::kExperimentalWebSchedulingUserInteraction:
+      return "ExperimentalWebSchedulingUserInteraction";
+    case TaskType::kExperimentalWebSchedulingBestEffort:
+      return "ExperimentalWebSchedulingBackground";
     case TaskType::kInternalDefault:
       return "InternalDefault";
     case TaskType::kInternalLoading:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
index 6ff3d3b9..ab18ef4 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -145,6 +145,8 @@
     case TaskType::kWorkerThreadTaskQueueDefault:
     case TaskType::kWorkerThreadTaskQueueV8:
     case TaskType::kWorkerThreadTaskQueueCompositor:
+    case TaskType::kExperimentalWebSchedulingUserInteraction:
+    case TaskType::kExperimentalWebSchedulingBestEffort:
     case TaskType::kCount:
       NOTREACHED();
       break;
diff --git a/tools/gdb/OWNERS b/tools/gdb/OWNERS
new file mode 100644
index 0000000..5d9d9d4e
--- /dev/null
+++ b/tools/gdb/OWNERS
@@ -0,0 +1,3 @@
+jbroman@chromium.org
+thomasanderson@chromium.org
+tikuta@chromium.org
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 42e402d..a9c58de1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9166,8 +9166,11 @@
   <int value="3" label="Error Loading Termina"/>
   <int value="4" label="Error Starting Concierge"/>
   <int value="5" label="Error Creating Disk Image"/>
-  <int value="6" label="Error Starting Termina"/>
+  <int value="6" label="Error Starting Termina VM"/>
   <int value="7" label="Error Starting Container"/>
+  <int value="8" label="Error Offline"/>
+  <int value="9" label="Error Fetching Ssh Keys"/>
+  <int value="10" label="Error Mounting Container"/>
 </enum>
 
 <enum name="CrostiniUISurface">
@@ -14609,6 +14612,7 @@
   <int value="483" label="EnterpriseHardwarePlatformAPIEnabled"/>
   <int value="484" label="ReportCrostiniUsageEnabled"/>
   <int value="485" label="VpnConfigAllowed"/>
+  <int value="486" label="WebUsbAllowDevicesForUrls"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -42411,6 +42415,8 @@
   <int value="18" label="Input"/>
   <int value="19" label="Detached"/>
   <int value="20" label="Cleanup"/>
+  <int value="21" label="WebSchedulingUserInteraction"/>
+  <int value="22" label="WebSchedulingBestEffort"/>
 </enum>
 
 <enum name="RendererSchedulerTaskType">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 669eff1..0120bc0 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -15168,6 +15168,16 @@
   </summary>
 </histogram>
 
+<histogram name="ContextualSuggestions.ResultsReturnedInOverviewMode"
+    enum="BooleanEnabled" expires_after="2019-01-30">
+  <owner>twellington@chromium.org</owner>
+  <owner>huayinz@chromium.org</owner>
+  <summary>
+    Android: Whether the contextual suggestions results are returned to the
+    UI-layer while the user is in overview mode.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Cookie.AgeFor" units="days">
   <owner>mkwst@chromium.org</owner>
   <owner>tnagel@chromium.org</owner>
diff --git a/tools/perf/page_sets/login_helpers/login_utils.py b/tools/perf/page_sets/login_helpers/login_utils.py
index 941dc7d..c3347b0 100644
--- a/tools/perf/page_sets/login_helpers/login_utils.py
+++ b/tools/perf/page_sets/login_helpers/login_utils.py
@@ -54,10 +54,14 @@
       possible exceptions.
   """
   action_runner.WaitForElement(selector=input_selector)
+  action_runner.Wait(0.5)
   # Focus the requested element first and then enter text using single
   # Keyboard events to bypass certain restrictions on websites.
   action_runner.ExecuteJavaScript(
       'document.querySelector({{selector}}).focus()', selector=input_selector)
+  # Wait a bit to make sure the focus is properly set, otherwise we'll end up
+  # losing some characters.
+  action_runner.Wait(0.5)
   action_runner.EnterText(input_text)
 
 def InputForm(action_runner, input_text, input_id, form_id=None):
diff --git a/ui/android/java/src/org/chromium/ui/widget/RoundedCornerImageView.java b/ui/android/java/src/org/chromium/ui/widget/RoundedCornerImageView.java
index 9d42d7c..7cb3c59e 100644
--- a/ui/android/java/src/org/chromium/ui/widget/RoundedCornerImageView.java
+++ b/ui/android/java/src/org/chromium/ui/widget/RoundedCornerImageView.java
@@ -155,31 +155,6 @@
 
         // Default to using the shader.
         mApplyShader = true;
-
-        // If the scale type would not scale up the image, and the image is smaller than the
-        // view bounds, then just draw it normally so the shader won't have adverse effects.
-        // CENTER does not do any scaling, and simply centers the image. In that case we need to
-        // check to see if the image is smaller than the view in either dimension, and don't apply
-        // the shaer if it is. CENTER_INSIDE will only scale down, so we need to calculate the
-        // scaled size of the image, and only apply the shader if it happens to match the size of
-        // the view.
-        // TODO: this won't work with a custom image matrix, but that's probably ok for now
-        ScaleType scaleType = getScaleType();
-        if (scaleType == ScaleType.CENTER || scaleType == ScaleType.CENTER_INSIDE) {
-            int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft();
-            int viewHeight = getHeight() - getPaddingTop() - getPaddingBottom();
-            int drawableWidth = drawable.getIntrinsicWidth();
-            int drawableHeight = drawable.getIntrinsicHeight();
-            if (scaleType == ScaleType.CENTER_INSIDE) {
-                float scale = Math.min((float) viewWidth / (float) drawableWidth,
-                        (float) viewHeight / (float) drawableHeight);
-                drawableWidth = (int) ((scale * drawableWidth) + 0.5f);
-                drawableHeight = (int) ((scale * drawableHeight) + 0.5f);
-            }
-            if ((drawableWidth < viewWidth) || (drawableHeight < viewHeight)) {
-                mApplyShader = false;
-            }
-        }
     }
 
     @Override
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index c97d5dd..f86fd07 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -250,6 +250,8 @@
     "test/mus/test_window_tree_client_delegate.h",
     "test/mus/test_window_tree_client_setup.cc",
     "test/mus/test_window_tree_client_setup.h",
+    "test/mus/window_port_mus_test_helper.cc",
+    "test/mus/window_port_mus_test_helper.h",
     "test/mus/window_tree_client_private.cc",
     "test/mus/window_tree_client_private.h",
     "test/test_cursor_client.cc",
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc
index 2fed6d19..1ed7c6e 100644
--- a/ui/aura/client/aura_constants.cc
+++ b/ui/aura/client/aura_constants.cc
@@ -24,8 +24,6 @@
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, SkColor)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t)
-DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT,
-                                       aura::client::WindowEmbedType)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
 
@@ -54,9 +52,6 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kImmersiveFullscreenKey, false);
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr);
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kMirroringEnabledKey, false);
-DEFINE_UI_CLASS_PROPERTY_KEY(WindowEmbedType,
-                             kEmbedType,
-                             WindowEmbedType::NONE);
 DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr);
 DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE);
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr);
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h
index 0b150af..65dc33a5 100644
--- a/ui/aura/client/aura_constants.h
+++ b/ui/aura/client/aura_constants.h
@@ -23,11 +23,6 @@
 namespace client {
 class FocusClient;
 
-enum class WindowEmbedType {
-  NONE,
-  EMBED_IN_OWNER,
-};
-
 // Alphabetical sort.
 
 // A property key to store whether accessibility focus falls back to widget or
@@ -155,9 +150,6 @@
 // A property key to store the window icon, typically 16x16 for title bars.
 AURA_EXPORT extern const WindowProperty<gfx::ImageSkia*>* const kWindowIconKey;
 
-// Indicates the type of embedding within the given window.
-AURA_EXPORT extern const WindowProperty<WindowEmbedType>* const kEmbedType;
-
 // The corner radius of a window in DIPs. Currently only used for shadows.
 // Default is -1, meaning "unspecified". 0 Ensures corners are square.
 AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey;
diff --git a/ui/aura/env.cc b/ui/aura/env.cc
index 07ff6f5..46c9287 100644
--- a/ui/aura/env.cc
+++ b/ui/aura/env.cc
@@ -113,19 +113,8 @@
     return std::make_unique<WindowPortForShutdown>();
 
   DCHECK(window_tree_client_);
-  WindowMusType window_mus_type;
-  switch (window->GetProperty(aura::client::kEmbedType)) {
-    case aura::client::WindowEmbedType::NONE:
-      window_mus_type = WindowMusType::LOCAL;
-      break;
-    case aura::client::WindowEmbedType::EMBED_IN_OWNER:
-      window_mus_type = WindowMusType::EMBED_IN_OWNER;
-      break;
-    default:
-      NOTREACHED();
-  }
-  // Use LOCAL as all other cases are created by WindowTreeClient explicitly.
-  return std::make_unique<WindowPortMus>(window_tree_client_, window_mus_type);
+  return std::make_unique<WindowPortMus>(window_tree_client_,
+                                         WindowMusType::LOCAL);
 }
 
 void Env::AddObserver(EnvObserver* observer) {
diff --git a/ui/aura/hit_test_data_provider_aura_unittest.cc b/ui/aura/hit_test_data_provider_aura_unittest.cc
index fd072153..79f73481 100644
--- a/ui/aura/hit_test_data_provider_aura_unittest.cc
+++ b/ui/aura/hit_test_data_provider_aura_unittest.cc
@@ -8,6 +8,7 @@
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/gfx/geometry/rect.h"
@@ -73,23 +74,17 @@
     test::AuraTestBaseMus::SetUp();
 
     root_ = std::make_unique<Window>(nullptr);
-    root_->SetProperty(client::kEmbedType,
-                       client::WindowEmbedType::EMBED_IN_OWNER);
     root_->Init(ui::LAYER_NOT_DRAWN);
     root_->SetEventTargeter(std::make_unique<WindowTargeter>());
     root_->SetBounds(gfx::Rect(0, 0, 300, 200));
     root_->Show();
 
     window2_ = new Window(nullptr);
-    window2_->SetProperty(client::kEmbedType,
-                          client::WindowEmbedType::EMBED_IN_OWNER);
     window2_->Init(ui::LAYER_TEXTURED);
     window2_->SetBounds(gfx::Rect(20, 30, 40, 60));
     window2_->Show();
 
     window3_ = new Window(nullptr);
-    window3_->SetProperty(client::kEmbedType,
-                          client::WindowEmbedType::EMBED_IN_OWNER);
     window3_->Init(ui::LAYER_TEXTURED);
     window3_->SetEventTargeter(std::make_unique<WindowTargeter>());
     window3_->SetBounds(gfx::Rect(50, 60, 100, 40));
diff --git a/ui/aura/mus/mus_types.h b/ui/aura/mus/mus_types.h
index 4f40626..3a58e55 100644
--- a/ui/aura/mus/mus_types.h
+++ b/ui/aura/mus/mus_types.h
@@ -20,17 +20,9 @@
   // The window is an embed root in the embedded client. That is, the client
   // received this window by way of another client calling Embed(). In other
   // words, this is the embedded side of an embedding.
-  // NOTE: in the client that called Embed() the window type is LOCAL (or
-  // EMBED_IN_OWNER).
-  // TODO(sky): ensure when Embed() is called type is always set to
-  // EMBED_IN_OWNER, and if the embedding is removed it goes back to LOCAL.
-  // https://crbug.com/834487
+  // NOTE: in the client that called Embed() the window type is LOCAL.
   EMBED,
 
-  // Embed() was called on the window by the local client. In other words, this
-  // is the embedder side of an embedding.
-  EMBED_IN_OWNER,
-
   // The window was created by requesting a top level
   // (WindowTree::NewTopLevel()).
   TOP_LEVEL,
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc
index c91999eb..5678ce1 100644
--- a/ui/aura/mus/window_port_mus.cc
+++ b/ui/aura/mus/window_port_mus.cc
@@ -98,16 +98,28 @@
 void WindowPortMus::Embed(ws::mojom::WindowTreeClientPtr client,
                           uint32_t flags,
                           ws::mojom::WindowTree::EmbedCallback callback) {
-  window_tree_client_->Embed(window_, std::move(client), flags,
-                             std::move(callback));
+  if (!PrepareForEmbed()) {
+    std::move(callback).Run(false);
+    return;
+  }
+  window_tree_client_->tree_->Embed(
+      server_id(), std::move(client), flags,
+      base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(),
+                     std::move(callback)));
 }
 
 void WindowPortMus::EmbedUsingToken(
     const base::UnguessableToken& token,
     uint32_t flags,
     ws::mojom::WindowTree::EmbedCallback callback) {
-  window_tree_client_->EmbedUsingToken(window_, token, flags,
-                                       std::move(callback));
+  if (!PrepareForEmbed()) {
+    std::move(callback).Run(false);
+    return;
+  }
+  window_tree_client_->tree_->EmbedUsingToken(
+      server_id(), token, flags,
+      base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(),
+                     std::move(callback)));
 }
 
 std::unique_ptr<cc::mojo_embedder::AsyncLayerTreeFrameSink>
@@ -219,6 +231,43 @@
   return iter;
 }
 
+bool WindowPortMus::PrepareForEmbed() {
+  // Window::Init() must be called before Embed() (otherwise the server hasn't
+  // been told about the window).
+  DCHECK(window_->layer());
+
+  // The window server removes all children before embedding. In other words,
+  // it's generally an error to Embed() with existing children. So, fail early.
+  if (!window_->children().empty())
+    return false;
+
+  // Can only embed in windows created by this client.
+  if (window_mus_type() != WindowMusType::LOCAL)
+    return false;
+
+  // Don't allow an embed when one exists. This could be handled, if the
+  // callback was converted to OnChangeCompleted(). To attempt to handle it
+  // without routing the callback over the WindowTreeClient pipe would result
+  // in problemcs because of ordering. The ordering problem is because there is
+  // the Embed() request, the callback, and OnEmbeddedAppDisconnected() (which
+  // originates from the server side).
+  if (has_embedding_)
+    return false;
+
+  has_embedding_ = true;
+  return true;
+}
+
+// static
+void WindowPortMus::OnEmbedAck(
+    base::WeakPtr<WindowPortMus> window,
+    ws::mojom::WindowTree::EmbedCallback real_callback,
+    bool result) {
+  if (window && !result)
+    window->has_embedding_ = false;
+  std::move(real_callback).Run(window && result);
+}
+
 PropertyConverter* WindowPortMus::GetPropertyConverter() {
   return window_tree_client_->delegate_->GetPropertyConverter();
 }
@@ -311,7 +360,6 @@
 
 void WindowPortMus::SetFrameSinkIdFromServer(
     const viz::FrameSinkId& frame_sink_id) {
-  DCHECK(window_mus_type() == WindowMusType::EMBED_IN_OWNER);
   embed_frame_sink_id_ = frame_sink_id;
   window_->SetEmbedFrameSinkId(embed_frame_sink_id_);
   UpdatePrimarySurfaceId();
@@ -449,6 +497,7 @@
 }
 
 void WindowPortMus::NotifyEmbeddedAppDisconnected() {
+  has_embedding_ = false;
   for (WindowObserver& observer : *GetObservers(window_))
     observer.OnEmbeddedAppDisconnected(window_);
 }
@@ -603,10 +652,8 @@
 }
 
 void WindowPortMus::UpdatePrimarySurfaceId() {
-  if (window_mus_type() != WindowMusType::EMBED_IN_OWNER &&
-      window_mus_type() != WindowMusType::LOCAL) {
+  if (window_mus_type() != WindowMusType::LOCAL)
     return;
-  }
 
   if (!window_->IsEmbeddingClient() || !local_surface_id_.is_valid())
     return;
@@ -617,10 +664,8 @@
 }
 
 void WindowPortMus::UpdateClientSurfaceEmbedder() {
-  if (window_mus_type() != WindowMusType::EMBED_IN_OWNER &&
-      window_mus_type() != WindowMusType::LOCAL) {
+  if (!window_->IsEmbeddingClient())
     return;
-  }
 
   if (!client_surface_embedder_) {
     client_surface_embedder_ = std::make_unique<ClientSurfaceEmbedder>(
diff --git a/ui/aura/mus/window_port_mus.h b/ui/aura/mus/window_port_mus.h
index 8148624..c56b0db 100644
--- a/ui/aura/mus/window_port_mus.h
+++ b/ui/aura/mus/window_port_mus.h
@@ -45,7 +45,6 @@
 class ClientSurfaceEmbedder;
 class PropertyConverter;
 class Window;
-class WindowPortMusTest;
 class WindowTreeClient;
 class WindowTreeClientPrivate;
 class WindowTreeHostMus;
@@ -106,7 +105,7 @@
   viz::FrameSinkId GenerateFrameSinkIdFromServerId() const;
 
  private:
-  friend class WindowPortMusTest;
+  friend class WindowPortMusTestHelper;
   friend class WindowTreeClient;
   friend class WindowTreeClientPrivate;
   friend class WindowTreeHostMus;
@@ -221,6 +220,16 @@
   ServerChanges::iterator FindChangeByTypeAndData(const ServerChangeType type,
                                                   const ServerChangeData& data);
 
+  // Called to setup state necessary for an embedding. Returns false if an
+  // embedding is not allowed in this window.
+  bool PrepareForEmbed();
+
+  // Called from OnEmbed() with the result of the embedding. |real_callback| is
+  // the callback supplied to the embed call.
+  static void OnEmbedAck(base::WeakPtr<WindowPortMus> window,
+                         ws::mojom::WindowTree::EmbedCallback real_callback,
+                         bool result);
+
   PropertyConverter* GetPropertyConverter();
 
   // WindowMus:
@@ -317,6 +326,9 @@
   // See description in single place that changes the value for details.
   bool should_restack_transient_children_ = true;
 
+  // True if this window has an embedding.
+  bool has_embedding_ = false;
+
   // When a frame sink is created
   // for a local aura::Window, we need keep a weak ptr of it, so we can update
   // the local surface id when necessary.
diff --git a/ui/aura/mus/window_port_mus_unittest.cc b/ui/aura/mus/window_port_mus_unittest.cc
index 0e05b58..fa492c8 100644
--- a/ui/aura/mus/window_port_mus_unittest.cc
+++ b/ui/aura/mus/window_port_mus_unittest.cc
@@ -7,26 +7,15 @@
 #include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/mus/client_surface_embedder.h"
+#include "ui/aura/test/aura_mus_test_base.h"
 #include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
 #include "ui/aura/window.h"
 #include "ui/base/ui_base_features.h"
 
 namespace aura {
 
-class WindowPortMusTest : public test::AuraTestBase {
- public:
-  WindowPortMusTest() { EnableMusWithTestWindowTree(); }
-
-  ~WindowPortMusTest() override = default;
-
-  base::WeakPtr<cc::LayerTreeFrameSink> GetFrameSinkFor(Window* window) {
-    auto* window_mus = WindowPortMus::Get(window);
-    return window_mus->local_layer_tree_frame_sink_;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WindowPortMusTest);
-};
+using WindowPortMusTest = test::AuraMusClientTestBase;
 
 // TODO(sadrul): https://crbug.com/842361.
 TEST_F(WindowPortMusTest,
@@ -45,7 +34,7 @@
       window.CreateLayerTreeFrameSink());
   EXPECT_TRUE(frame_sink.get());
 
-  auto mus_frame_sink = GetFrameSinkFor(&window);
+  auto mus_frame_sink = WindowPortMusTestHelper(&window).GetFrameSink();
   ASSERT_TRUE(mus_frame_sink);
   auto frame_sink_local_surface_id =
       static_cast<cc::mojo_embedder::AsyncLayerTreeFrameSink*>(
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 50227f6..ffca8b77 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -290,53 +290,12 @@
   tree_->UnattachFrameSinkId(window->server_id());
 }
 
-void WindowTreeClient::Embed(Window* window,
-                             ws::mojom::WindowTreeClientPtr client,
-                             uint32_t flags,
-                             ws::mojom::WindowTree::EmbedCallback callback) {
-  DCHECK(tree_);
-  // Window::Init() must be called before Embed() (otherwise the server hasn't
-  // been told about the window).
-  DCHECK(window->layer());
-  if (!window->children().empty()) {
-    // The window server removes all children before embedding. In other words,
-    // it's generally an error to Embed() with existing children. So, fail
-    // early.
-    std::move(callback).Run(false);
-    return;
-  }
-
-  tree_->Embed(WindowMus::Get(window)->server_id(), std::move(client), flags,
-               std::move(callback));
-}
-
 void WindowTreeClient::ScheduleEmbed(
     ws::mojom::WindowTreeClientPtr client,
     base::OnceCallback<void(const base::UnguessableToken&)> callback) {
   tree_->ScheduleEmbed(std::move(client), std::move(callback));
 }
 
-void WindowTreeClient::EmbedUsingToken(
-    Window* window,
-    const base::UnguessableToken& token,
-    uint32_t flags,
-    ws::mojom::WindowTree::EmbedCallback callback) {
-  DCHECK(tree_);
-  // Window::Init() must be called before Embed() (otherwise the server hasn't
-  // been told about the window).
-  DCHECK(window->layer());
-  if (!window->children().empty()) {
-    // The window server removes all children before embedding. In other words,
-    // it's generally an error to Embed() with existing children. So, fail
-    // early.
-    std::move(callback).Run(false);
-    return;
-  }
-
-  tree_->EmbedUsingToken(WindowMus::Get(window)->server_id(), token, flags,
-                         std::move(callback));
-}
-
 void WindowTreeClient::AttachCompositorFrameSink(
     ws::Id window_id,
     viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
@@ -736,16 +695,17 @@
       ScheduleInFlightChange(std::make_unique<InFlightBoundsChange>(
           this, window, old_bounds, window->GetLocalSurfaceId()));
   base::Optional<viz::LocalSurfaceId> local_surface_id;
-  if (window->window_mus_type() == WindowMusType::EMBED_IN_OWNER ||
+  if (window->GetWindow()->IsEmbeddingClient() ||
       window->HasLocalLayerTreeFrameSink()) {
     // Do not use ConvertRectToPixel, enclosing rects cause problems.
     const gfx::Size size = gfx::ScaleToCeiledSize(
         new_bounds.size(), window->GetDeviceScaleFactor());
     local_surface_id = window->GetOrAllocateLocalSurfaceId(size);
     // |window_tree_host| may be null if this is called during creation of
-    // the window associated with the WindowTreeHostMus.
+    // the window associated with the WindowTreeHostMus, or if there is an
+    // embedding.
     WindowTreeHost* window_tree_host = window->GetWindow()->GetHost();
-    if (window_tree_host)
+    if (window_tree_host && window_tree_host->window() == window->GetWindow())
       window_tree_host->compositor()->OnChildResizing();
   }
   tree_->SetWindowBounds(change_id, window->server_id(), new_bounds,
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index 0c62b661..42348fd9 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -145,19 +145,6 @@
                            const viz::FrameSinkId& child_frame_sink_id);
   void UnregisterFrameSinkId(WindowMus* window);
 
-  // Embeds a new client in |window|. |flags| is a bitmask of the values defined
-  // by kEmbedFlag*; 0 gives default behavior. |callback| is called to indicate
-  // whether the embedding succeeded or failed and may be called immediately if
-  // the embedding is known to fail.
-  void Embed(Window* window,
-             ws::mojom::WindowTreeClientPtr client,
-             uint32_t flags,
-             ws::mojom::WindowTree::EmbedCallback callback);
-  void EmbedUsingToken(Window* window,
-                       const base::UnguessableToken& token,
-                       uint32_t flags,
-                       ws::mojom::WindowTree::EmbedCallback callback);
-
   // Schedules an embed of a client. See
   // ws::mojom::WindowTreeClient::ScheduleEmbed() for details.
   void ScheduleEmbed(
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 4281959c..003f0278 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -39,6 +39,7 @@
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/test/aura_mus_test_base.h"
 #include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
 #include "ui/aura/test/test_screen.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -273,11 +274,8 @@
 // reverted if the server replied that the change failed.
 TEST_F(WindowTreeClientTest, SetBoundsFailedLocalSurfaceId) {
   Window window(nullptr);
-  // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
-  // when their sizes change.
-  window.SetProperty(aura::client::kEmbedType,
-                     aura::client::WindowEmbedType::EMBED_IN_OWNER);
   window.Init(ui::LAYER_NOT_DRAWN);
+  WindowPortMusTestHelper(&window).SimulateEmbedding();
 
   const gfx::Rect original_bounds(window.bounds());
   const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
@@ -299,70 +297,26 @@
                         WindowTreeClientTestSurfaceSync,
                         ::testing::Bool());
 
-// Verifies that a ClientSurfaceEmbedder is created for a window once it has
-// a bounds, and a valid FrameSinkId.
-TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderOnValidEmbedding) {
+// Verifies that windows with an embedding create a ClientSurfaceEmbedder.
+TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderCreated) {
   Window window(nullptr);
-  // EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds when their sizes
-  // change.
-  window.SetProperty(aura::client::kEmbedType,
-                     aura::client::WindowEmbedType::EMBED_IN_OWNER);
   window.Init(ui::LAYER_NOT_DRAWN);
+  WindowPortMusTestHelper(&window).SimulateEmbedding();
 
   // The window will allocate a viz::LocalSurfaceId once it has a bounds.
-  WindowMus* window_mus = WindowMus::Get(&window);
-  ASSERT_NE(nullptr, window_mus);
-  EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid());
+  WindowPortMus* window_port_mus = WindowPortMus::Get(&window);
+  ASSERT_NE(nullptr, window_port_mus);
+  EXPECT_FALSE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid());
+  // A ClientSurfaceEmbedder is only created once there is bounds and a
+  // FrameSinkId.
+  EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder());
   gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
   ASSERT_NE(new_bounds, window.bounds());
   window.SetBounds(new_bounds);
   EXPECT_EQ(new_bounds, window.bounds());
-  EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid());
+  EXPECT_TRUE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid());
 
-  // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and
-  // a valid FrameSinkId.
-  WindowPortMus* window_port_mus = WindowPortMus::Get(&window);
-  ASSERT_NE(nullptr, window_port_mus);
-  EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder());
-
-  // Now that the window has a valid FrameSinkId, it can embed the client in a
-  // CompositorFrame.
-  window_tree_client()->OnFrameSinkIdAllocated(server_id(&window),
-                                               viz::FrameSinkId(1, 1));
-  ClientSurfaceEmbedder* client_surface_embedder =
-      window_port_mus->client_surface_embedder();
-  ASSERT_NE(nullptr, client_surface_embedder);
-}
-
-// Verifies that EMBED_IN_OWNER windows do not gutter.
-TEST_P(WindowTreeClientTestSurfaceSync, NoEmbedInOwnerGutter) {
-  Window window(nullptr);
-  // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
-  // when their sizes change.
-  window.SetProperty(aura::client::kEmbedType,
-                     aura::client::WindowEmbedType::EMBED_IN_OWNER);
-  window.Init(ui::LAYER_NOT_DRAWN);
-
-  // The window will allocate a viz::LocalSurfaceId once it has a bounds.
-  WindowMus* window_mus = WindowMus::Get(&window);
-  ASSERT_NE(nullptr, window_mus);
-  EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid());
-  gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
-  ASSERT_NE(new_bounds, window.bounds());
-  window.SetBounds(new_bounds);
-  EXPECT_EQ(new_bounds, window.bounds());
-  EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid());
-
-  // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and
-  // a valid FrameSinkId.
-  WindowPortMus* window_port_mus = WindowPortMus::Get(&window);
-  ASSERT_NE(nullptr, window_port_mus);
-  EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder());
-
-  // Now that the window has a valid FrameSinkId, it can embed the client in a
-  // CompositorFrame.
-  window_tree_client()->OnFrameSinkIdAllocated(server_id(&window),
-                                               viz::FrameSinkId(1, 1));
+  // Once the bounds have been set, the ClientSurfaceEmbedder should be created.
   ClientSurfaceEmbedder* client_surface_embedder =
       window_port_mus->client_surface_embedder();
   ASSERT_NE(nullptr, client_surface_embedder);
@@ -376,11 +330,8 @@
 TEST_P(WindowTreeClientTestSurfaceSync, SetBoundsLocalSurfaceIdChanges) {
   ASSERT_EQ(base::nullopt, window_tree()->last_local_surface_id());
   Window window(nullptr);
-  // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
-  // when their sizes change.
-  window.SetProperty(aura::client::kEmbedType,
-                     aura::client::WindowEmbedType::EMBED_IN_OWNER);
   window.Init(ui::LAYER_NOT_DRAWN);
+  WindowPortMusTestHelper(&window).SimulateEmbedding();
 
   // Resize the window and verify that we've allocated a viz::LocalSurfaceId.
   const gfx::Rect new_bounds(0, 0, 100, 100);
diff --git a/ui/aura/test/mus/window_port_mus_test_helper.cc b/ui/aura/test/mus/window_port_mus_test_helper.cc
new file mode 100644
index 0000000..98652a1
--- /dev/null
+++ b/ui/aura/test/mus/window_port_mus_test_helper.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
+
+#include "ui/aura/mus/window_port_mus.h"
+#include "ui/aura/window.h"
+
+namespace aura {
+
+// Start with something large that shouldn't conflict with any other values.
+// static
+uint32_t WindowPortMusTestHelper::next_client_id_ = 10001;
+
+WindowPortMusTestHelper::WindowPortMusTestHelper(Window* window)
+    : window_port_mus_(WindowPortMus::Get(window)) {
+  DCHECK(window_port_mus_);
+}
+
+WindowPortMusTestHelper::~WindowPortMusTestHelper() = default;
+
+void WindowPortMusTestHelper::SimulateEmbedding() {
+  window_port_mus_->GetWindow()->SetEmbedFrameSinkId(
+      viz::FrameSinkId(next_client_id_++, 1));
+}
+
+base::WeakPtr<cc::LayerTreeFrameSink> WindowPortMusTestHelper::GetFrameSink() {
+  return window_port_mus_->local_layer_tree_frame_sink_;
+}
+
+}  // namespace aura
diff --git a/ui/aura/test/mus/window_port_mus_test_helper.h b/ui/aura/test/mus/window_port_mus_test_helper.h
new file mode 100644
index 0000000..860c763
--- /dev/null
+++ b/ui/aura/test/mus/window_port_mus_test_helper.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_TEST_MUS_WINDOW_PORT_MUS_TEST_HELPER_H_
+#define UI_AURA_TEST_MUS_WINDOW_PORT_MUS_TEST_HELPER_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+
+namespace cc {
+class LayerTreeFrameSink;
+}
+
+namespace aura {
+
+class Window;
+class WindowPortMus;
+
+class WindowPortMusTestHelper {
+ public:
+  explicit WindowPortMusTestHelper(Window* window);
+  ~WindowPortMusTestHelper();
+
+  void SimulateEmbedding();
+
+  base::WeakPtr<cc::LayerTreeFrameSink> GetFrameSink();
+
+ private:
+  static uint32_t next_client_id_;
+
+  WindowPortMus* window_port_mus_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowPortMusTestHelper);
+};
+
+}  // namespace aura
+
+#endif  // UI_AURA_TEST_MUS_WINDOW_PORT_MUS_TEST_HELPER_H_
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 118d5a5..65ded87 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -452,6 +452,8 @@
       "blink/fling_booster_unittest.cc",
       "blink/input_handler_proxy_unittest.cc",
       "blink/input_scroll_elasticity_controller_unittest.cc",
+      "blink/prediction/input_predictor_unittest_helpers.cc",
+      "blink/prediction/input_predictor_unittest_helpers.h",
       "blink/prediction/kalman_predictor_unittest.cc",
       "blink/prediction/least_squares_predictor_unittest.cc",
       "blink/scroll_predictor_unittest.cc",
diff --git a/ui/events/blink/prediction/input_predictor_unittest.cc b/ui/events/blink/prediction/input_predictor_unittest.cc
deleted file mode 100644
index ec8a051..0000000
--- a/ui/events/blink/prediction/input_predictor_unittest.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
-#define UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
-
-#include "ui/events/blink/prediction/input_predictor.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/blink/blink_event_util.h"
-
-namespace {
-
-constexpr double kEpsilon = 0.1;
-
-}  // namespace
-
-namespace ui {
-
-// Base class for predictor unit tests
-class InputPredictorTest : public testing::Test {
- public:
-  InputPredictorTest() {}
-
-  static base::TimeTicks FromMilliseconds(int64_t ms) {
-    return blink::WebInputEvent::GetStaticTimeStampForTests() +
-           base::TimeDelta::FromMilliseconds(ms);
-  }
-
-  void ValidatePredictor(const std::vector<double>& x,
-                         const std::vector<double>& y,
-                         const std::vector<double>& timestamp_ms) {
-    predictor_->Reset();
-    for (size_t i = 0; i < timestamp_ms.size(); i++) {
-      if (predictor_->HasPrediction()) {
-        ui::InputPredictor::InputData result;
-        EXPECT_TRUE(predictor_->GeneratePrediction(
-            FromMilliseconds(timestamp_ms[i]), &result));
-        EXPECT_NEAR(result.pos.x(), x[i], kEpsilon);
-        EXPECT_NEAR(result.pos.y(), y[i], kEpsilon);
-      }
-      InputPredictor::InputData data = {gfx::PointF(x[i], y[i]),
-                                        FromMilliseconds(timestamp_ms[i])};
-      predictor_->Update(data);
-    }
-  }
-
- protected:
-  std::unique_ptr<InputPredictor> predictor_;
-
-  DISALLOW_COPY_AND_ASSIGN(InputPredictorTest);
-};
-
-}  // namespace ui
-
-#endif  // UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
diff --git a/ui/events/blink/prediction/input_predictor_unittest_helpers.cc b/ui/events/blink/prediction/input_predictor_unittest_helpers.cc
new file mode 100644
index 0000000..9912ea6
--- /dev/null
+++ b/ui/events/blink/prediction/input_predictor_unittest_helpers.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
+
+namespace ui {
+
+InputPredictorTest::InputPredictorTest() = default;
+InputPredictorTest::~InputPredictorTest() = default;
+
+void InputPredictorTest::ValidatePredictor(
+    const std::vector<double>& x,
+    const std::vector<double>& y,
+    const std::vector<double>& timestamp_ms) {
+  predictor_->Reset();
+  for (size_t i = 0; i < timestamp_ms.size(); i++) {
+    if (predictor_->HasPrediction()) {
+      ui::InputPredictor::InputData result;
+      EXPECT_TRUE(predictor_->GeneratePrediction(
+          FromMilliseconds(timestamp_ms[i]), &result));
+      EXPECT_NEAR(result.pos.x(), x[i], kEpsilon);
+      EXPECT_NEAR(result.pos.y(), y[i], kEpsilon);
+    }
+    InputPredictor::InputData data = {gfx::PointF(x[i], y[i]),
+                                      FromMilliseconds(timestamp_ms[i])};
+    predictor_->Update(data);
+  }
+}
+
+}  // namespace ui
diff --git a/ui/events/blink/prediction/input_predictor_unittest_helpers.h b/ui/events/blink/prediction/input_predictor_unittest_helpers.h
new file mode 100644
index 0000000..569d7a2e
--- /dev/null
+++ b/ui/events/blink/prediction/input_predictor_unittest_helpers.h
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
+#define UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
+
+#include "ui/events/blink/prediction/input_predictor.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/blink/blink_event_util.h"
+
+namespace ui {
+
+// Base class for predictor unit tests
+class InputPredictorTest : public testing::Test {
+ public:
+  InputPredictorTest();
+  ~InputPredictorTest() override;
+
+  static base::TimeTicks FromMilliseconds(int64_t ms) {
+    return blink::WebInputEvent::GetStaticTimeStampForTests() +
+           base::TimeDelta::FromMilliseconds(ms);
+  }
+
+  void ValidatePredictor(const std::vector<double>& x,
+                         const std::vector<double>& y,
+                         const std::vector<double>& timestamp_ms);
+
+ protected:
+  static constexpr double kEpsilon = 0.1;
+
+  std::unique_ptr<InputPredictor> predictor_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputPredictorTest);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
diff --git a/ui/events/blink/prediction/kalman_predictor_unittest.cc b/ui/events/blink/prediction/kalman_predictor_unittest.cc
index 6a4074cf..4d8a1d8 100644
--- a/ui/events/blink/prediction/kalman_predictor_unittest.cc
+++ b/ui/events/blink/prediction/kalman_predictor_unittest.cc
@@ -5,7 +5,7 @@
 #include <vector>
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/blink/prediction/input_predictor_unittest.cc"
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
 #include "ui/events/blink/prediction/kalman_predictor.h"
 
 namespace ui {
@@ -13,7 +13,6 @@
 namespace {
 
 constexpr uint32_t kExpectedStableIterNum = 4;
-constexpr double kEpsilon = 0.001;
 
 struct DataSet {
   double initial_observation;
@@ -26,6 +25,7 @@
 void ValidateSingleKalmanFilter(const DataSet& data) {
   std::unique_ptr<KalmanFilter> kalman_filter =
       std::make_unique<KalmanFilter>();
+  constexpr double kEpsilon = 0.001;
   constexpr double kDtMillisecond = 8;
   kalman_filter->Update(data.initial_observation, kDtMillisecond);
   for (size_t i = 0; i < data.observation.size(); i++) {
diff --git a/ui/events/blink/prediction/least_squares_predictor.cc b/ui/events/blink/prediction/least_squares_predictor.cc
index 94f1be7..534d3de 100644
--- a/ui/events/blink/prediction/least_squares_predictor.cc
+++ b/ui/events/blink/prediction/least_squares_predictor.cc
@@ -10,12 +10,12 @@
 
 namespace {
 
-constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
-
 // Solve XB = y.
 static bool SolveLeastSquares(const gfx::Matrix3F& x,
                               const std::deque<double>& y,
                               gfx::Vector3dF& result) {
+  constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
+
   // return last point if y didn't change.
   if (std::abs(y[0] - y[1]) < kEpsilon && std::abs(y[1] - y[2]) < kEpsilon) {
     result = gfx::Vector3dF(y[2], 0, 0);
diff --git a/ui/events/blink/prediction/least_squares_predictor_unittest.cc b/ui/events/blink/prediction/least_squares_predictor_unittest.cc
index c4836f0..d1d2c032 100644
--- a/ui/events/blink/prediction/least_squares_predictor_unittest.cc
+++ b/ui/events/blink/prediction/least_squares_predictor_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "ui/events/blink/prediction/least_squares_predictor.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/blink/prediction/input_predictor_unittest.cc"
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/gfx/gpu_memory_buffer.cc b/ui/gfx/gpu_memory_buffer.cc
index e6751d8..5da026a 100644
--- a/ui/gfx/gpu_memory_buffer.cc
+++ b/ui/gfx/gpu_memory_buffer.cc
@@ -8,7 +8,8 @@
 
 namespace gfx {
 
-GpuMemoryBufferHandle::GpuMemoryBufferHandle() : type(EMPTY_BUFFER), id(0) {}
+GpuMemoryBufferHandle::GpuMemoryBufferHandle()
+    : type(EMPTY_BUFFER), id(0), offset(0), stride(0) {}
 
 // TODO(crbug.com/863011): Reset |type| and possibly the handles on the
 // moved-from object.
diff --git a/ui/latency/latency_tracker.cc b/ui/latency/latency_tracker.cc
index 35c320b..ef6ce721 100644
--- a/ui/latency/latency_tracker.cc
+++ b/ui/latency/latency_tracker.cc
@@ -322,26 +322,31 @@
   }
 
   base::TimeTicks renderer_swap_timestamp;
-  bool found_component =
+  bool found_renderer_swap_component =
       latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
                           &renderer_swap_timestamp);
-  DCHECK_AND_RETURN_ON_FAIL(found_component);
-
-  UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
-      "Event.Latency." + scroll_name + "." + input_modality +
-          ".HandledToRendererSwap2_" + thread_name,
-      rendering_scheduled_timestamp, renderer_swap_timestamp);
 
   base::TimeTicks browser_received_swap_timestamp;
-  found_component =
+  bool found_received_frame_component =
       latency.FindLatency(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
                           &browser_received_swap_timestamp);
-  DCHECK_AND_RETURN_ON_FAIL(found_component);
+  DCHECK_AND_RETURN_ON_FAIL(found_received_frame_component);
 
-  UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
-      "Event.Latency." + scroll_name + "." + input_modality +
-          ".RendererSwapToBrowserNotified2",
-      renderer_swap_timestamp, browser_received_swap_timestamp);
+  // If we're committing to the active tree, there will never be a renderer
+  // swap. In this case, don't record the two histogram values for the periods
+  // surrounding the renderer swap. We could assign the total time to one or the
+  // other of them, but that would likely skew statistics.
+  if (found_renderer_swap_component) {
+    UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
+        "Event.Latency." + scroll_name + "." + input_modality +
+            ".HandledToRendererSwap2_" + thread_name,
+        rendering_scheduled_timestamp, renderer_swap_timestamp);
+
+    UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
+        "Event.Latency." + scroll_name + "." + input_modality +
+            ".RendererSwapToBrowserNotified2",
+        renderer_swap_timestamp, browser_received_swap_timestamp);
+  }
 
   UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
       "Event.Latency." + scroll_name + "." + input_modality +
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index 8ca9ae5..a3782fe 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -11,6 +11,7 @@
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
+#include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/image_skia_operations.h"
@@ -241,6 +242,15 @@
   return true;
 }
 
+void MessageView::PaintChildren(const views::PaintInfo& paint_info) {
+  views::View::PaintChildren(paint_info);
+
+  // Paint focus ring on top of all the children.
+  ui::PaintRecorder recorder(paint_info.context(), size());
+  views::Painter::PaintFocusPainter(this, recorder.canvas(),
+                                    focus_painter_.get());
+}
+
 void MessageView::OnPaint(gfx::Canvas* canvas) {
   if (ShouldShowAeroShadowBorder()) {
     // If the border is shadow, paint border first.
@@ -249,7 +259,6 @@
   } else {
     views::View::OnPaint(canvas);
   }
-  views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
 }
 
 void MessageView::OnFocus() {
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index 6a62b89..49138c6 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -111,6 +111,7 @@
   void OnMouseReleased(const ui::MouseEvent& event) override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   bool OnKeyReleased(const ui::KeyEvent& event) override;
+  void PaintChildren(const views::PaintInfo& paint_info) override;
   void OnPaint(gfx::Canvas* canvas) override;
   void OnFocus() override;
   void OnBlur() override;
diff --git a/ui/views/mus/remote_view/remote_view_host.cc b/ui/views/mus/remote_view/remote_view_host.cc
index a203d2b..70d35ea 100644
--- a/ui/views/mus/remote_view/remote_view_host.cc
+++ b/ui/views/mus/remote_view/remote_view_host.cc
@@ -43,8 +43,6 @@
   embedding_root_->set_owned_by_parent(false);
 
   embedding_root_->SetName("RemoteViewHostWindow");
-  embedding_root_->SetProperty(aura::client::kEmbedType,
-                               aura::client::WindowEmbedType::EMBED_IN_OWNER);
   embedding_root_->SetType(aura::client::WINDOW_TYPE_CONTROL);
   embedding_root_->Init(ui::LAYER_NOT_DRAWN);
 
diff --git a/ui/webui/PLATFORM_OWNERS b/ui/webui/PLATFORM_OWNERS
index d5df6113..a93051bd 100644
--- a/ui/webui/PLATFORM_OWNERS
+++ b/ui/webui/PLATFORM_OWNERS
@@ -3,7 +3,6 @@
 dpapad@chromium.org
 dschuyler@chromium.org
 michaelpg@chromium.org
-pam@chromium.org
 scottchen@chromium.org
 stevenjb@chromium.org
 tommycli@chromium.org