diff --git a/DEPS b/DEPS
index 9691f1b..0f89d6bb 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '9f85d68887a61f93656dbfacdd3f978d510c02ee',
+  'skia_revision': 'e980174d0f3af8e497d9c38851114cc6a3c02e9a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '213c71950c7eb00f8ad53cf6c184cbecc1499d36',
+  'v8_revision': '4eb9e4f0e51b914cbe911f3f5a48672c43314040',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -1175,6 +1175,4 @@
   'src/third_party/android_tools',
   # ANGLE manages DEPS that it also owns the build files for, such as dEQP.
   ("src/third_party/angle", "DEPS.chromium"),
-  # SwiftShader manages DEPS that it also owns the build files for, such as Subzero.
-  ("src/third_party/swiftshader", "DEPS"),
 ]
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index ac2cb98..7645203 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -2269,8 +2269,17 @@
         if (callback != null) {
             jsCallback = new JavaScriptCallback() {
                 @Override
-                public void handleJavaScriptResult(String jsonResult) {
-                    callback.onReceiveValue(jsonResult);
+                public void handleJavaScriptResult(final String jsonResult) {
+                    // Post the application callback back to the current thread to ensure the
+                    // application callback is executed without any native code on the stack. This
+                    // so that any exception thrown by the application callback won't have to be
+                    // propagated through a native call stack.
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            callback.onReceiveValue(jsonResult);
+                        }
+                    });
                 }
             };
         }
diff --git a/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc
index b1b2d36..3bcda338 100644
--- a/base/task_scheduler/task_scheduler_impl.cc
+++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/memory/ptr_util.h"
 #include "base/task_scheduler/delayed_task_manager.h"
 #include "base/task_scheduler/scheduler_worker_pool_params.h"
 #include "base/task_scheduler/sequence.h"
@@ -53,10 +52,13 @@
 
 }  // namespace
 
-TaskSchedulerImpl::TaskSchedulerImpl(StringPiece name)
+TaskSchedulerImpl::TaskSchedulerImpl(
+    StringPiece name,
+    std::unique_ptr<TaskTrackerType> task_tracker)
     : name_(name),
       service_thread_("TaskSchedulerServiceThread"),
-      single_thread_task_runner_manager_(&task_tracker_,
+      task_tracker_(std::move(task_tracker)),
+      single_thread_task_runner_manager_(task_tracker_.get(),
                                          &delayed_task_manager_) {
   static_assert(arraysize(worker_pools_) == ENVIRONMENT_COUNT,
                 "The size of |worker_pools_| must match ENVIRONMENT_COUNT.");
@@ -68,7 +70,7 @@
        ++environment_type) {
     worker_pools_[environment_type] = MakeUnique<SchedulerWorkerPoolImpl>(
         name_ + kEnvironmentParams[environment_type].name_suffix,
-        kEnvironmentParams[environment_type].priority_hint, &task_tracker_,
+        kEnvironmentParams[environment_type].priority_hint, task_tracker_.get(),
         &delayed_task_manager_);
   }
 }
@@ -96,11 +98,11 @@
 #if defined(OS_POSIX) && !defined(OS_NACL_SFI)
   // Needs to happen after starting the service thread to get its
   // message_loop().
-  task_tracker_.set_watch_file_descriptor_message_loop(
+  task_tracker_->set_watch_file_descriptor_message_loop(
       static_cast<MessageLoopForIO*>(service_thread_.message_loop()));
 
 #if DCHECK_IS_ON()
-  task_tracker_.set_service_thread_handle(service_thread_.GetThreadHandle());
+  task_tracker_->set_service_thread_handle(service_thread_.GetThreadHandle());
 #endif  // DCHECK_IS_ON()
 #endif  // defined(OS_POSIX) && !defined(OS_NACL_SFI)
 
@@ -179,11 +181,11 @@
 
 void TaskSchedulerImpl::Shutdown() {
   // TODO(fdoray): Increase the priority of BACKGROUND tasks blocking shutdown.
-  task_tracker_.Shutdown();
+  task_tracker_->Shutdown();
 }
 
 void TaskSchedulerImpl::FlushForTesting() {
-  task_tracker_.Flush();
+  task_tracker_->Flush();
 }
 
 void TaskSchedulerImpl::JoinForTesting() {
diff --git a/base/task_scheduler/task_scheduler_impl.h b/base/task_scheduler/task_scheduler_impl.h
index 4907ce2..1b05baf9 100644
--- a/base/task_scheduler/task_scheduler_impl.h
+++ b/base/task_scheduler/task_scheduler_impl.h
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string_piece.h"
 #include "base/synchronization/atomic_flag.h"
@@ -38,8 +39,19 @@
 // Default TaskScheduler implementation. This class is thread-safe.
 class BASE_EXPORT TaskSchedulerImpl : public TaskScheduler {
  public:
-  // |name| is used to label threads and histograms.
-  explicit TaskSchedulerImpl(StringPiece name);
+  using TaskTrackerType =
+#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
+      TaskTrackerPosix;
+#else
+      TaskTracker;
+#endif
+
+  // |name| is used to label threads and histograms. |task_tracker| can be used
+  // for tests that need more execution control. By default, you get the
+  // production TaskTracker.
+  explicit TaskSchedulerImpl(StringPiece name,
+                             std::unique_ptr<TaskTrackerType> task_tracker =
+                                 MakeUnique<TaskTrackerType>());
   ~TaskSchedulerImpl() override;
 
   // TaskScheduler:
@@ -74,11 +86,7 @@
 
   const std::string name_;
   Thread service_thread_;
-#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
-  TaskTrackerPosix task_tracker_;
-#else
-  TaskTracker task_tracker_;
-#endif
+  const std::unique_ptr<TaskTrackerType> task_tracker_;
   DelayedTaskManager delayed_task_manager_;
   SchedulerSingleThreadTaskRunnerManager single_thread_task_runner_manager_;
 
diff --git a/base/task_scheduler/task_tracker.cc b/base/task_scheduler/task_tracker.cc
index 55230aa9..5509e32 100644
--- a/base/task_scheduler/task_tracker.cc
+++ b/base/task_scheduler/task_tracker.cc
@@ -388,6 +388,10 @@
 }
 #endif
 
+int TaskTracker::GetNumPendingUndelayedTasksForTesting() const {
+  return subtle::Acquire_Load(&num_pending_undelayed_tasks_);
+}
+
 bool TaskTracker::BeforePostTask(TaskShutdownBehavior shutdown_behavior) {
   if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
     // BLOCK_SHUTDOWN tasks block shutdown between the moment they are posted
diff --git a/base/task_scheduler/task_tracker.h b/base/task_scheduler/task_tracker.h
index 1a1977d..b80e661c 100644
--- a/base/task_scheduler/task_tracker.h
+++ b/base/task_scheduler/task_tracker.h
@@ -90,6 +90,10 @@
   virtual bool IsPostingBlockShutdownTaskAfterShutdownAllowed();
 #endif
 
+  // Returns the number of undelayed tasks that haven't completed their
+  // execution.
+  int GetNumPendingUndelayedTasksForTesting() const;
+
  private:
   class State;
 
diff --git a/base/task_scheduler/task_tracker_posix.h b/base/task_scheduler/task_tracker_posix.h
index a98b464c..7a17f75 100644
--- a/base/task_scheduler/task_tracker_posix.h
+++ b/base/task_scheduler/task_tracker_posix.h
@@ -50,11 +50,12 @@
   }
 #endif
 
- private:
+ protected:
   // TaskTracker:
   void PerformRunTask(std::unique_ptr<Task> task,
                       const SequenceToken& sequence_token) override;
 
+ private:
 #if DCHECK_IS_ON()
   bool IsPostingBlockShutdownTaskAfterShutdownAllowed() override;
 #endif
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc
index 672ffb05..7ca8af07 100644
--- a/base/test/scoped_task_environment.cc
+++ b/base/test/scoped_task_environment.cc
@@ -5,8 +5,12 @@
 #include "base/test/scoped_task_environment.h"
 
 #include "base/run_loop.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/task_scheduler/task_scheduler.h"
+#include "base/task_scheduler/task_scheduler_impl.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 
 namespace base {
@@ -21,25 +25,70 @@
   // MessageLoop::TaskObserver:
   void WillProcessTask(const PendingTask& pending_task) override {}
   void DidProcessTask(const PendingTask& pending_task) override {
-    ran_task_ = true;
+    ++task_count_;
   }
 
-  bool ran_task() const { return ran_task_; }
+  int task_count() const { return task_count_; }
 
  private:
-  bool ran_task_ = false;
+  int task_count_ = 0;
+
   DISALLOW_COPY_AND_ASSIGN(TaskObserver);
 };
 
 }  // namespace
 
-ScopedTaskEnvironment::ScopedTaskEnvironment(MainThreadType main_thread_type)
-    : message_loop_(main_thread_type == MainThreadType::DEFAULT
+class ScopedTaskEnvironment::TestTaskTracker
+    : public internal::TaskSchedulerImpl::TaskTrackerType {
+ public:
+  TestTaskTracker(ScopedTaskEnvironment* outer);
+
+  void SetTaskQueueEmptyClosure(OnceClosure task_queue_empty_closure);
+
+  // Allow running tasks.
+  void AllowRunRask();
+
+  // Disallow running tasks. No-ops and returns false if a task is running.
+  bool DisallowRunTasks();
+
+ private:
+  friend class ScopedTaskEnvironment;
+
+  // internal::TaskSchedulerImpl::TaskTrackerType:
+  void PerformRunTask(std::unique_ptr<internal::Task> task,
+                      const SequenceToken& sequence_token) override;
+
+  ScopedTaskEnvironment* const outer_;
+
+  // Synchronizes accesses to members below.
+  Lock lock_;
+
+  // Closure posted to the main thread when the task queue becomes empty.
+  OnceClosure task_queue_empty_closure_;
+
+  // True if running tasks is allowed.
+  bool can_run_tasks_ = true;
+
+  // Signaled when |can_run_tasks_| becomes true.
+  ConditionVariable can_run_tasks_cv_;
+
+  // Number of tasks that are currently running.
+  int num_tasks_running_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestTaskTracker);
+};
+
+ScopedTaskEnvironment::ScopedTaskEnvironment(
+    MainThreadType main_thread_type,
+    ExecutionControlMode execution_control_mode)
+    : execution_control_mode_(execution_control_mode),
+      message_loop_(main_thread_type == MainThreadType::DEFAULT
                         ? MessageLoop::TYPE_DEFAULT
                         : (main_thread_type == MainThreadType::UI
                                ? MessageLoop::TYPE_UI
-                               : MessageLoop::TYPE_IO)) {
-  DCHECK(!TaskScheduler::GetInstance());
+                               : MessageLoop::TYPE_IO)),
+      task_tracker_(new TestTaskTracker(this)) {
+  CHECK(!TaskScheduler::GetInstance());
 
   // Instantiate a TaskScheduler with 1 thread in each of its 4 pools. Threads
   // stay alive even when they don't have work.
@@ -48,10 +97,14 @@
   const SchedulerWorkerPoolParams worker_pool_params(
       SchedulerWorkerPoolParams::StandbyThreadPolicy::ONE, kMaxThreads,
       kSuggestedReclaimTime);
-  TaskScheduler::Create("ScopedTaskEnvironment");
+  TaskScheduler::SetInstance(MakeUnique<internal::TaskSchedulerImpl>(
+      "ScopedTaskEnvironment", WrapUnique(task_tracker_)));
   task_scheduler_ = TaskScheduler::GetInstance();
   TaskScheduler::GetInstance()->Start({worker_pool_params, worker_pool_params,
                                        worker_pool_params, worker_pool_params});
+
+  if (execution_control_mode_ == ExecutionControlMode::QUEUED)
+    CHECK(task_tracker_->DisallowRunTasks());
 }
 
 ScopedTaskEnvironment::~ScopedTaskEnvironment() {
@@ -59,10 +112,10 @@
   // infinite post loop in the remaining work but this isn't possible right now
   // because base::~MessageLoop() didn't use to do this and adding it here would
   // make the migration away from MessageLoop that much harder.
-
-  DCHECK_EQ(TaskScheduler::GetInstance(), task_scheduler_);
+  CHECK_EQ(TaskScheduler::GetInstance(), task_scheduler_);
   // Without FlushForTesting(), DeleteSoon() and ReleaseSoon() tasks could be
   // skipped, resulting in memory leaks.
+  task_tracker_->AllowRunRask();
   TaskScheduler::GetInstance()->FlushForTesting();
   TaskScheduler::GetInstance()->Shutdown();
   TaskScheduler::GetInstance()->JoinForTesting();
@@ -76,15 +129,104 @@
 
 void ScopedTaskEnvironment::RunUntilIdle() {
   for (;;) {
-    TaskScheduler::GetInstance()->FlushForTesting();
+    RunLoop run_loop;
 
+    // Register a closure to stop running tasks on the main thread when the
+    // TaskScheduler queue becomes empty.
+    task_tracker_->SetTaskQueueEmptyClosure(run_loop.QuitWhenIdleClosure());
+
+    // The closure registered above may never run if the TaskScheduler queue
+    // starts empty. Post a TaskScheduler tasks to make sure that the queue
+    // doesn't start empty.
+    PostTask(FROM_HERE, BindOnce(&DoNothing));
+
+    // Run main thread and TaskScheduler tasks.
+    task_tracker_->AllowRunRask();
     TaskObserver task_observer;
     MessageLoop::current()->AddTaskObserver(&task_observer);
-    RunLoop().RunUntilIdle();
+    run_loop.Run();
     MessageLoop::current()->RemoveTaskObserver(&task_observer);
 
-    if (!task_observer.ran_task())
+    // If the ExecutionControlMode is QUEUED and DisallowRunTasks() fails,
+    // another iteration is required to make sure that RunUntilIdle() doesn't
+    // return while TaskScheduler tasks are still allowed to run.
+    //
+    // If tasks other than the QuitWhenIdle closure ran on the main thread, they
+    // may have posted TaskScheduler tasks that didn't run yet. Another
+    // iteration is required to run them.
+    //
+    // Note: DisallowRunTasks() fails when a TaskScheduler task is running. A
+    // TaskScheduler task may be running after the TaskScheduler queue became
+    // empty even if no tasks ran on the main thread in these cases:
+    // - An undelayed task became ripe for execution.
+    // - A task was posted from an external thread.
+    if ((execution_control_mode_ == ExecutionControlMode::QUEUED &&
+         task_tracker_->DisallowRunTasks()) ||
+        task_observer.task_count() == 1) {
       return;
+    }
+  }
+}
+
+ScopedTaskEnvironment::TestTaskTracker::TestTaskTracker(
+    ScopedTaskEnvironment* outer)
+    : outer_(outer), can_run_tasks_cv_(&lock_) {}
+
+void ScopedTaskEnvironment::TestTaskTracker::SetTaskQueueEmptyClosure(
+    OnceClosure task_queue_empty_closure) {
+  AutoLock auto_lock(lock_);
+  CHECK(!task_queue_empty_closure_);
+  task_queue_empty_closure_ = std::move(task_queue_empty_closure);
+}
+
+void ScopedTaskEnvironment::TestTaskTracker::AllowRunRask() {
+  AutoLock auto_lock(lock_);
+  can_run_tasks_ = true;
+  can_run_tasks_cv_.Broadcast();
+}
+
+bool ScopedTaskEnvironment::TestTaskTracker::DisallowRunTasks() {
+  AutoLock auto_lock(lock_);
+
+  // Can't disallow run task if there are tasks running.
+  if (num_tasks_running_ > 0)
+    return false;
+
+  can_run_tasks_ = false;
+  return true;
+}
+
+void ScopedTaskEnvironment::TestTaskTracker::PerformRunTask(
+    std::unique_ptr<internal::Task> task,
+    const SequenceToken& sequence_token) {
+  {
+    AutoLock auto_lock(lock_);
+
+    while (!can_run_tasks_)
+      can_run_tasks_cv_.Wait();
+
+    ++num_tasks_running_;
+  }
+
+  internal::TaskSchedulerImpl::TaskTrackerType::PerformRunTask(std::move(task),
+                                                               sequence_token);
+
+  {
+    AutoLock auto_lock(lock_);
+
+    CHECK_GT(num_tasks_running_, 0);
+    CHECK(can_run_tasks_);
+
+    --num_tasks_running_;
+
+    // Notify the main thread when no undelayed tasks are queued and no task
+    // other than the current one is running.
+    if (num_tasks_running_ == 0 &&
+        GetNumPendingUndelayedTasksForTesting() == 1 &&
+        task_queue_empty_closure_) {
+      outer_->GetMainThreadTaskRunner()->PostTask(
+          FROM_HERE, std::move(task_queue_empty_closure_));
+    }
   }
 }
 
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h
index f46b516..6156c215 100644
--- a/base/test/scoped_task_environment.h
+++ b/base/test/scoped_task_environment.h
@@ -26,7 +26,9 @@
 // RunLoop::Run(UntilIdle) or ScopedTaskEnvironment::RunUntilIdle is called on
 // the thread where the ScopedTaskEnvironment lives.
 //
-// Tasks posted through base/task_scheduler/post_task.h run on dedicated threads
+// Tasks posted through base/task_scheduler/post_task.h run on dedicated
+// threads. If ExecutionControlMode is QUEUED, they run when RunUntilIdle() or
+// ~ScopedTaskEnvironment is called. If ExecutionControlMode is ASYNC, they run
 // as they are posted.
 //
 // All methods of ScopedTaskEnvironment must be called from the same thread.
@@ -61,8 +63,17 @@
     IO,
   };
 
+  enum class ExecutionControlMode {
+    // Tasks are queued and executed when RunUntilIdle() is called.
+    QUEUED,
+    // Tasks run as they are posted.
+    ASYNC,
+  };
+
   ScopedTaskEnvironment(
-      MainThreadType main_thread_type = MainThreadType::DEFAULT);
+      MainThreadType main_thread_type = MainThreadType::DEFAULT,
+      ExecutionControlMode execution_control_mode =
+          ExecutionControlMode::ASYNC);
 
   // Waits until no undelayed TaskScheduler tasks remain. Then, unregisters the
   // TaskScheduler and the (Thread|Sequenced)TaskRunnerHandle.
@@ -71,11 +82,15 @@
   // Returns a TaskRunner that schedules tasks on the main thread.
   scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner();
 
-  // Synchronously runs (Thread|Sequenced)TaskRunnerHandle tasks until no
-  // undelayed (Thread|Sequenced)TaskRunnerHandle or TaskScheduler tasks remain.
+  // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the
+  // TaskScheduler queues are empty.
   void RunUntilIdle();
 
  private:
+  class TestTaskTracker;
+
+  const ExecutionControlMode execution_control_mode_;
+
   // Note: |message_loop_| is an implementation detail and will be replaced in
   // the future, do NOT rely on the presence of a MessageLoop beyond
   // (Thread|Sequenced)TaskRunnerHandle and RunLoop.
@@ -83,6 +98,9 @@
 
   const TaskScheduler* task_scheduler_ = nullptr;
 
+  // Owned by |task_scheduler_|.
+  TestTaskTracker* const task_tracker_;
+
   DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment);
 };
 
diff --git a/base/test/scoped_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc
index 245cda28..fcc366dc 100644
--- a/base/test/scoped_task_environment_unittest.cc
+++ b/base/test/scoped_task_environment_unittest.cc
@@ -6,7 +6,10 @@
 
 #include "base/bind.h"
 #include "base/synchronization/atomic_flag.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/task_scheduler/post_task.h"
+#include "base/test/test_timeouts.h"
+#include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -22,11 +25,11 @@
   task_ran->Set();
 }
 
-}  // namespace
-
-TEST(ScopedTaskEnvironmentTest, RunUntilIdle) {
+void RunUntilIdleTest(
+    ScopedTaskEnvironment::ExecutionControlMode execution_control_mode) {
   AtomicFlag run_until_idle_returned;
-  ScopedTaskEnvironment scoped_task_environment;
+  ScopedTaskEnvironment scoped_task_environment(
+      ScopedTaskEnvironment::MainThreadType::DEFAULT, execution_control_mode);
 
   AtomicFlag first_main_thread_task_ran;
   ThreadTaskRunnerHandle::Get()->PostTask(
@@ -58,5 +61,76 @@
   EXPECT_TRUE(second_main_thread_task_ran.IsSet());
 }
 
+}  // namespace
+
+TEST(ScopedTaskEnvironmentTest, QueuedRunUntilIdle) {
+  RunUntilIdleTest(ScopedTaskEnvironment::ExecutionControlMode::QUEUED);
+}
+
+TEST(ScopedTaskEnvironmentTest, AsyncRunUntilIdle) {
+  RunUntilIdleTest(ScopedTaskEnvironment::ExecutionControlMode::ASYNC);
+}
+
+// Verify that tasks posted to an ExecutionControlMode::QUEUED
+// ScopedTaskEnvironment do not run outside of RunUntilIdle().
+TEST(ScopedTaskEnvironmentTest, QueuedTasksDoNotRunOutsideOfRunUntilIdle) {
+  ScopedTaskEnvironment scoped_task_environment(
+      ScopedTaskEnvironment::MainThreadType::DEFAULT,
+      ScopedTaskEnvironment::ExecutionControlMode::QUEUED);
+
+  AtomicFlag run_until_idle_called;
+  PostTask(FROM_HERE, BindOnce(
+                          [](AtomicFlag* run_until_idle_called) {
+                            EXPECT_TRUE(run_until_idle_called->IsSet());
+                          },
+                          Unretained(&run_until_idle_called)));
+  PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+  run_until_idle_called.Set();
+  scoped_task_environment.RunUntilIdle();
+
+  AtomicFlag other_run_until_idle_called;
+  PostTask(FROM_HERE, BindOnce(
+                          [](AtomicFlag* other_run_until_idle_called) {
+                            EXPECT_TRUE(other_run_until_idle_called->IsSet());
+                          },
+                          Unretained(&other_run_until_idle_called)));
+  PlatformThread::Sleep(TestTimeouts::tiny_timeout());
+  other_run_until_idle_called.Set();
+  scoped_task_environment.RunUntilIdle();
+}
+
+// Verify that a task posted to an ExecutionControlMode::QUEUED
+// ScopedTaskEnvironment can run without a call to RunUntilIdle().
+TEST(ScopedTaskEnvironmentTest, AsyncTasksRunAsTheyArePosted) {
+  ScopedTaskEnvironment scoped_task_environment(
+      ScopedTaskEnvironment::MainThreadType::DEFAULT,
+      ScopedTaskEnvironment::ExecutionControlMode::ASYNC);
+
+  WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
+                         WaitableEvent::InitialState::NOT_SIGNALED);
+  PostTask(FROM_HERE,
+           BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); },
+                    Unretained(&task_ran)));
+  task_ran.Wait();
+}
+
+// Verify that a task posted to an ExecutionControlMode::QUEUED
+// ScopedTaskEnvironment after a call to RunUntilIdle() can run without another
+// call to RunUntilIdle().
+TEST(ScopedTaskEnvironmentTest, AsyncTasksRunAsTheyArePostedAfterRunUntilIdle) {
+  ScopedTaskEnvironment scoped_task_environment(
+      ScopedTaskEnvironment::MainThreadType::DEFAULT,
+      ScopedTaskEnvironment::ExecutionControlMode::ASYNC);
+
+  scoped_task_environment.RunUntilIdle();
+
+  WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
+                         WaitableEvent::InitialState::NOT_SIGNALED);
+  PostTask(FROM_HERE,
+           BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); },
+                    Unretained(&task_ran)));
+  task_ran.Wait();
+}
+
 }  // namespace test
 }  // namespace base
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc
index fe1156e..d39b9e2 100644
--- a/cc/surfaces/compositor_frame_sink_support_unittest.cc
+++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -123,6 +123,7 @@
   void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
     *changed = true;
   }
+  void OnSurfaceDiscarded(const SurfaceId& surface_id) override {}
 
   void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
                                           size_t num_resource_ids) {
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index e3693207..846897b 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -412,6 +412,11 @@
 
 void Display::OnSurfaceCreated(const SurfaceInfo& surface_info) {}
 
+void Display::OnSurfaceDiscarded(const SurfaceId& surface_id) {
+  if (aggregator_)
+    aggregator_->ReleaseResources(surface_id);
+}
+
 const SurfaceId& Display::CurrentSurfaceId() {
   return current_surface_id_;
 }
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h
index 314cb405..df0f717 100644
--- a/cc/surfaces/display.h
+++ b/cc/surfaces/display.h
@@ -88,6 +88,7 @@
   // SurfaceObserver implementation.
   void OnSurfaceDamaged(const SurfaceId& surface, bool* changed) override;
   void OnSurfaceCreated(const SurfaceInfo& surface_info) override;
+  void OnSurfaceDiscarded(const SurfaceId& surface_id) override;
 
   bool has_scheduler() const { return !!scheduler_; }
   DirectRenderer* renderer_for_testing() const { return renderer_.get(); }
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index cbdb78c..0eb2b21 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -494,6 +494,8 @@
 }
 
 void SurfaceManager::SurfaceDiscarded(Surface* surface) {
+  for (auto& observer : observer_list_)
+    observer.OnSurfaceDiscarded(surface->surface_id());
   if (dependency_tracker_)
     dependency_tracker_->OnSurfaceDiscarded(surface);
 }
diff --git a/cc/surfaces/surface_observer.h b/cc/surfaces/surface_observer.h
index e1c182a..9b2fc1c5 100644
--- a/cc/surfaces/surface_observer.h
+++ b/cc/surfaces/surface_observer.h
@@ -18,6 +18,9 @@
   // Runs when a Surface is damaged. *changed should be set to true if this
   // causes a Display to be damaged.
   virtual void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) = 0;
+
+  // Called when a surface is garbage-collected.
+  virtual void OnSurfaceDiscarded(const SurfaceId& surface_id) = 0;
 };
 
 }  // namespace cc
diff --git a/cc/surfaces/surface_synchronization_unittest.cc b/cc/surfaces/surface_synchronization_unittest.cc
index ae7d7487..445ffc0b 100644
--- a/cc/surfaces/surface_synchronization_unittest.cc
+++ b/cc/surfaces/surface_synchronization_unittest.cc
@@ -155,6 +155,7 @@
   void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override {
     damaged_surfaces_.insert(surface_id);
   }
+  void OnSurfaceDiscarded(const SurfaceId& surface_id) override {}
 
  protected:
   testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index e3cec7c..71ead755 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -347,6 +347,7 @@
     ":app_hooks_java",
     ":chrome_java",
     ":chrome_java_resources",
+    ":partner_location_descriptor_proto_java",
     "//base:base_java",
     "//base:base_java_test_support",
     "//chrome/android/webapk/libs/client:client_java",
@@ -376,6 +377,7 @@
     "//third_party/WebKit/public:android_mojo_bindings_java",
     "//third_party/WebKit/public:blink_headers_java",
     "//third_party/WebKit/public:mojo_bindings_java",
+    "//third_party/android_protobuf:protobuf_nano_javalib",
     "//third_party/android_tools:android_support_annotations_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
     "//third_party/android_tools:android_support_v7_mediarouter_java",
diff --git a/chrome/android/java/res/drawable-hdpi/diners_card.png b/chrome/android/java/res/drawable-hdpi/diners_card.png
new file mode 100644
index 0000000..d276c42b
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/diners_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/jcb_card.png b/chrome/android/java/res/drawable-hdpi/jcb_card.png
new file mode 100644
index 0000000..03b2f5a
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/jcb_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/mir_card.png b/chrome/android/java/res/drawable-hdpi/mir_card.png
deleted file mode 100644
index c686f15..0000000
--- a/chrome/android/java/res/drawable-hdpi/mir_card.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_amex.png b/chrome/android/java/res/drawable-hdpi/pr_amex.png
deleted file mode 100644
index 8584b7a8..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_amex.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_dinersclub.png b/chrome/android/java/res/drawable-hdpi/pr_dinersclub.png
deleted file mode 100644
index 8875789..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_dinersclub.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_discover.png b/chrome/android/java/res/drawable-hdpi/pr_discover.png
deleted file mode 100644
index a34d9bd..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_discover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_generic.png b/chrome/android/java/res/drawable-hdpi/pr_generic.png
deleted file mode 100644
index fdec48b..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_generic.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_jcb.png b/chrome/android/java/res/drawable-hdpi/pr_jcb.png
deleted file mode 100644
index 1547fe1..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_jcb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_mc.png b/chrome/android/java/res/drawable-hdpi/pr_mc.png
deleted file mode 100644
index 5731888..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_mc.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_mir.png b/chrome/android/java/res/drawable-hdpi/pr_mir.png
deleted file mode 100644
index 2a51a41a..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_mir.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_unionpay.png b/chrome/android/java/res/drawable-hdpi/pr_unionpay.png
deleted file mode 100644
index 9c61af1..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_unionpay.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pr_visa.png b/chrome/android/java/res/drawable-hdpi/pr_visa.png
deleted file mode 100644
index 1f8dc61..0000000
--- a/chrome/android/java/res/drawable-hdpi/pr_visa.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/diners_card.png b/chrome/android/java/res/drawable-mdpi/diners_card.png
new file mode 100644
index 0000000..c8caf67
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/diners_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/jcb_card.png b/chrome/android/java/res/drawable-mdpi/jcb_card.png
new file mode 100644
index 0000000..8c603de
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/jcb_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/mir_card.png b/chrome/android/java/res/drawable-mdpi/mir_card.png
deleted file mode 100644
index a17a51b..0000000
--- a/chrome/android/java/res/drawable-mdpi/mir_card.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_amex.png b/chrome/android/java/res/drawable-mdpi/pr_amex.png
deleted file mode 100644
index 67dfb96..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_amex.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_dinersclub.png b/chrome/android/java/res/drawable-mdpi/pr_dinersclub.png
deleted file mode 100644
index a3446c40..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_dinersclub.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_discover.png b/chrome/android/java/res/drawable-mdpi/pr_discover.png
deleted file mode 100644
index c6e04e9..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_discover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_generic.png b/chrome/android/java/res/drawable-mdpi/pr_generic.png
deleted file mode 100644
index a93ff32d..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_generic.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_jcb.png b/chrome/android/java/res/drawable-mdpi/pr_jcb.png
deleted file mode 100644
index 66495ce5..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_jcb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_mc.png b/chrome/android/java/res/drawable-mdpi/pr_mc.png
deleted file mode 100644
index bcdf48f..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_mc.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_mir.png b/chrome/android/java/res/drawable-mdpi/pr_mir.png
deleted file mode 100644
index fc97556..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_mir.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_unionpay.png b/chrome/android/java/res/drawable-mdpi/pr_unionpay.png
deleted file mode 100644
index 0e11c0f..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_unionpay.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pr_visa.png b/chrome/android/java/res/drawable-mdpi/pr_visa.png
deleted file mode 100644
index c0c8c08..0000000
--- a/chrome/android/java/res/drawable-mdpi/pr_visa.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/diners_card.png b/chrome/android/java/res/drawable-xhdpi/diners_card.png
new file mode 100644
index 0000000..f3cc7bfd
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/diners_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/jcb_card.png b/chrome/android/java/res/drawable-xhdpi/jcb_card.png
new file mode 100644
index 0000000..d96b48a
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/jcb_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/mir_card.png b/chrome/android/java/res/drawable-xhdpi/mir_card.png
deleted file mode 100644
index 8fdae43..0000000
--- a/chrome/android/java/res/drawable-xhdpi/mir_card.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_amex.png b/chrome/android/java/res/drawable-xhdpi/pr_amex.png
deleted file mode 100644
index f29dcdf57..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_amex.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_dinersclub.png b/chrome/android/java/res/drawable-xhdpi/pr_dinersclub.png
deleted file mode 100644
index c61096b..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_dinersclub.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_discover.png b/chrome/android/java/res/drawable-xhdpi/pr_discover.png
deleted file mode 100644
index 6d8f2ff2..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_discover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_generic.png b/chrome/android/java/res/drawable-xhdpi/pr_generic.png
deleted file mode 100644
index 8dd4609..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_generic.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_jcb.png b/chrome/android/java/res/drawable-xhdpi/pr_jcb.png
deleted file mode 100644
index 2a18c032..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_jcb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_mc.png b/chrome/android/java/res/drawable-xhdpi/pr_mc.png
deleted file mode 100644
index ade774b8..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_mc.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_mir.png b/chrome/android/java/res/drawable-xhdpi/pr_mir.png
deleted file mode 100644
index 1b9e5330..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_mir.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_unionpay.png b/chrome/android/java/res/drawable-xhdpi/pr_unionpay.png
deleted file mode 100644
index 33f62de..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_unionpay.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pr_visa.png b/chrome/android/java/res/drawable-xhdpi/pr_visa.png
deleted file mode 100644
index 493c2ab..0000000
--- a/chrome/android/java/res/drawable-xhdpi/pr_visa.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/diners_card.png b/chrome/android/java/res/drawable-xxhdpi/diners_card.png
new file mode 100644
index 0000000..ed5aae44
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/diners_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/jcb_card.png b/chrome/android/java/res/drawable-xxhdpi/jcb_card.png
new file mode 100644
index 0000000..aed168f9
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/jcb_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/mir_card.png b/chrome/android/java/res/drawable-xxhdpi/mir_card.png
deleted file mode 100644
index 743fcff2..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/mir_card.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_amex.png b/chrome/android/java/res/drawable-xxhdpi/pr_amex.png
deleted file mode 100644
index 9cb774c7..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_amex.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_dinersclub.png b/chrome/android/java/res/drawable-xxhdpi/pr_dinersclub.png
deleted file mode 100644
index 99c5aa2..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_dinersclub.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_discover.png b/chrome/android/java/res/drawable-xxhdpi/pr_discover.png
deleted file mode 100644
index 8c84098..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_discover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_generic.png b/chrome/android/java/res/drawable-xxhdpi/pr_generic.png
deleted file mode 100644
index da56787c..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_generic.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_jcb.png b/chrome/android/java/res/drawable-xxhdpi/pr_jcb.png
deleted file mode 100644
index 6a8adc5..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_jcb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_mc.png b/chrome/android/java/res/drawable-xxhdpi/pr_mc.png
deleted file mode 100644
index 450a1b6c..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_mc.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_mir.png b/chrome/android/java/res/drawable-xxhdpi/pr_mir.png
deleted file mode 100644
index 5d25999..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_mir.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_unionpay.png b/chrome/android/java/res/drawable-xxhdpi/pr_unionpay.png
deleted file mode 100644
index e6b8b12a..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_unionpay.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pr_visa.png b/chrome/android/java/res/drawable-xxhdpi/pr_visa.png
deleted file mode 100644
index 53b39f8..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/pr_visa.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/diners_card.png b/chrome/android/java/res/drawable-xxxhdpi/diners_card.png
new file mode 100644
index 0000000..fc1784d
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/diners_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/jcb_card.png b/chrome/android/java/res/drawable-xxxhdpi/jcb_card.png
new file mode 100644
index 0000000..bcaa6b8
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/jcb_card.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/mir_card.png b/chrome/android/java/res/drawable-xxxhdpi/mir_card.png
deleted file mode 100644
index a2324c0..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/mir_card.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_amex.png b/chrome/android/java/res/drawable-xxxhdpi/pr_amex.png
deleted file mode 100644
index 318ec6584..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_amex.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_dinersclub.png b/chrome/android/java/res/drawable-xxxhdpi/pr_dinersclub.png
deleted file mode 100644
index 87fa3c4..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_dinersclub.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_discover.png b/chrome/android/java/res/drawable-xxxhdpi/pr_discover.png
deleted file mode 100644
index b8109ff..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_discover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_generic.png b/chrome/android/java/res/drawable-xxxhdpi/pr_generic.png
deleted file mode 100644
index bda5b34..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_generic.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_jcb.png b/chrome/android/java/res/drawable-xxxhdpi/pr_jcb.png
deleted file mode 100644
index d9919ef..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_jcb.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_mc.png b/chrome/android/java/res/drawable-xxxhdpi/pr_mc.png
deleted file mode 100644
index 4cdd3a52..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_mc.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_mir.png b/chrome/android/java/res/drawable-xxxhdpi/pr_mir.png
deleted file mode 100644
index 56934a4..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_mir.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_unionpay.png b/chrome/android/java/res/drawable-xxxhdpi/pr_unionpay.png
deleted file mode 100644
index fa1bd84..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_unionpay.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pr_visa.png b/chrome/android/java/res/drawable-xxxhdpi/pr_visa.png
deleted file mode 100644
index ef6aa856..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/pr_visa.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable/discover_card.xml b/chrome/android/java/res/drawable/discover_card.xml
index 7609429..d7d075c73 100644
--- a/chrome/android/java/res/drawable/discover_card.xml
+++ b/chrome/android/java/res/drawable/discover_card.xml
@@ -12,122 +12,64 @@
     android:viewportHeight="80">
 
     <path
+        android:pathData="M0,8C0,3.58 3.59,0 8.01,0L119.99,0C124.42,0 128,3.58 128,8L128,72C128,76.42 124.41,80 119.99,80L8.01,80C3.58,80 0,76.42 0,72L0,8Z"
+        android:strokeColor="#00000000"
         android:fillColor="#E0E0E0"
-        android:fillType="evenOdd"
-        android:strokeWidth="1"
-        android:pathData="M0,8.00005106 C0,3.58174486 3.59075293,0 8.00697327,0 L119.993027,0
-C124.415156,0 128,3.5797863 128,8.00005106 L128,71.9999489 C128,76.4182551
-124.409247,80 119.993027,80 L8.00697327,80 C3.58484404,80 0,76.4202137
-0,71.9999489 L0,8.00005106 Z" />
+        android:strokeWidth="1"/>
     <path
+        android:pathData="M4,8L4,72C4,74.21 5.79,76 8.01,76L119.99,76C122.2,76 124,74.21 124,72L124,8C124,5.79 122.21,4 119.99,4L8.01,4C5.8,4 4,5.79 4,8Z"
+        android:strokeColor="#00000000"
         android:fillColor="#FFFFFF"
-        android:fillType="evenOdd"
-        android:strokeWidth="1"
-        android:pathData="M4,8.00005106 L4,71.9999489 C4,74.2094718 5.79238055,76 8.00697327,76
-L119.993027,76 C122.203379,76 124,74.2058465 124,71.9999489 L124,8.00005106
-C124,5.79052815 122.207619,4 119.993027,4 L8.00697327,4 C5.79662132,4
-4,5.79415354 4,8.00005106 Z" />
-    <group
-            android:translateX="4.000000"
-            android:translateY="4.000000">
-        <path
-            android:fillColor="#FFFFFF"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M0,4.00005106 L0,67.9999489 C0,70.2094718 1.79238055,72 4.00697327,72
-L115.993027,72 C118.203379,72 120,70.2058465 120,67.9999489 L120,4.00005106
-C120,1.79052815 118.207619,0 115.993027,0 L4.00697327,0 C1.79662132,0
-0,1.79415354 0,4.00005106 Z" />
-        <path
-            android:fillColor="#F68221"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M32,72 L115.990154,71.9999999 C118.204731,71.9999999 120,70.2132052
-120,68.0007251 L119.999999,42 C119.999999,42 86.8891933,63.0977749 32,72 Z" />
-    </group>
-    <group
-            android:translateX="12.000000"
-            android:translateY="27.000000">
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M4.80389506,0.997038492 L0.0556034122,0.997038492 L0.0556034122,16.9970385
-L4.77945083,16.9970385 C7.29109545,16.9970385 9.10607951,16.4251888
-10.69801,15.1488439 C12.5893823,13.6396324 13.7077058,11.3610768
-13.7077058,9.00882921 C13.7077058,4.28664792 10.0502379,0.997038492
-4.80389506,0.997038492 L4.80389506,0.997038492 Z M8.5835841,13.0176722
-C7.56609303,13.9019759 6.24610462,14.2881218 4.15612297,14.2881218
-L3.28835281,14.2881218 L3.28835281,3.7089029 L4.15612297,3.7089029
-C6.24610462,3.7089029 7.51414904,4.0685197 8.5835841,5.00293385
-C9.70190761,5.96387711 10.3741239,7.45245485 10.3741239,8.98524778
-C10.3771795,10.5209884 9.70190761,12.056729 8.5835841,13.0176722
-L8.5835841,13.0176722 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M 15.1957483 0.997038492 H 18.43155323 V 16.997038492 H 15.1957483 V 0.997038492 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M26.3423171,7.16111621 C24.4020563,6.46569698 23.8306725,6.00701621
-23.8306725,5.13996159 C23.8306725,4.12790466 24.845108,3.35850466
-26.2414846,3.35850466 C27.2100872,3.35850466 28.0075802,3.74320466
-28.8509062,4.6605662 L30.5436691,2.51512388 C29.1534035,1.33735003
-27.4881404,0.733666952 25.6701008,0.733666952 C22.7367932,0.733666952
-20.4970906,2.70747388 20.4970906,5.33527082 C20.4970906,7.54877544
-21.5390259,8.68216083 24.5762215,9.73860622 C25.8412104,10.1706539
-26.4859269,10.4606585 26.8128685,10.6530085 C27.4606406,11.0613824
-27.7814711,11.6413916 27.7814711,12.3160962 C27.7814711,13.6181578
-26.7120361,14.582867 25.2698265,14.582867 C23.7267845,14.582867
-22.4831843,13.8371409 21.7406908,12.4403839 L19.6507092,14.390517
-C21.1418072,16.5093263 22.932347,17.4474024 25.3920476,17.4474024
-C28.7531292,17.4474024 31.1119974,15.2842047 31.1119974,12.1740532
-C31.1119974,9.62023699 30.0211737,8.46613699 26.3423171,7.16111621
-L26.3423171,7.16111621 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M32.132544,9.04022776 C32.132544,13.7602009 35.9611215,17.4207693
-40.8866338,17.4207693 C42.2799549,17.4207693 43.4716111,17.1544386
-44.9413205,16.4856524 L44.9413205,12.7984509 C43.6488318,14.0531647
-42.5030085,14.5562339 41.0363547,14.5562339 C37.7791611,14.5562339
-35.4661259,12.2687485 35.4661259,9.01655391 C35.4661259,5.93303544
-37.8524938,3.50054773 40.8866338,3.50054773 C42.4296758,3.50054773
-43.5968878,4.03320927 44.9413205,5.30863774 L44.9413205,1.62143619
-C43.5204996,0.923057722 42.3532876,0.636012336 40.9630221,0.636012336
-C36.061954,0.636012336 32.132544,4.37056158 32.132544,9.04022776
-L32.132544,9.04022776 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M 70.5924841 11.7902985 L 66.1680785 0.997038492 L 62.6358873 0.997038492 L 69.67277 17.477038 L 71.4144214 17.477038 L 78.5796362 0.997038492 L 75.0718893 0.997038492 Z" />
-        <path
-            android:fillColor="#F68221"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M 54.7155963 0.31999969 C 59.681092217 0.31999969 63.70642199 4.22253031673 63.70642199 9.03654581 C 63.70642199 13.8505613033 59.681092217 17.75309193 54.7155963 17.75309193 C 49.750100383 17.75309193 45.72477061 13.8505613033 45.72477061 9.03654581 C 45.72477061 4.22253031673 49.750100383 0.31999969 54.7155963 0.31999969 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M 80.040179 16.9970385 L 89.2159318 16.9970385 L 89.2159318 14.2881218 L 83.2729284 14.2881218 L 83.2729284 9.96977246 L 88.9959337 9.96977246 L 88.9959337 7.26085574 L 83.2729284 7.26085574 L 83.2729284 3.7089029 L 89.2159318 3.7089029 L 89.2159318 0.997038492 L 80.040179 0.997038492 Z" />
-        <path
-            android:fillColor="#231F20"
-            android:fillType="evenOdd"
-            android:strokeWidth="1"
-            android:pathData="M102.024708,5.722179 C102.024708,2.72733744 99.8858381,0.999997723
-96.1550375,0.999997723 L91.3578574,0.999997723 L91.3578574,16.9999977
-L94.5875513,16.9999977 L94.5875513,10.5740582 L95.0092142,10.5740582
-L99.4855638,16.9999977 L103.463862,16.9999977 L98.2419636,10.2586565
-C100.683331,9.7781849 102.024708,8.17170001 102.024708,5.722179
-L102.024708,5.722179 Z M95.5347652,8.36329912 L94.5906068,8.36329912
-L94.5906068,3.51731534 L95.5867092,3.51731534 C97.6003026,3.51731534
-98.6972374,4.33087466 98.6972374,5.88724901 C98.6941819,7.49668158
-97.6003026,8.36329912 95.5347652,8.36329912 L95.5347652,8.36329912 Z" />
-    </group>
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M4,8L4,72C4,74.21 5.79,76 8.01,76L119.99,76C122.2,76 124,74.21 124,72L124,8C124,5.79 122.21,4 119.99,4L8.01,4C5.8,4 4,5.79 4,8Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M36,76L119.99,76C122.2,76 124,74.21 124,72L124,46C124,46 90.89,67.1 36,76Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#F68221"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M16.8,28L12.06,28L12.06,44L16.78,44C19.29,44 21.11,43.43 22.7,42.15C24.59,40.64 25.71,38.36 25.71,36.01C25.71,31.29 22.05,28 16.8,28L16.8,28ZM20.58,40.02C19.57,40.9 18.25,41.29 16.16,41.29L15.29,41.29L15.29,30.71L16.16,30.71C18.25,30.71 19.51,31.07 20.58,32C21.7,32.96 22.37,34.45 22.37,35.99C22.38,37.52 21.7,39.06 20.58,40.02L20.58,40.02Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M27.2,28h3.24v16h-3.24z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M38.34,34.16C36.4,33.47 35.83,33.01 35.83,32.14C35.83,31.13 36.85,30.36 38.24,30.36C39.21,30.36 40.01,30.74 40.85,31.66L42.54,29.52C41.15,28.34 39.49,27.73 37.67,27.73C34.74,27.73 32.5,29.71 32.5,32.34C32.5,34.55 33.54,35.68 36.58,36.74C37.84,37.17 38.49,37.46 38.81,37.65C39.46,38.06 39.78,38.64 39.78,39.32C39.78,40.62 38.71,41.58 37.27,41.58C35.73,41.58 34.48,40.84 33.74,39.44L31.65,41.39C33.14,43.51 34.93,44.45 37.39,44.45C40.75,44.45 43.11,42.28 43.11,39.17C43.11,36.62 42.02,35.47 38.34,34.16L38.34,34.16Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M44.13,36.04C44.13,40.76 47.96,44.42 52.89,44.42C54.28,44.42 55.47,44.15 56.94,43.49L56.94,39.8C55.65,41.05 54.5,41.56 53.04,41.56C49.78,41.56 47.47,39.27 47.47,36.02C47.47,32.93 49.85,30.5 52.89,30.5C54.43,30.5 55.6,31.03 56.94,32.31L56.94,28.62C55.52,27.92 54.35,27.64 52.96,27.64C48.06,27.64 44.13,31.37 44.13,36.04L44.13,36.04Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M82.59,38.79l-4.42,-10.79l-3.53,0l7.04,16.48l1.74,0l7.17,-16.48l-3.51,0z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M57.72,36.04a8.99,8.72 0,1 0,17.98 0a8.99,8.72 0,1 0,-17.98 0z"
+        android:strokeColor="#00000000"
+        android:fillColor="#F68221"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M92.04,44l9.18,0l0,-2.71l-5.94,0l0,-4.32l5.72,0l0,-2.71l-5.72,0l0,-3.55l5.94,0l0,-2.71l-9.18,0z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M114.02,32.72C114.02,29.73 111.89,28 108.16,28L103.36,28L103.36,44L106.59,44L106.59,37.57L107.01,37.57L111.49,44L115.46,44L110.24,37.26C112.68,36.78 114.02,35.17 114.02,32.72L114.02,32.72ZM107.53,35.36L106.59,35.36L106.59,30.52L107.59,30.52C109.6,30.52 110.7,31.33 110.7,32.89C110.69,34.5 109.6,35.36 107.53,35.36L107.53,35.36Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#231F20"
+        android:strokeWidth="1"/>
 </vector>
+
diff --git a/chrome/android/java/res/drawable/mir_card.xml b/chrome/android/java/res/drawable/mir_card.xml
new file mode 100644
index 0000000..06deb0c
--- /dev/null
+++ b/chrome/android/java/res/drawable/mir_card.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+   xmlns:tools="http://schemas.android.com/tools"
+   tools:targetApi="21"
+   android:width="32dp"
+   android:height="20dp"
+   android:viewportWidth="128"
+   android:viewportHeight="80">
+
+    <path
+        android:fillColor="#E0E0E0"
+        android:fillType="evenOdd"
+        android:strokeWidth="1"
+        android:pathData="M0,8.00005106 C0,3.58174486 3.59075293,0 8.00697327,0 L119.993027,0
+C124.415156,0 128,3.5797863 128,8.00005106 L128,71.9999489 C128,76.4182551
+124.409247,80 119.993027,80 L8.00697327,80 C3.58484404,80 0,76.4202137
+0,71.9999489 L0,8.00005106 Z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="evenOdd"
+        android:strokeWidth="1"
+        android:pathData="M4,8.00005106 L4,71.9999489 C4,74.2094718 5.79238055,76 8.00697327,76
+L119.993027,76 C122.203379,76 124,74.2058465 124,71.9999489 L124,8.00005106
+C124,5.79052815 122.207619,4 119.993027,4 L8.00697327,4 C5.79662132,4
+4,5.79415354 4,8.00005106 Z" />
+    <path android:fillColor="#3BA536"
+        android:pathData="M34.86,29.77L31.05,42.52C30.95,42.86 30.44,42.86 30.34,42.52L26.53,29.77C25.87,27.54 23.74,26 21.31,26L21.31,26L12,26L12,54L21.31,54L21.31,37.62C21.31,37.22 21.9,37.13 22.03,37.51L27.47,54L33.92,54L39.36,37.51C39.48,37.13 40.08,37.22 40.08,37.62L40.08,54L49.39,54L49.39,26L40.08,26L40.08,26C37.65,26 35.52,27.54 34.86,29.77"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+    <path android:fillColor="#3BA536"
+        android:pathData="M74.71,26C72.62,26 70.72,27.17 69.84,28.99L63.44,42.25C63.28,42.59 62.74,42.48 62.74,42.1L62.74,26L53.43,26L53.43,54L61.31,54L61.31,54C63.38,54 65.25,52.83 66.09,51.01L72.58,36.87C72.74,36.52 73.28,36.63 73.28,37.01L73.28,54L73.28,54L73.28,54L82.59,54L82.59,26L74.71,26Z"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+    <path android:fillColor="#3BA536"
+        android:pathData="M86.63,38.9L86.63,54L95.94,54L95.94,45.06L105.85,45.06C110.1,45.06 113.73,42.5 115.15,38.9L86.63,38.9Z"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+    <path android:fillColor="#0093D3"
+        android:pathData="M105.85,26L85.42,26C86.14,32.48 91.86,37.53 98.81,37.53L115.57,37.53C115.72,36.88 115.8,36.21 115.8,35.53L115.8,35.53C115.8,30.27 111.34,26 105.85,26"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
+
diff --git a/chrome/android/java/res/drawable/unionpay_card.xml b/chrome/android/java/res/drawable/unionpay_card.xml
index 7e1a077..4e3c228 100644
--- a/chrome/android/java/res/drawable/unionpay_card.xml
+++ b/chrome/android/java/res/drawable/unionpay_card.xml
@@ -4,74 +4,111 @@
      found in the LICENSE file. -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:targetApi="21"
-    android:viewportWidth="128"
-    android:viewportHeight="80"
-    android:width="32dp"
-    android:height="20dp">
+   xmlns:tools="http://schemas.android.com/tools"
+   tools:targetApi="21"
+   android:width="32dp"
+   android:height="20dp"
+   android:viewportWidth="128"
+   android:viewportHeight="80">
+
     <path
-        android:pathData="M0 8.0000511C0 3.5817449 3.5907529 0 8.0069733 0L119.99303 0C124.41516 0 128 3.5797863 128 8.0000511l0 63.9998979C128 76.418255 124.40925 80 119.99303 80L8.0069733 80C3.584844 80 0 76.420214 0 71.999949L0 8.0000511Z"
-        android:fillColor="#e0e0e0" />
+        android:pathData="M0,8C0,3.58 3.59,0 8.01,0L119.99,0C124.42,0 128,3.58 128,8L128,72C128,76.42 124.41,80 119.99,80L8.01,80C3.58,80 0,76.42 0,72L0,8Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#E0E0E0"
+        android:strokeWidth="1"/>
     <path
-        android:pathData="M4 8.0000511L4 71.999949C4 74.209472 5.7923805 76 8.0069733 76L119.99303 76C122.20338 76 124 74.205847 124 71.999949L124 8.0000511C124 5.7905281 122.20762 4 119.99303 4L8.0069733 4C5.7966213 4 4 5.7941535 4 8.0000511Z"
-        android:fillColor="#ffffff" />
-    <group
-        android:translateX="19"
-        android:translateY="12">
-        <path
-            android:pathData="M20.740341 50.248637L31.191144 5.6617631c0.741483 -3.1240388 3.871032 -5.66198057573 7.006602 -5.66198057573l-20.582577 0c-3.137759 0 -6.273875 2.53794177573 -7.004961 5.66198057573L0.1533857 50.248637c-0.73108561 3.113709 1.222489 5.653281 4.3520388 5.653281l20.5803885 0c-3.139947 0 -5.083125 -2.539572 -4.345472 -5.653281"
-            android:fillColor="#e21836" />
-        <path
-            android:pathData="M45.534102 50.248637L55.987094 5.6617631C56.717633 2.5377243 59.85156 -0.00021747573 62.991507 -0.00021747573l-22.925225 0 -1.868208 0c-3.136116 0 -6.265119 2.53794177573 -7.007149 5.66198057573L20.740122 50.248637c-0.737105 3.113709 1.206072 5.653281 4.346019 5.653281l1.868208 0 22.931792 0c-3.139947 0 -5.087502 -2.539572 -4.352039 -5.653281"
-            android:fillColor="#00447c" />
-        <path
-            android:pathData="M85.442676 -0.0001631068l-21.426937 0 -1.023848 0c-3.140495 0 -6.273875 2.5379417068 -7.004961 5.6619806068L45.533938 50.248691c-0.734916 3.113165 1.212092 5.653282 4.352039 5.653282l1.017829 0 21.422559 0c3.138306 0 6.278253 -2.540117 7.015905 -5.653282L89.792526 5.6618175C90.530178 2.5377786 88.580434 -0.0001631068 85.442676 -0.0001631068"
-            android:fillColor="#007b84" />
-        <path
-            android:pathData="M62.502184 34.74713c-0.42519 0.116893 -1.21647 0.471379 -1.21647 0.471379l0.703725 -2.299806 2.109532 0 -0.508914 1.67565c0 0 -0.651739 0.03806 -1.087873 0.152777l0 0zm0.04049 3.285515c0 0 -0.662683 0.08264 -1.098818 0.180504 -0.429567 0.129399 -1.235075 0.537166 -1.235075 0.537166l0.726708 -2.393321 2.120477 0 -0.513292 1.675651zm-1.181995 3.905864l-2.116099 0 0.613434 -2.019806 2.109532 0 -0.606867 2.019806zm3.311227 -0.0212l-0.739841 0 2.738288 -8.998602 0.908384 0 0.287838 -0.92699 0.029 1.030835c-0.03448 0.637203 0.470061 1.202097 1.795428 1.108582l1.532762 0 0.52752 -1.732738 -0.57677 0c-0.331615 0 -0.485383 -0.08318 -0.466231 -0.261514l-0.02791 -1.048777 -2.838429 0 0 0.0054c-0.917687 0.01957 -3.658164 0.08808 -4.213045 0.23433 -0.671439 0.171806 -1.378994 0.677437 -1.378994 0.677437l0.277988 -0.928078 -2.65511 0 -0.55324 1.841476 -2.774951 9.136155 -0.538464 0 -0.528067 1.720777 5.288331 0 -0.177299 0.573048 2.605861 0 0.172921 -0.573048 0.731086 0 0.572939 -1.85833z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M66.456722 36.35694l3.050203 0 -0.438323 1.41033 -3.090697 0 -0.464043 1.541903 2.70436 0 -2.047696 2.864699c-0.143372 0.210408 -0.271968 0.284893 -0.414792 0.344155 -0.143372 0.07231 -0.331616 0.157126 -0.549409 0.157126l-0.750239 0 -0.515481 1.688699 1.962331 0c1.020017 0 1.622506 -0.461048 2.067396 -1.066174l1.404166 -1.909437 0.301518 1.938796c0.06403 0.363184 0.32669 0.575767 0.504537 0.658408 0.196451 0.09786 0.39947 0.265864 0.685666 0.290873 0.308085 0.01305 0.530256 0.02338 0.678005 0.02338l0.963654 0 0.579506 -1.889864 -0.380318 0c-0.218341 0 -0.594281 -0.03643 -0.658305 -0.104388 -0.06403 -0.08264 -0.06403 -0.209864 -0.0985 -0.403418l-0.305896 -1.943145 -1.252586 0 0.549409 -0.649709 3.084678 0 0.474439 -1.541903 -2.85594 0 0.44489 -1.41033 2.847185 0 0.528067 -1.739262 -8.488474 0 -0.519311 1.739262z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M40.6946 42.331161l0.711933 -2.353087 2.925984 0 0.534634 -1.750136 -2.92872 0 0.447078 -1.448388 2.86196 0 0.530256 -1.69468 -7.160918 0 -0.519312 1.69468 1.626884 0 -0.433945 1.448388 -1.631262 0 -0.540653 1.780039 1.626337 0 -0.948879 3.113165c-0.128049 0.412116 0.06019 0.569242 0.179488 0.760621 0.12203 0.186486 0.246249 0.309903 0.52369 0.380039 0.286743 0.06361 0.483194 0.10167 0.750238 0.10167l3.298641 0 0.587714 -1.938796 -1.462172 0.199534c-0.282365 0 -1.064342 -0.03371 -0.978976 -0.293049"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M41.03021 31.066625l-0.74203 1.331495c-0.158146 0.290874 -0.300971 0.471379 -0.429568 0.554563 -0.113274 0.07014 -0.337634 0.0995 -0.662683 0.0995l-0.386884 0 -0.517123 1.703378 1.284872 0c0.617812 0 1.092251 -0.225087 1.3188 -0.337631 0.243513 -0.129398 0.307537 -0.05546 0.495781 -0.235961l0.433945 -0.373515 4.012216 0 0.532445 -1.773514 -2.936929 0 0.512745 -0.968311 -2.915587 0z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M48.843086 35.6944l4.097581 0 -0.260476 0.811184c-0.03666 0.01903 -0.124219 -0.04023 -0.541201 0.0087l-3.548173 0 0.252269 -0.819883zm0.820829 -2.720621l4.132057 0 -0.297141 0.977009c0 0 -1.947555 -0.01903 -2.25947 0.03806 -1.372427 0.235961 -2.174104 0.964504 -2.174104 0.964504l0.598658 -1.979572zm-2.710379 9.391145c-0.0684 -0.09732 -0.01915 -0.26967 0.08537 -0.628505l1.096629 -3.606291 3.901129 0c0.568561 -0.0082 0.978976 -0.01468 1.24602 -0.03371 0.286743 -0.0299 0.598658 -0.131572 0.938481 -0.314252 0.350768 -0.191379 0.530257 -0.393087 0.681836 -0.624699 0.169091 -0.231068 0.440512 -0.736699 0.673628 -1.51635l1.378447 -4.563728 -4.048332 0.02338c0 0 -1.246567 0.182679 -1.795976 0.384388 -0.553239 0.225088 -1.344519 0.853592 -1.344519 0.853592l0.365543 -1.251029 -2.500794 0 -3.501112 11.536544c-0.124219 0.448 -0.207397 0.773126 -0.226549 0.968311 -0.0066 0.210407 0.267043 0.41864 0.444342 0.575767 0.209585 0.157126 0.519312 0.131573 0.816452 0.157126 0.312463 0.02338 0.756805 0.03806 1.370238 0.03806l1.921836 0 0.589903 -1.979029 -1.720459 0.161476c-0.183866 0 -0.31684 -0.09786 -0.372109 -0.181049l0 0z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M52.771905 39.221965c-0.03393 0.121243 -0.08755 0.195184 -0.162525 0.250641 -0.08318 0.05274 -0.217793 0.07231 -0.418623 0.07231l-0.583883 0 0.03448 -0.987883 -2.428562 0 -0.0985 4.829592c-0.0038 0.348505 0.0301 0.550214 0.286743 0.71169 0.256646 0.201708 1.047378 0.227262 2.111721 0.227262l1.522365 0 0.548862 -1.807767 -1.324819 0.07231 -0.440512 0.02555c-0.06019 -0.02555 -0.117652 -0.04893 -0.181677 -0.112544 -0.05582 -0.05546 -0.149938 -0.0212 -0.134616 -0.369709l0.0104 -1.23798 1.389391 -0.05709c0.750238 0 1.070909 -0.242485 1.344519 -0.473553 0.261024 -0.221282 0.34639 -0.475728 0.44489 -0.819884l0.233115 -1.096077 -1.90925 0 -0.243512 0.773126z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M23.478574 14.288699c-2.308721 0.02338 -2.990556 0 -3.20835 -0.05111 -0.08372 0.395262 -1.641659 7.535534 -1.646037 7.541515 -0.335446 1.444582 -0.579506 2.47433 -1.408544 3.139262 -0.470609 0.386563 -1.020017 0.573048 -1.656981 0.573048 -1.023848 0 -1.620318 -0.505087 -1.720459 -1.463068l-0.01915 -0.328932c0 0 0.311916 -1.93499 0.311916 -1.945864 0 0 1.635092 -6.506873 1.927855 -7.36699 0.01532 -0.04893 0.0197 -0.07449 0.02353 -0.09786 -3.18263 0.02773 -3.746814 0 -3.785666 -0.05111 -0.02134 0.07014 -0.100141 0.473554 -0.100141 0.473554l-1.669568 7.333825 -0.143371 0.62198 -0.277441 2.034486c0 0.603495 0.119294 1.096078 0.356788 1.512544 0.761182 1.320621 2.930361 1.518524 4.157775 1.518524 1.581465 0 3.064978 -0.333825 4.067485 -0.943301 1.740159 -1.021592 2.195446 -2.618408 2.601483 -4.037437l0.188243 -0.728c0 0 1.684343 -6.758058 1.970539 -7.637204 0.01094 -0.04893 0.01532 -0.07449 0.0301 -0.09786"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M29.209387 19.740435c-0.406037 0 -1.148067 0.09786 -1.81458 0.422447 -0.241871 0.123417 -0.470609 0.265864 -0.711933 0.407766l0.217793 -0.781281 -0.119294 -0.131573c-1.412921 0.28435 -1.729761 0.322408 -3.035428 0.505088l-0.108897 0.07231c-0.152127 1.248855 -0.286743 2.187806 -0.848737 4.642563 -0.213963 0.904699 -0.436135 1.818097 -0.658853 2.720622l0.06019 0.114718c1.337953 -0.07014 1.74399 -0.07014 2.906832 -0.05111l0.09412 -0.10167c0.14775 -0.751922 0.166902 -0.928077 0.49414 -2.450951 0.153769 -0.722019 0.474439 -2.308505 0.632586 -2.873398 0.290574 -0.133748 0.577317 -0.265321 0.850927 -0.265321 0.651738 0 0.572939 0.564894 0.547219 0.789981 -0.02791 0.377864 -0.265401 1.612039 -0.508914 2.671689l-0.162524 0.683962c-0.113275 0.505087 -0.237494 0.996038 -0.350768 1.496776l0.04925 0.100039c1.318799 -0.07014 1.721006 -0.07014 2.847184 -0.05111l0.132427 -0.10167c0.203566 -1.174369 0.263213 -1.488621 0.624378 -3.198524l0.181677 -0.785631C30.881144 22.03861 31.058443 21.258959 30.7914 20.62393 30.509034 19.912241 29.831576 19.740435 29.209387 19.740435"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M35.611476 21.350299c-0.700989 0.133748 -1.148067 0.222913 -1.59241 0.280544 -0.440512 0.06959 -0.870079 0.133747 -1.547537 0.227262l-0.05363 0.04839 -0.04925 0.0386c-0.07059 0.501282 -0.119841 0.934602 -0.213415 1.444039 -0.07935 0.526835 -0.201377 1.125437 -0.400018 1.985553 -0.153769 0.658408 -0.233116 0.887845 -0.320671 1.119457 -0.08537 0.231611 -0.179488 0.456699 -0.352409 1.104233l0.04049 0.05981 0.03393 0.05491c0.633133 -0.0299 1.047378 -0.05111 1.473115 -0.05491 0.42519 -0.01522 0.865702 0 1.547538 0.0038l0.05965 -0.04893 0.06402 -0.05274c0.0985 -0.583922 0.113275 -0.741048 0.173469 -1.025941 0.05965 -0.305554 0.162524 -0.728544 0.414793 -1.85833 0.119294 -0.530641 0.252268 -1.059651 0.37594 -1.601165 0.128596 -0.53934 0.263212 -1.070525 0.391262 -1.601166l-0.01915 -0.06415 -0.02572 -0.05926z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M39.37788 23.949786c0.29714 -1.305941 0.647908 -2.402019 1.54316 -2.402019 0.701536 0 0.752427 0.815534 0.440512 2.125825 -0.05582 0.290874 -0.311916 1.372272 -0.658306 1.832777 -0.241871 0.339806 -0.528067 0.545864 -0.84436 0.545864 -0.09412 0 -0.653928 0 -0.662683 -0.825864 -0.0044 -0.407767 0.07935 -0.824233 0.181677 -1.276583m0.100688 3.880311c1.288703 0 2.609691 -0.352854 3.60399 -1.4 0.765013 -0.849243 1.115781 -2.112777 1.237264 -2.633087 0.39564 -1.724583 0.08755 -2.529787 -0.299329 -3.020194 -0.587715 -0.747573 -1.626338 -0.98734 -2.703813 -0.98734 -0.647909 0 -2.191068 0.06361 -3.396594 1.167844 -0.865701 0.796505 -1.265719 1.87736 -1.507043 2.913631 -0.243513 1.055845 -0.523689 2.956583 1.235622 3.663923 0.542842 0.231068 1.325367 0.295223 1.829903 0.295223"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M67.630235 24.087829c0.301518 -1.282563 0.647908 -2.368311 1.545348 -2.368311 0.567467 0 0.866796 0.520855 0.805508 1.408156 -0.04816 0.221281 -0.100141 0.454524 -0.161977 0.718213 -0.08974 0.381127 -0.187149 0.758991 -0.281818 1.137398 -0.09631 0.258253 -0.207944 0.502913 -0.331616 0.665476 -0.230926 0.325126 -0.780335 0.526835 -1.096628 0.526835 -0.08974 0 -0.64353 0 -0.662683 -0.811184 -0.0044 -0.403962 0.07935 -0.819884 0.183866 -1.276583m-2.95827 -0.06361c-0.245702 1.040622 -0.528067 2.94136 1.222489 3.618797 0.558164 0.235961 1.058323 0.306097 1.56669 0.280543 0.536823 -0.02881 1.034245 -0.29631 1.495004 -0.681242 -0.04159 0.158213 -0.08263 0.316427 -0.124766 0.475184l0.07935 0.10167c1.259153 -0.05274 1.650415 -0.05274 3.014086 -0.04241l0.123672 -0.09351c0.199188 -1.163495 0.386885 -2.293826 0.904554 -4.519146 0.252269 -1.066175 0.50399 -2.122019 0.762825 -3.183845l-0.04049 -0.116893c-1.408544 0.25934 -1.785031 0.314796 -3.139947 0.505631l-0.102878 0.08319c-0.01423 0.108194 -0.02736 0.212038 -0.04104 0.315883 -0.21068 -0.338175 -0.516028 -0.626874 -0.987185 -0.806835 -0.602489 -0.235417 -2.017599 0.06796 -3.234069 1.168388 -0.854757 0.785632 -1.265172 1.862136 -1.498287 2.894602"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M47.54125 27.662206l0.100688 -0.10167c0.142825 -0.751922 0.166355 -0.928621 0.483195 -2.450952 0.158147 -0.722019 0.484837 -2.308504 0.638606 -2.873398 0.291121 -0.134291 0.572939 -0.265864 0.855304 -0.265864 0.647908 0 0.568562 0.564893 0.542842 0.789981 -0.02353 0.378408 -0.261024 1.612039 -0.508914 2.671689l-0.153769 0.683961c-0.117652 0.505631 -0.245702 0.996039 -0.358976 1.497321l0.04925 0.100039c1.323177 -0.07014 1.710061 -0.07014 2.842806 -0.05111l0.136805 -0.10167c0.198641 -1.174913 0.252269 -1.489165 0.624378 -3.198524l0.177299 -0.786175c0.354599 -1.537554 0.534087 -2.31666 0.271421 -2.951689 -0.290573 -0.71169 -0.972409 -0.883496 -1.585843 -0.883496 -0.406584 0 -1.152444 0.09732 -1.815128 0.422447 -0.236946 0.123417 -0.474439 0.26532 -0.707555 0.407767l0.203019 -0.781282 -0.108897 -0.132116C47.81486 19.942361 47.492 19.980419 46.187975 20.163099l-0.100141 0.07231c-0.158146 1.248854 -0.286743 2.187262 -0.848738 4.642563 -0.213963 0.904699 -0.436134 1.818097 -0.658305 2.720621l0.05965 0.114719c1.340141 -0.07014 1.740159 -0.07014 2.900812 -0.05111"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M58.883255 20.560264c0 0 0.929726 -4.018408 0.925349 -4.003184l0.0301 -0.206059 0.01259 -0.157126 0.372109 0.03806c0 0 1.917458 0.163651 1.96233 0.168 0.756805 0.290874 1.068721 1.040622 0.850927 2.019262 -0.198641 0.894369 -0.782524 1.646292 -1.532762 2.009476 -0.617812 0.307728 -1.374617 0.333282 -2.154405 0.333282l-0.504536 0 0.03831 -0.201709zm-1.620318 7.152777c0.08318 -0.403418 0.577317 -2.794563 0.581695 -2.794563 0 0 0.420812 -1.754486 0.446531 -1.818097 0 0 0.132428 -0.18268 0.264855 -0.254991l0.19481 0c1.838111 0 3.913716 0 5.5406 -1.189048 1.107026 -0.815534 1.863831 -2.019806 2.201465 -3.483418 0.08756 -0.358835 0.152127 -0.785631 0.152127 -1.212427 0 -0.560544 -0.113274 -1.115107 -0.440512 -1.548427 -0.829585 -1.153165 -2.481641 -1.174369 -4.388702 -1.183068 -0.006 0 -0.940124 0.0087 -0.940124 0.0087 -2.441147 0.0299 -3.420123 0.0212 -3.82233 -0.02773 -0.03393 0.176699 -0.09795 0.490951 -0.09795 0.490951 0 0 -0.874457 4.026563 -0.874457 4.033088 0 0 -2.092569 8.560932 -2.191068 8.964349 2.130874 -0.02555 3.005331 -0.02555 3.373062 0.01468l0 0z"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M83.078523 19.853033l-0.108897 -0.123417c-1.393769 0.280543 -1.646037 0.325126 -2.926532 0.496932l-0.09412 0.09351c-0.0044 0.01522 -0.0082 0.0386 -0.01478 0.05981l-0.0044 -0.0212c-0.953257 2.185087 -0.925349 1.713709 -1.701306 3.433942 -0.0044 -0.07829 -0.0044 -0.127224 -0.0088 -0.210408l-0.194263 -3.729165 -0.12203 -0.123417c-1.459982 0.280543 -1.494457 0.325126 -2.842807 0.496932l-0.105066 0.09351c-0.01478 0.04458 -0.01478 0.09352 -0.02353 0.146796l0.0088 0.01903c0.168544 0.855767 0.12805 0.664932 0.297141 2.015457 0.0788 0.662757 0.183866 1.32932 0.262665 1.983378 0.132427 1.096078 0.207396 1.635418 0.369921 3.307263 -0.910574 1.49297 -1.126726 2.057863 -2.002825 3.368155l0.006 0.01359 -0.617264 0.969398c-0.07059 0.102214 -0.134616 0.17235 -0.22436 0.202252 -0.0985 0.04839 -0.226549 0.05709 -0.404396 0.05709l-0.342012 0 -0.508367 1.68 1.743989 0.0299c1.023848 -0.0043 1.667379 -0.480078 2.013769 -1.119457l1.096628 -1.867029 -0.01806 0 0.116011 -0.131572c0.737652 -1.577787 6.348844 -11.141282 6.348844 -11.141282"
-            android:fillColor="#fefefe" />
-        <path
-            android:pathData="M35.626415 19.179837c-0.636964 -0.373515 -1.754934 -0.25499 -2.507361 0.260971 -0.750239 0.505631 -0.835605 1.223301 -0.20083 1.601709 0.62602 0.363184 1.748367 0.254446 2.494228 -0.265321 0.748596 -0.516505 0.842171 -1.22765 0.213963 -1.597359"
-            android:fillColor="#fefefe" />
-    </group>
-</vector>
\ No newline at end of file
+        android:pathData="M4,8L4,72C4,74.21 5.79,76 8.01,76L119.99,76C122.2,76 124,74.21 124,72L124,8C124,5.79 122.21,4 119.99,4L8.01,4C5.8,4 4,5.79 4,8Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FFFFFF"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M39.74,62.25L50.19,17.66C50.93,14.54 54.06,12 57.2,12L36.62,12C33.48,12 30.34,14.54 29.61,17.66L19.15,62.25C18.42,65.36 20.38,67.9 23.51,67.9L44.09,67.9C40.95,67.9 39,65.36 39.74,62.25"
+        android:strokeColor="#00000000"
+        android:fillColor="#E21836"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M64.53,62.25L74.99,17.66C75.72,14.54 78.85,12 81.99,12L59.07,12L57.2,12C54.06,12 50.93,14.54 50.19,17.66L39.74,62.25C39,65.36 40.95,67.9 44.09,67.9L45.95,67.9L68.89,67.9C65.75,67.9 63.8,65.36 64.53,62.25"
+        android:strokeColor="#00000000"
+        android:fillColor="#00447C"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M104.44,12L83.02,12L81.99,12C78.85,12 75.72,14.54 74.99,17.66L64.53,62.25C63.8,65.36 65.75,67.9 68.89,67.9L69.9,67.9L91.33,67.9C94.46,67.9 97.6,65.36 98.34,62.25L108.79,17.66C109.53,14.54 107.58,12 104.44,12"
+        android:strokeColor="#00000000"
+        android:fillColor="#007B84"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M81.5,46.75C81.08,46.86 80.29,47.22 80.29,47.22L80.99,44.92L83.1,44.92L82.59,46.59C82.59,46.59 81.94,46.63 81.5,46.75L81.5,46.75ZM81.54,50.03C81.54,50.03 80.88,50.12 80.44,50.21C80.01,50.34 79.21,50.75 79.21,50.75L79.94,48.36L82.06,48.36L81.54,50.03ZM80.36,53.94L78.24,53.94L78.86,51.92L80.97,51.92L80.36,53.94ZM83.67,53.92L82.93,53.92L85.67,44.92L86.58,44.92L86.87,43.99L86.9,45.02C86.86,45.66 87.37,46.22 88.69,46.13L90.22,46.13L90.75,44.4L90.17,44.4C89.84,44.4 89.69,44.32 89.71,44.14L89.68,43.09L86.84,43.09L86.84,43.09C85.92,43.11 83.18,43.18 82.63,43.33C81.96,43.5 81.25,44.01 81.25,44.01L81.53,43.08L78.87,43.08L78.32,44.92L75.54,54.05L75.01,54.05L74.48,55.78L79.77,55.78L79.59,56.35L82.19,56.35L82.37,55.78L83.1,55.78L83.67,53.92Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M85.46,48.36L88.51,48.36L88.07,49.77L84.98,49.77L84.51,51.31L87.22,51.31L85.17,54.17C85.03,54.38 84.9,54.46 84.76,54.52C84.61,54.59 84.42,54.68 84.21,54.68L83.46,54.68L82.94,56.36L84.9,56.36C85.92,56.36 86.53,55.9 86.97,55.3L88.37,53.39L88.68,55.33C88.74,55.69 89,55.9 89.18,55.99C89.38,56.08 89.58,56.25 89.87,56.28C90.17,56.29 90.4,56.3 90.54,56.3L91.51,56.3L92.09,54.41L91.71,54.41C91.49,54.41 91.11,54.37 91.05,54.31C90.98,54.22 90.98,54.1 90.95,53.9L90.64,51.96L89.39,51.96L89.94,51.31L93.03,51.31L93.5,49.77L90.64,49.77L91.09,48.36L93.94,48.36L94.46,46.62L85.98,46.62L85.46,48.36Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M59.69,54.33L60.41,51.98L63.33,51.98L63.87,50.23L60.94,50.23L61.39,48.78L64.25,48.78L64.78,47.08L57.62,47.08L57.1,48.78L58.72,48.78L58.29,50.23L56.66,50.23L56.12,52.01L57.74,52.01L56.8,55.12C56.67,55.53 56.86,55.69 56.98,55.88C57.1,56.07 57.22,56.19 57.5,56.26C57.79,56.33 57.98,56.36 58.25,56.36L61.55,56.36L62.14,54.42L60.67,54.62C60.39,54.62 59.61,54.59 59.69,54.33"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M60.03,43.07L59.29,44.4C59.13,44.69 58.99,44.87 58.86,44.95C58.75,45.02 58.52,45.05 58.2,45.05L57.81,45.05L57.29,46.76L58.58,46.76C59.19,46.76 59.67,46.53 59.9,46.42C60.14,46.29 60.2,46.36 60.39,46.18L60.83,45.81L64.84,45.81L65.37,44.03L62.43,44.03L62.95,43.07L60.03,43.07Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M67.84,47.69L71.94,47.69L71.68,48.51C71.64,48.52 71.56,48.47 71.14,48.51L67.59,48.51L67.84,47.69ZM68.66,44.97L72.8,44.97L72.5,45.95C72.5,45.95 70.55,45.93 70.24,45.99C68.87,46.22 68.07,46.95 68.07,46.95L68.66,44.97ZM65.95,54.36C65.89,54.27 65.93,54.1 66.04,53.74L67.14,50.13L71.04,50.13C71.61,50.12 72.02,50.12 72.28,50.1C72.57,50.07 72.88,49.96 73.22,49.78C73.57,49.59 73.75,49.39 73.9,49.16C74.07,48.93 74.34,48.42 74.58,47.64L75.96,43.08L71.91,43.1C71.91,43.1 70.66,43.28 70.11,43.49C69.56,43.71 68.77,44.34 68.77,44.34L69.13,43.09L66.63,43.09L63.13,54.62C63.01,55.07 62.92,55.4 62.9,55.59C62.9,55.8 63.17,56.01 63.35,56.17C63.56,56.33 63.87,56.3 64.16,56.33C64.48,56.35 64.92,56.36 65.53,56.36L67.46,56.36L68.05,54.38L66.33,54.55C66.14,54.55 66.01,54.45 65.95,54.36L65.95,54.36Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M71.77,51.22C71.74,51.34 71.68,51.42 71.61,51.47C71.53,51.53 71.39,51.54 71.19,51.54L70.61,51.54L70.64,50.56L68.21,50.56L68.11,55.39C68.11,55.74 68.14,55.94 68.4,56.1C68.66,56.3 69.45,56.33 70.51,56.33L72.04,56.33L72.58,54.52L71.26,54.59L70.82,54.62C70.76,54.59 70.7,54.57 70.64,54.5C70.58,54.45 70.49,54.48 70.5,54.13L70.51,52.9L71.9,52.84C72.65,52.84 72.97,52.6 73.25,52.36C73.51,52.14 73.59,51.89 73.69,51.54L73.92,50.45L72.02,50.45L71.77,51.22Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M42.48,26.29C40.17,26.31 39.49,26.29 39.27,26.24C39.19,26.63 37.63,33.77 37.62,33.78C37.29,35.22 37.04,36.25 36.22,36.92C35.75,37.3 35.2,37.49 34.56,37.49C33.53,37.49 32.94,36.99 32.84,36.03L32.82,35.7C32.82,35.7 33.13,33.76 33.13,33.75C33.13,33.75 34.77,27.25 35.06,26.39C35.07,26.34 35.08,26.31 35.08,26.29C31.9,26.32 31.34,26.29 31.3,26.24C31.28,26.31 31.2,26.71 31.2,26.71L29.53,34.04L29.38,34.67L29.11,36.7C29.11,37.3 29.23,37.8 29.46,38.21C30.22,39.53 32.39,39.73 33.62,39.73C35.2,39.73 36.69,39.4 37.69,38.79C39.43,37.77 39.88,36.17 40.29,34.75L40.48,34.02C40.48,34.02 42.16,27.27 42.45,26.39C42.46,26.34 42.46,26.31 42.48,26.29"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M48.21,31.74C47.8,31.74 47.06,31.84 46.39,32.16C46.15,32.29 45.92,32.43 45.68,32.57L45.9,31.79L45.78,31.66C44.37,31.94 44.05,31.98 42.75,32.16L42.64,32.24C42.48,33.48 42.35,34.42 41.79,36.88C41.57,37.78 41.35,38.7 41.13,39.6L41.19,39.71C42.53,39.64 42.93,39.64 44.1,39.66L44.19,39.56C44.34,38.81 44.36,38.63 44.68,37.11C44.84,36.39 45.16,34.8 45.32,34.24C45.61,34.1 45.89,33.97 46.17,33.97C46.82,33.97 46.74,34.54 46.72,34.76C46.69,35.14 46.45,36.37 46.21,37.43L46.04,38.12C45.93,38.62 45.81,39.11 45.69,39.61L45.74,39.71C47.06,39.64 47.46,39.64 48.59,39.66L48.72,39.56C48.93,38.39 48.99,38.07 49.35,36.36L49.53,35.58C49.88,34.04 50.06,33.26 49.79,32.62C49.51,31.91 48.83,31.74 48.21,31.74"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M54.61,33.35C53.91,33.48 53.46,33.57 53.02,33.63C52.58,33.7 52.15,33.76 51.47,33.86L51.42,33.91L51.37,33.95C51.3,34.45 51.25,34.88 51.16,35.39C51.08,35.92 50.95,36.51 50.76,37.37C50.6,38.03 50.52,38.26 50.43,38.49C50.35,38.73 50.26,38.95 50.08,39.6L50.12,39.66L50.16,39.71C50.79,39.68 51.2,39.66 51.63,39.66C52.05,39.64 52.5,39.66 53.18,39.66L53.24,39.61L53.3,39.56C53.4,38.98 53.41,38.82 53.47,38.53C53.53,38.23 53.64,37.81 53.89,36.68C54.01,36.15 54.14,35.62 54.27,35.07C54.39,34.54 54.53,34 54.66,33.47L54.64,33.41L54.61,33.35Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M58.38,35.95C58.68,34.64 59.03,33.55 59.92,33.55C60.62,33.55 60.67,34.36 60.36,35.67C60.31,35.96 60.05,37.05 59.7,37.51C59.46,37.85 59.18,38.05 58.86,38.05C58.76,38.05 58.2,38.05 58.2,37.23C58.19,36.82 58.28,36.4 58.38,35.95M58.48,39.83C59.77,39.83 61.09,39.48 62.08,38.43C62.85,37.58 63.2,36.32 63.32,35.8C63.72,34.07 63.41,33.27 63.02,32.78C62.43,32.03 61.39,31.79 60.32,31.79C59.67,31.79 58.13,31.85 56.92,32.96C56.05,33.75 55.65,34.83 55.41,35.87C55.17,36.93 54.89,38.83 56.65,39.53C57.19,39.77 57.97,39.83 58.48,39.83"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M86.63,36.09C86.93,34.81 87.28,33.72 88.18,33.72C88.74,33.72 89.04,34.24 88.98,35.13C88.93,35.35 88.88,35.58 88.82,35.85C88.73,36.23 88.63,36.6 88.54,36.98C88.44,37.24 88.33,37.49 88.21,37.65C87.97,37.97 87.43,38.18 87.11,38.18C87.02,38.18 86.47,38.18 86.45,37.36C86.44,36.96 86.53,36.54 86.63,36.09M83.67,36.02C83.43,37.06 83.14,38.97 84.89,39.64C85.45,39.88 85.95,39.95 86.46,39.92C87,39.89 87.5,39.63 87.96,39.24C87.91,39.4 87.87,39.56 87.83,39.72L87.91,39.82C89.17,39.77 89.56,39.77 90.92,39.78L91.05,39.68C91.25,38.52 91.44,37.39 91.95,35.16C92.21,34.1 92.46,33.04 92.72,31.98L92.68,31.86C91.27,32.12 90.89,32.18 89.54,32.37L89.43,32.45C89.42,32.56 89.41,32.66 89.39,32.77C89.18,32.43 88.88,32.14 88.4,31.96C87.8,31.73 86.39,32.03 85.17,33.13C84.32,33.92 83.91,34.99 83.67,36.02"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M66.54,39.66L66.64,39.56C66.78,38.81 66.81,38.63 67.13,37.11C67.28,36.39 67.61,34.8 67.76,34.24C68.05,34.1 68.34,33.97 68.62,33.97C69.27,33.97 69.19,34.54 69.16,34.76C69.14,35.14 68.9,36.37 68.65,37.43L68.5,38.12C68.38,38.62 68.25,39.11 68.14,39.61L68.19,39.71C69.51,39.64 69.9,39.64 71.03,39.66L71.17,39.56C71.37,38.39 71.42,38.07 71.79,36.36L71.97,35.58C72.33,34.04 72.5,33.26 72.24,32.62C71.95,31.91 71.27,31.74 70.66,31.74C70.25,31.74 69.5,31.84 68.84,32.16C68.6,32.29 68.37,32.43 68.13,32.57L68.34,31.79L68.23,31.66C66.81,31.94 66.49,31.98 65.19,32.16L65.09,32.24C64.93,33.48 64.8,34.42 64.24,36.88C64.03,37.78 63.8,38.7 63.58,39.6L63.64,39.71C64.98,39.64 65.38,39.64 66.54,39.66"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M77.88,32.56C77.88,32.56 78.81,28.54 78.81,28.56L78.84,28.35L78.85,28.19L79.22,28.23C79.22,28.23 81.14,28.4 81.19,28.4C81.94,28.69 82.25,29.44 82.04,30.42C81.84,31.31 81.25,32.07 80.5,32.43C79.89,32.74 79.13,32.76 78.35,32.76L77.84,32.76L77.88,32.56ZM76.26,39.71C76.35,39.31 76.84,36.92 76.84,36.92C76.84,36.92 77.27,35.16 77.29,35.1C77.29,35.1 77.42,34.92 77.56,34.85L77.75,34.85C79.59,34.85 81.66,34.85 83.29,33.66C84.4,32.84 85.16,31.64 85.49,30.17C85.58,29.81 85.65,29.39 85.65,28.96C85.65,28.4 85.53,27.85 85.2,27.41C84.37,26.26 82.72,26.24 80.82,26.23C80.81,26.23 79.88,26.24 79.88,26.24C77.43,26.27 76.46,26.26 76.05,26.21C76.02,26.39 75.96,26.7 75.96,26.7C75.96,26.7 75.08,30.73 75.08,30.73C75.08,30.73 72.99,39.29 72.89,39.7C75.02,39.67 75.9,39.67 76.26,39.71L76.26,39.71Z"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M102.08,31.85L101.97,31.73C100.58,32.01 100.32,32.05 99.04,32.23L98.95,32.32C98.94,32.34 98.94,32.36 98.93,32.38L98.93,32.36C97.98,34.54 98,34.07 97.23,35.79C97.22,35.71 97.22,35.67 97.22,35.58L97.03,31.85L96.9,31.73C95.44,32.01 95.41,32.05 94.06,32.23L93.96,32.32C93.94,32.36 93.94,32.41 93.93,32.47L93.94,32.49C94.11,33.34 94.07,33.15 94.24,34.5C94.32,35.16 94.42,35.83 94.5,36.48C94.63,37.58 94.71,38.12 94.87,39.79C93.96,41.28 93.74,41.85 92.87,43.16L92.87,43.17L92.26,44.14C92.19,44.25 92.12,44.32 92.03,44.35C91.93,44.39 91.81,44.4 91.63,44.4L91.29,44.4L90.78,46.08L92.52,46.11C93.55,46.11 94.19,45.63 94.54,44.99L95.63,43.13L95.61,43.13L95.73,42.99C96.47,41.42 102.08,31.85 102.08,31.85"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+    <path
+        android:pathData="M54.63,31.18C53.99,30.81 52.87,30.92 52.12,31.44C51.37,31.95 51.28,32.66 51.92,33.04C52.54,33.41 53.67,33.3 54.41,32.78C55.16,32.26 55.25,31.55 54.63,31.18"
+        android:strokeColor="#00000000"
+        android:fillColor="#FEFEFE"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index c8b72ea..8f3f744 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -98,7 +98,7 @@
     <dimen name="infobar_big_icon_margin">16dp</dimen>
 
     <!-- Dimensions for compact infobars are a little shorter. -->
-    <dimen name="infobar_compact_size">48dp</dimen>
+    <dimen name="infobar_compact_size">56dp</dimen>
 
     <!-- Dimensions for compact translate infobar. -->
     <dimen name="infobar_translate_fade_edge_length">18dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
index 793c7df4..3c26b3e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
@@ -96,8 +96,7 @@
             int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1);
             String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA);
             openUrl(intent.getData());
-            recordCachedActionMetric(ContentSuggestionsNotificationAction.TAP);
-            removeActiveNotification(category, idWithinCategory);
+            hideNotification(category, idWithinCategory, ContentSuggestionsNotificationAction.TAP);
         }
     }
 
@@ -109,8 +108,9 @@
         public void onReceive(Context context, Intent intent) {
             int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1);
             String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA);
-            recordCachedActionMetric(ContentSuggestionsNotificationAction.DISMISSAL);
-            removeActiveNotification(category, idWithinCategory);
+            if (removeActiveNotification(category, idWithinCategory)) {
+                recordCachedActionMetric(ContentSuggestionsNotificationAction.DISMISSAL);
+            }
         }
     }
 
@@ -122,10 +122,6 @@
         public void onReceive(Context context, Intent intent) {
             int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1);
             String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITHIN_CATEGORY_EXTRA);
-            if (findActiveNotification(category, idWithinCategory) == null) {
-                return; // tapped or swiped
-            }
-
             hideNotification(
                     category, idWithinCategory, ContentSuggestionsNotificationAction.HIDE_DEADLINE);
         }
@@ -172,7 +168,6 @@
                 NotificationBuilderFactory
                         .createChromeNotificationBuilder(
                                 true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_BROWSER)
-                        .setAutoCancel(true)
                         .setContentIntent(contentIntent)
                         .setDeleteIntent(deleteIntent)
                         .setContentTitle(title)
@@ -206,17 +201,22 @@
         return true;
     }
 
+    /**
+     * Hides a notification and records an action to the Actions histogram.
+     *
+     * If the notification is not actually visible, then no action will be taken, and the action
+     * will not be recorded.
+     */
     @CalledByNative
     private static void hideNotification(int category, String idWithinCategory, int why) {
+        ActiveNotification activeNotification = findActiveNotification(category, idWithinCategory);
+        if (!removeActiveNotification(category, idWithinCategory)) return;
+
         Context context = ContextUtils.getApplicationContext();
         NotificationManager manager =
                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        ActiveNotification activeNotification = findActiveNotification(category, idWithinCategory);
-        if (activeNotification == null) return;
         manager.cancel(NOTIFICATION_TAG, activeNotification.mId);
-        if (removeActiveNotification(category, idWithinCategory)) {
-            recordCachedActionMetric(why);
-        }
+        recordCachedActionMetric(why);
     }
 
     @CalledByNative
@@ -285,6 +285,7 @@
         return new HashSet<String>(prefValue);
     }
 
+    /** Adds notification to the "active" set. */
     private static void addActiveNotification(ActiveNotification notification) {
         SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
         Set<String> activeNotifications =
@@ -293,6 +294,7 @@
         prefs.edit().putStringSet(PREF_ACTIVE_NOTIFICATIONS, activeNotifications).apply();
     }
 
+    /** Removes notification from the "active" set. Returns false if it wasn't there. */
     private static boolean removeActiveNotification(int category, String idWithinCategory) {
         SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
         ActiveNotification notification = findActiveNotification(category, idWithinCategory);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
index 0910cce6..517d3f8e1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
@@ -33,10 +33,10 @@
     private VisibleNetworks(@Nullable VisibleWifi connectedWifi,
             @Nullable VisibleCell connectedCell, @Nullable Set<VisibleWifi> allVisibleWifis,
             @Nullable Set<VisibleCell> allVisibleCells) {
-        this.mConnectedWifi = connectedWifi;
-        this.mConnectedCell = connectedCell;
-        this.mAllVisibleWifis = allVisibleWifis;
-        this.mAllVisibleCells = allVisibleCells;
+        mConnectedWifi = connectedWifi;
+        mConnectedCell = connectedCell;
+        mAllVisibleWifis = allVisibleWifis;
+        mAllVisibleCells = allVisibleCells;
     }
 
     public static VisibleNetworks create(@Nullable VisibleWifi connectedWifi,
@@ -101,11 +101,10 @@
             return false;
         }
         VisibleNetworks that = (VisibleNetworks) object;
-        return ApiCompatibilityUtils.objectEquals(this.mConnectedWifi, that.connectedWifi())
-                && ApiCompatibilityUtils.objectEquals(this.mConnectedCell, that.connectedCell())
-                && ApiCompatibilityUtils.objectEquals(this.mAllVisibleWifis, that.allVisibleWifis())
-                && ApiCompatibilityUtils.objectEquals(
-                           this.mAllVisibleCells, that.allVisibleCells());
+        return ApiCompatibilityUtils.objectEquals(mConnectedWifi, that.connectedWifi())
+                && ApiCompatibilityUtils.objectEquals(mConnectedCell, that.connectedCell())
+                && ApiCompatibilityUtils.objectEquals(mAllVisibleWifis, that.allVisibleWifis())
+                && ApiCompatibilityUtils.objectEquals(mAllVisibleCells, that.allVisibleCells());
     }
 
     private static int objectsHashCode(Object o) {
@@ -118,8 +117,8 @@
 
     @Override
     public int hashCode() {
-        return objectsHash(this.mConnectedWifi, this.mConnectedCell,
-                objectsHashCode(this.mAllVisibleWifis), objectsHashCode(this.mAllVisibleCells));
+        return objectsHash(mConnectedWifi, mConnectedCell, objectsHashCode(mAllVisibleWifis),
+                objectsHashCode(mAllVisibleCells));
     }
 
     /**
@@ -139,10 +138,10 @@
 
         private VisibleWifi(@Nullable String ssid, @Nullable String bssid, @Nullable Integer level,
                 @Nullable Long timestampMs) {
-            this.mSsid = ssid;
-            this.mBssid = bssid;
-            this.mLevel = level;
-            this.mTimestampMs = timestampMs;
+            mSsid = ssid;
+            mBssid = bssid;
+            mLevel = level;
+            mTimestampMs = timestampMs;
         }
 
         public static VisibleWifi create(@Nullable String ssid, @Nullable String bssid,
@@ -194,13 +193,34 @@
             }
 
             VisibleWifi that = (VisibleWifi) object;
-            return ApiCompatibilityUtils.objectEquals(this.mSsid, that.ssid())
-                    && ApiCompatibilityUtils.objectEquals(this.mBssid, that.bssid());
+            return ApiCompatibilityUtils.objectEquals(mSsid, that.ssid())
+                    && ApiCompatibilityUtils.objectEquals(mBssid, that.bssid());
         }
 
         @Override
         public int hashCode() {
-            return VisibleNetworks.objectsHash(this.mSsid, this.mBssid);
+            return VisibleNetworks.objectsHash(mSsid, mBssid);
+        }
+
+        /**
+         * Encodes a VisibleWifi into its corresponding PartnerLocationDescriptor.VisibleNetwork
+         * proto.
+         */
+        public PartnerLocationDescriptor.VisibleNetwork toProto(boolean connected) {
+            PartnerLocationDescriptor.VisibleNetwork visibleNetwork =
+                    new PartnerLocationDescriptor.VisibleNetwork();
+
+            PartnerLocationDescriptor.VisibleNetwork.WiFi wifi =
+                    new PartnerLocationDescriptor.VisibleNetwork.WiFi();
+
+            wifi.bssid = bssid();
+            wifi.levelDbm = level();
+
+            visibleNetwork.wifi = wifi;
+            visibleNetwork.timestampMs = timestampMs();
+            visibleNetwork.connected = connected;
+
+            return visibleNetwork;
         }
     }
 
@@ -252,15 +272,15 @@
         private Long mTimestampMs;
 
         private VisibleCell(Builder builder) {
-            this.mRadioType = builder.mRadioType;
-            this.mCellId = builder.mCellId;
-            this.mLocationAreaCode = builder.mLocationAreaCode;
-            this.mMobileCountryCode = builder.mMobileCountryCode;
-            this.mMobileNetworkCode = builder.mMobileNetworkCode;
-            this.mPrimaryScramblingCode = builder.mPrimaryScramblingCode;
-            this.mPhysicalCellId = builder.mPhysicalCellId;
-            this.mTrackingAreaCode = builder.mTrackingAreaCode;
-            this.mTimestampMs = builder.mTimestampMs;
+            mRadioType = builder.mRadioType;
+            mCellId = builder.mCellId;
+            mLocationAreaCode = builder.mLocationAreaCode;
+            mMobileCountryCode = builder.mMobileCountryCode;
+            mMobileNetworkCode = builder.mMobileNetworkCode;
+            mPrimaryScramblingCode = builder.mPrimaryScramblingCode;
+            mPhysicalCellId = builder.mPhysicalCellId;
+            mTrackingAreaCode = builder.mTrackingAreaCode;
+            mTimestampMs = builder.mTimestampMs;
         }
 
         /**
@@ -347,27 +367,71 @@
                 return false;
             }
             VisibleCell that = (VisibleCell) object;
-            return ApiCompatibilityUtils.objectEquals(this.mRadioType, that.radioType())
-                    && ApiCompatibilityUtils.objectEquals(this.mCellId, that.cellId())
+            return ApiCompatibilityUtils.objectEquals(mRadioType, that.radioType())
+                    && ApiCompatibilityUtils.objectEquals(mCellId, that.cellId())
                     && ApiCompatibilityUtils.objectEquals(
-                               this.mLocationAreaCode, that.locationAreaCode())
+                               mLocationAreaCode, that.locationAreaCode())
                     && ApiCompatibilityUtils.objectEquals(
-                               this.mMobileCountryCode, that.mobileCountryCode())
+                               mMobileCountryCode, that.mobileCountryCode())
                     && ApiCompatibilityUtils.objectEquals(
-                               this.mMobileNetworkCode, that.mobileNetworkCode())
+                               mMobileNetworkCode, that.mobileNetworkCode())
                     && ApiCompatibilityUtils.objectEquals(
-                               this.mPrimaryScramblingCode, that.primaryScramblingCode())
+                               mPrimaryScramblingCode, that.primaryScramblingCode())
+                    && ApiCompatibilityUtils.objectEquals(mPhysicalCellId, that.physicalCellId())
                     && ApiCompatibilityUtils.objectEquals(
-                               this.mPhysicalCellId, that.physicalCellId())
-                    && ApiCompatibilityUtils.objectEquals(
-                               this.mTrackingAreaCode, that.trackingAreaCode());
+                               mTrackingAreaCode, that.trackingAreaCode());
         }
 
         @Override
         public int hashCode() {
-            return VisibleNetworks.objectsHash(this.mRadioType, this.mCellId,
-                    this.mLocationAreaCode, this.mMobileCountryCode, this.mMobileNetworkCode,
-                    this.mPrimaryScramblingCode, this.mPhysicalCellId, this.mTrackingAreaCode);
+            return VisibleNetworks.objectsHash(mRadioType, mCellId, mLocationAreaCode,
+                    mMobileCountryCode, mMobileNetworkCode, mPrimaryScramblingCode, mPhysicalCellId,
+                    mTrackingAreaCode);
+        }
+
+        /**
+         * Encodes a VisibleCell into its corresponding PartnerLocationDescriptor.VisibleNetwork
+         * proto.
+         */
+        public PartnerLocationDescriptor.VisibleNetwork toProto(boolean connected) {
+            PartnerLocationDescriptor.VisibleNetwork visibleNetwork =
+                    new PartnerLocationDescriptor.VisibleNetwork();
+
+            PartnerLocationDescriptor.VisibleNetwork.Cell cell =
+                    new PartnerLocationDescriptor.VisibleNetwork.Cell();
+
+            switch (radioType()) {
+                case VisibleCell.CDMA_RADIO_TYPE:
+                    cell.type = PartnerLocationDescriptor.VisibleNetwork.Cell.CDMA;
+                    break;
+                case VisibleCell.GSM_RADIO_TYPE:
+                    cell.type = PartnerLocationDescriptor.VisibleNetwork.Cell.GSM;
+                    break;
+                case VisibleCell.LTE_RADIO_TYPE:
+                    cell.type = PartnerLocationDescriptor.VisibleNetwork.Cell.LTE;
+                    break;
+                case VisibleCell.WCDMA_RADIO_TYPE:
+                    cell.type = PartnerLocationDescriptor.VisibleNetwork.Cell.WCDMA;
+                    break;
+                case VisibleCell.UNKNOWN_RADIO_TYPE:
+                case VisibleCell.UNKNOWN_MISSING_LOCATION_PERMISSION_RADIO_TYPE:
+                default:
+                    cell.type = PartnerLocationDescriptor.VisibleNetwork.Cell.UNKNOWN;
+                    break;
+            }
+            cell.cellId = cellId();
+            cell.locationAreaCode = locationAreaCode();
+            cell.mobileCountryCode = mobileCountryCode();
+            cell.mobileNetworkCode = mobileNetworkCode();
+            cell.primaryScramblingCode = primaryScramblingCode();
+            cell.physicalCellId = physicalCellId();
+            cell.trackingAreaCode = trackingAreaCode();
+
+            visibleNetwork.cell = cell;
+            visibleNetwork.timestampMs = timestampMs();
+            visibleNetwork.connected = connected;
+
+            return visibleNetwork;
         }
 
         /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
index efaf9f0b..864760e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
@@ -27,6 +27,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.PaymentCurrencyAmount;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
@@ -166,9 +167,9 @@
             public void onServiceDisconnected(ComponentName name) {}
         };
 
-        mIsReadyToPayIntent.putExtras(buildExtras(null /* id */, null /* merchantName */, origin,
-                iframeOrigin, certificateChain, methodDataMap, total, null /* displayItems */,
-                null /* modifiers */));
+        mIsReadyToPayIntent.putExtras(buildExtras(null /* id */, null /* merchantName */,
+                removeUrlScheme(origin), removeUrlScheme(iframeOrigin), certificateChain,
+                methodDataMap, total, null /* displayItems */, null /* modifiers */));
         try {
             if (!ContextUtils.getApplicationContext().bindService(
                         mIsReadyToPayIntent, mServiceConnection, Context.BIND_AUTO_CREATE)) {
@@ -264,17 +265,19 @@
     }
 
     @Override
-    public void invokePaymentApp(final String id, final String merchantName, final String origin,
-            final String iframeOrigin, final byte[][] certificateChain,
+    public void invokePaymentApp(final String id, final String merchantName, String origin,
+            String iframeOrigin, final byte[][] certificateChain,
             final Map<String, PaymentMethodData> methodDataMap, final PaymentItem total,
             final List<PaymentItem> displayItems,
             final Map<String, PaymentDetailsModifier> modifiers,
             InstrumentDetailsCallback callback) {
         mInstrumentDetailsCallback = callback;
 
+        final String schemelessOrigin = removeUrlScheme(origin);
+        final String schemelessIframeOrigin = removeUrlScheme(iframeOrigin);
         if (!mIsIncognito) {
-            launchPaymentApp(id, merchantName, origin, iframeOrigin, certificateChain,
-                    methodDataMap, total, displayItems, modifiers);
+            launchPaymentApp(id, merchantName, schemelessOrigin, schemelessIframeOrigin,
+                    certificateChain, methodDataMap, total, displayItems, modifiers);
             return;
         }
 
@@ -291,9 +294,9 @@
                         new OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int which) {
-                                launchPaymentApp(id, merchantName, origin, iframeOrigin,
-                                        certificateChain, methodDataMap, total, displayItems,
-                                        modifiers);
+                                launchPaymentApp(id, merchantName, schemelessOrigin,
+                                        schemelessIframeOrigin, certificateChain, methodDataMap,
+                                        total, displayItems, modifiers);
                             }
                         })
                 .setNegativeButton(R.string.cancel,
@@ -312,6 +315,10 @@
                 .show();
     }
 
+    private static String removeUrlScheme(String url) {
+        return UrlFormatter.formatUrlForSecurityDisplay(url, false /* omit scheme */);
+    }
+
     private void launchPaymentApp(String id, String merchantName, String origin,
             String iframeOrigin, byte[][] certificateChain,
             Map<String, PaymentMethodData> methodDataMap, PaymentItem total,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
index f8973c96d..b10e349 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
@@ -5,10 +5,10 @@
 package org.chromium.chrome.browser.payments;
 
 import android.content.Context;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.util.JsonWriter;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
@@ -66,8 +66,8 @@
         if (context == null) return;
 
         if (card.getIssuerIconDrawableId() != 0) {
-            updateDrawableIcon(ApiCompatibilityUtils.getDrawable(
-                    context.getResources(), card.getIssuerIconDrawableId()));
+            updateDrawableIcon(
+                    AppCompatResources.getDrawable(context, card.getIssuerIconDrawableId()));
         }
 
         checkAndUpateCardCompleteness(context);
@@ -261,8 +261,7 @@
         if (context == null) return;
 
         updateIdentifierLabelsAndIcon(card.getGUID(), card.getObfuscatedNumber(), card.getName(),
-                null, ApiCompatibilityUtils.getDrawable(
-                        context.getResources(), card.getIssuerIconDrawableId()));
+                null, AppCompatResources.getDrawable(context, card.getIssuerIconDrawableId()));
         checkAndUpateCardCompleteness(context);
         assert mIsComplete;
         assert mHasValidNumberAndName;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
index f12ab2e..281c0fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -54,7 +54,7 @@
     private static class CardIssuerNetwork {
         /**
          * The identifier for the drawable resource of the card issuer network, e.g.,
-         * R.drawable.pr_visa.
+         * R.drawable.visa_card.
          */
         public final int icon;
 
@@ -211,21 +211,21 @@
 
         mCardIssuerNetworks = new HashMap<>();
         mCardIssuerNetworks.put(
-                AMEX, new CardIssuerNetwork(R.drawable.pr_amex, R.string.autofill_cc_amex));
-        mCardIssuerNetworks.put(DINERS,
-                new CardIssuerNetwork(R.drawable.pr_dinersclub, R.string.autofill_cc_diners));
+                AMEX, new CardIssuerNetwork(R.drawable.amex_card, R.string.autofill_cc_amex));
+        mCardIssuerNetworks.put(
+                DINERS, new CardIssuerNetwork(R.drawable.diners_card, R.string.autofill_cc_diners));
         mCardIssuerNetworks.put(DISCOVER,
-                new CardIssuerNetwork(R.drawable.pr_discover, R.string.autofill_cc_discover));
+                new CardIssuerNetwork(R.drawable.discover_card, R.string.autofill_cc_discover));
         mCardIssuerNetworks.put(
-                JCB, new CardIssuerNetwork(R.drawable.pr_jcb, R.string.autofill_cc_jcb));
+                JCB, new CardIssuerNetwork(R.drawable.jcb_card, R.string.autofill_cc_jcb));
         mCardIssuerNetworks.put(MASTERCARD,
-                new CardIssuerNetwork(R.drawable.pr_mc, R.string.autofill_cc_mastercard));
+                new CardIssuerNetwork(R.drawable.mc_card, R.string.autofill_cc_mastercard));
         mCardIssuerNetworks.put(
-                MIR, new CardIssuerNetwork(R.drawable.pr_mir, R.string.autofill_cc_mir));
+                MIR, new CardIssuerNetwork(R.drawable.mir_card, R.string.autofill_cc_mir));
         mCardIssuerNetworks.put(UNIONPAY,
-                new CardIssuerNetwork(R.drawable.pr_unionpay, R.string.autofill_cc_union_pay));
+                new CardIssuerNetwork(R.drawable.unionpay_card, R.string.autofill_cc_union_pay));
         mCardIssuerNetworks.put(
-                VISA, new CardIssuerNetwork(R.drawable.pr_visa, R.string.autofill_cc_visa));
+                VISA, new CardIssuerNetwork(R.drawable.visa_card, R.string.autofill_cc_visa));
 
         mAcceptedIssuerNetworks = new HashSet<>();
         mAcceptedBasicCardIssuerNetworks = new HashSet<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index a5ecb24a..d21b6367 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -257,9 +257,8 @@
     private final Handler mHandler = new Handler();
     private final RenderFrameHost mRenderFrameHost;
     private final WebContents mWebContents;
-    private final String mSchemelessOriginForPaymentApp;
-    private final String mOriginForDisplay;
-    private final String mSchemelessIFrameOriginForPaymentApp;
+    private final String mTopLevelOrigin;
+    private final String mPaymentRequestOrigin;
     private final String mMerchantName;
     @Nullable
     private final byte[][] mCertificateChain;
@@ -364,15 +363,12 @@
         assert renderFrameHost != null;
 
         mRenderFrameHost = renderFrameHost;
-        mSchemelessIFrameOriginForPaymentApp = UrlFormatter.formatUrlForSecurityDisplay(
-                mRenderFrameHost.getLastCommittedURL(), false /* omit scheme for payment apps. */);
         mWebContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost);
 
-        mSchemelessOriginForPaymentApp = UrlFormatter.formatUrlForSecurityDisplay(
-                mWebContents.getLastCommittedUrl(), false /* omit scheme for payment apps. */);
-
-        mOriginForDisplay = UrlFormatter.formatUrlForSecurityDisplay(
-                mWebContents.getLastCommittedUrl(), true /* include scheme in display */);
+        mPaymentRequestOrigin = UrlFormatter.formatUrlForSecurityDisplay(
+                mRenderFrameHost.getLastCommittedURL(), true);
+        mTopLevelOrigin =
+                UrlFormatter.formatUrlForSecurityDisplay(mWebContents.getLastCommittedUrl(), true);
 
         mMerchantName = mWebContents.getTitle();
 
@@ -521,7 +517,7 @@
         mUI = new PaymentRequestUI(activity, this, mRequestShipping,
                 mRequestPayerName || mRequestPayerPhone || mRequestPayerEmail,
                 mMerchantSupportsAutofillPaymentInstruments,
-                !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mOriginForDisplay,
+                !PaymentPreferencesUtil.isPaymentCompleteOnce(), mMerchantName, mTopLevelOrigin,
                 SecurityStateModel.getSecurityLevelForWebContents(mWebContents),
                 new ShippingStrings(mShippingType));
 
@@ -717,8 +713,7 @@
         }
 
         if (queryApps.isEmpty()) {
-            CanMakePaymentQuery query =
-                    sCanMakePaymentQueries.get(mSchemelessIFrameOriginForPaymentApp);
+            CanMakePaymentQuery query = sCanMakePaymentQueries.get(mPaymentRequestOrigin);
             if (query != null && query.matchesPaymentMethods(mMethodData)) {
                 query.notifyObserversOfResponse(mCanMakePayment);
             }
@@ -730,8 +725,8 @@
         // so a fast response from a non-autofill payment app at the front of the app list does not
         // cause NOT_SUPPORTED payment rejection.
         for (Map.Entry<PaymentApp, Map<String, PaymentMethodData>> q : queryApps.entrySet()) {
-            q.getKey().getInstruments(q.getValue(), mSchemelessOriginForPaymentApp,
-                    mSchemelessIFrameOriginForPaymentApp, mCertificateChain, mRawTotal, this);
+            q.getKey().getInstruments(q.getValue(), mTopLevelOrigin, mPaymentRequestOrigin,
+                    mCertificateChain, mRawTotal, this);
         }
     }
 
@@ -1302,10 +1297,9 @@
             }
         }
 
-        instrument.invokePaymentApp(mId, mMerchantName, mSchemelessOriginForPaymentApp,
-                mSchemelessIFrameOriginForPaymentApp, mCertificateChain,
-                Collections.unmodifiableMap(methodData), mRawTotal, mRawLineItems,
-                Collections.unmodifiableMap(modifiers), this);
+        instrument.invokePaymentApp(mId, mMerchantName, mTopLevelOrigin, mPaymentRequestOrigin,
+                mCertificateChain, Collections.unmodifiableMap(methodData), mRawTotal,
+                mRawLineItems, Collections.unmodifiableMap(modifiers), this);
 
         mJourneyLogger.setEventOccurred(JourneyLogger.EVENT_PAY_CLICKED);
         return !(instrument instanceof AutofillPaymentInstrument);
@@ -1391,19 +1385,18 @@
     public void canMakePayment() {
         if (mClient == null) return;
 
-        CanMakePaymentQuery query =
-                sCanMakePaymentQueries.get(mSchemelessIFrameOriginForPaymentApp);
+        CanMakePaymentQuery query = sCanMakePaymentQueries.get(mPaymentRequestOrigin);
         if (query == null) {
             // If there has not been a canMakePayment() query in the last 30 minutes, take a note
             // that one has happened just now. Remember the payment method names and the
             // corresponding data for the next 30 minutes. Forget about it after the 30 minute
             // period expires.
             query = new CanMakePaymentQuery(Collections.unmodifiableMap(mMethodData));
-            sCanMakePaymentQueries.put(mSchemelessIFrameOriginForPaymentApp, query);
+            sCanMakePaymentQueries.put(mPaymentRequestOrigin, query);
             mHandler.postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    sCanMakePaymentQueries.remove(mSchemelessIFrameOriginForPaymentApp);
+                    sCanMakePaymentQueries.remove(mPaymentRequestOrigin);
                 }
             }, CAN_MAKE_PAYMENT_QUERY_PERIOD_MS);
         } else if (shouldEnforceCanMakePaymentQueryQuota()
@@ -1427,8 +1420,7 @@
 
         boolean isIgnoringQueryQuota = false;
         if (!shouldEnforceCanMakePaymentQueryQuota()) {
-            CanMakePaymentQuery query =
-                    sCanMakePaymentQueries.get(mSchemelessIFrameOriginForPaymentApp);
+            CanMakePaymentQuery query = sCanMakePaymentQueries.get(mPaymentRequestOrigin);
             // The cached query may have expired between instantiation of PaymentRequest and
             // finishing the query of the payment apps.
             if (query != null) {
@@ -1572,8 +1564,7 @@
             }
         }
 
-        CanMakePaymentQuery query =
-                sCanMakePaymentQueries.get(mSchemelessIFrameOriginForPaymentApp);
+        CanMakePaymentQuery query = sCanMakePaymentQueries.get(mPaymentRequestOrigin);
         if (query != null && query.matchesPaymentMethods(mMethodData)) {
             query.notifyObserversOfResponse(mCanMakePayment);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorIconsField.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorIconsField.java
index afce857..b9b48d67 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorIconsField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorIconsField.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.payments.ui;
 
 import android.content.Context;
+import android.support.v7.content.res.AppCompatResources;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -47,8 +48,8 @@
         ApiCompatibilityUtils.setMarginEnd(layoutParams, margin);
         for (int i = 0; i < fieldModel.getIconResourceIds().size(); i++) {
             ImageView icon = new ImageView(context);
-            icon.setImageResource(fieldModel.getIconResourceIds().get(i));
-            icon.setBackgroundResource(R.drawable.payments_ui_logo_bg);
+            icon.setImageDrawable(AppCompatResources.getDrawable(
+                    context, fieldModel.getIconResourceIds().get(i)));
             icon.setContentDescription(context.getString(
                     fieldModel.getIconDescriptionsForAccessibility().get(i)));
             icon.setAdjustViewBounds(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorLabelField.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorLabelField.java
index 9b1eece8..695fe43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorLabelField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorLabelField.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.payments.ui;
 
 import android.content.Context;
+import android.support.v7.content.res.AppCompatResources;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -49,11 +50,9 @@
         ((TextView) mLayout.findViewById(R.id.top_label)).setText(fieldModel.getLabel());
         ((TextView) mLayout.findViewById(R.id.mid_label)).setText(fieldModel.getMidLabel());
         ((TextView) mLayout.findViewById(R.id.bottom_label)).setText(fieldModel.getBottomLabel());
-
-        ((ImageView) mLayout.findViewById(R.id.icon)).setImageResource(
-                fieldModel.getLabelIconResourceId());
         ((ImageView) mLayout.findViewById(R.id.icon))
-                .setBackgroundResource(R.drawable.payments_ui_logo_bg);
+                .setImageDrawable(AppCompatResources.getDrawable(
+                        context, fieldModel.getLabelIconResourceId()));
     }
 
     /** @return The View containing everything. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorTextField.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorTextField.java
index 46a027a..d7838c7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorTextField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorTextField.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.payments.ui;
 
 import android.content.Context;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.InputType;
@@ -91,7 +92,6 @@
 
         if (fieldModel.getValueIconGenerator() != null) {
             mValueIcon = (ImageView) mIconsLayer.findViewById(R.id.value_icon);
-            mValueIcon.setBackgroundResource(R.drawable.payments_ui_logo_bg);
             mValueIcon.setVisibility(VISIBLE);
         }
 
@@ -270,7 +270,7 @@
         if (mValueIconId == 0) {
             mValueIcon.setVisibility(GONE);
         } else {
-            mValueIcon.setImageResource(mValueIconId);
+            mValueIcon.setImageDrawable(AppCompatResources.getDrawable(getContext(), mValueIconId));
             mValueIcon.setVisibility(VISIBLE);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
index 665f1a3b..0ca58da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -184,17 +184,11 @@
      * Sets what logo should be displayed.
      *
      * @param logo       The logo to display.
-     * @param drawBorder Whether draw border background for the logo.
      */
-    protected void setLogoDrawable(Drawable logo, boolean drawBorder) {
+    protected void setLogoDrawable(Drawable logo) {
         assert isLogoNecessary();
         mLogo = logo;
-
-        if (drawBorder) {
-            mLogoView.setBackgroundResource(R.drawable.payments_ui_logo_bg);
-        } else {
-            mLogoView.setBackgroundResource(0);
-        }
+        mLogoView.setBackgroundResource(0);
         mLogoView.setImageDrawable(mLogo);
     }
 
@@ -1111,8 +1105,6 @@
                 ImageView optionIcon = new ImageView(parent.getContext());
                 optionIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
                 if (mOption.isEditable()) {
-                    // Draw border background for the icon if the option is editable.
-                    optionIcon.setBackgroundResource(R.drawable.payments_ui_logo_bg);
                     optionIcon.setMaxWidth(mEditableOptionIconMaxWidth);
                 } else {
                     optionIcon.setMaxWidth(mNonEditableOptionIconMaxWidth);
@@ -1376,7 +1368,7 @@
             }
 
             if (selectedItem == null) {
-                setLogoDrawable(null, false);
+                setLogoDrawable(null);
                 // Section summary should be displayed as R.style.PaymentsUiSectionDescriptiveText.
                 if (!mSummaryInDescriptiveText) {
                     ApiCompatibilityUtils.setTextAppearance(
@@ -1386,7 +1378,7 @@
                 SectionUiUtils.showSectionSummaryInTextViewInSingeLine(
                         getContext(), mSectionInformation, getSummaryLeftTextView());
             } else {
-                setLogoDrawable(selectedItem.getDrawableIcon(), selectedItem.isEditable());
+                setLogoDrawable(selectedItem.getDrawableIcon());
                 // Selected item summary should be displayed as
                 // R.style.PaymentsUiSectionDefaultText.
                 if (mSummaryInDescriptiveText) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
index 56968d8..c573b63 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
@@ -71,8 +71,12 @@
             if (isMovingUp && !mAnimatingToolbarButtonDisappearance
                     && mToolbarButtonVisibilityPercent != 0.f) {
                 animateToolbarButtonVisibility(false);
-            } else if (isMovingDown && heightFraction <= 0.5f && !mAnimatingToolbarButtonAppearance
+            } else if (isMovingDown && heightFraction < 0.45f && !mAnimatingToolbarButtonAppearance
                     && mToolbarButtonVisibilityPercent != 1.f) {
+                // If the sheet is moving down and the height is less than 45% of the max, start
+                // showing the toolbar buttons. 45% is used rather than 50% so that the buttons
+                // aren't shown in the half height state if the user is dragging the sheet down
+                // slowly and releases at exactly the half way point.
                 animateToolbarButtonVisibility(true);
             }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
index 13ebc38f8..024d116 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
@@ -45,7 +45,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
index b89923c..ae6adbd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
@@ -34,7 +34,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
index d5e3226..4276ede 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
@@ -59,7 +59,7 @@
                 "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", "US",
                 "650-253-0000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa, profile1,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card, profile1,
                 "" /* serverId */));
         String profile2 = helper.setProfile(new AutofillProfile("", "https://example.com", true,
                 "Rob Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", "US",
@@ -94,7 +94,7 @@
 
         // This card has no billing address selected.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jane Doe",
-                "4242424242424242", "1111", "12", "2050", "visa", R.drawable.pr_visa, profile6,
+                "4242424242424242", "1111", "12", "2050", "visa", R.drawable.visa_card, profile6,
                 "" /* serverId */));
 
         // Assign use stats so that incomplete profiles have the highest frecency, profile2 has the
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
index 1352ed3c..ad4c946 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
@@ -60,7 +60,7 @@
                 "https://example.com", true, "Jon NoPhone", "Google", "340 Main St", "CA",
                 "Los Angeles", "", "90291", "", "US", "", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 address_without_phone, "" /* serverId */));
         String address_with_phone = helper.setProfile(new AutofillProfile("", "https://example.com",
                 true, "Rob Phone", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
index 3b3b6c7..362acde 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
@@ -49,7 +49,7 @@
         // canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "" /* nameOnCard */, "4111111111111111", "1111", "12", "2050", "visa",
-                R.drawable.pr_visa, "" /* billingAddressId */, "" /* serverId */));
+                R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
index c5e22816..139c647 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
@@ -48,7 +48,7 @@
         // The user has a valid credit card without a billing address on file. This is sufficient
         // for canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
-                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 "" /* billingAddressId */, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
index d8b71c3..65adf11 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
@@ -53,7 +53,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "1", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "1", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
index ba4bd4e..2188897b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
@@ -44,7 +44,7 @@
         // canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "" /* nameOnCard */, "4111111111111111", "1111", "12", "2050", "visa",
-                R.drawable.pr_visa, "" /* billingAddressId */, "" /* serverId */));
+                R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
index c52f299..9e98dbe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
@@ -30,7 +30,7 @@
         // The user has a valid credit card without a billing address on file. This is sufficient
         // for canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
-                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 "" /* billingAddressId */, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
index 98b2821..0e95190a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -51,7 +51,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
index 539f284..e768058 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -52,7 +52,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
index d53e2fc..24e21c71 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -50,7 +50,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
index 1877d7f..665ae83 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
@@ -54,7 +54,7 @@
                 "US", "555-555-5555", "", "en-US"));
         // Create an expired credit card
         mCreditCardId = mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true,
-                "Jon Doe", "4111111111111111", "1111", "1", "2016", "visa", R.drawable.pr_visa,
+                "Jon Doe", "4111111111111111", "1111", "1", "2016", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
index 3ea9de7d..8fbf9afe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
@@ -47,7 +47,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
index d879f73..b206d0e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
@@ -46,7 +46,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
index 3fd3d47..7b1892d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -51,7 +51,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
index 4e0192e9..330687e4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
@@ -47,7 +47,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
index 703de2e..9b48730a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
@@ -49,7 +49,7 @@
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         helper.addServerCreditCard(new CreditCard("", "https://example.com", false /* isLocal */,
                 true /* isCached */, "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa",
-                R.drawable.pr_visa, "" /* billing address */, "" /* serverId */));
+                R.drawable.visa_card, "" /* billing address */, "" /* serverId */));
     }
 
     /** Click [PAY] and dismiss the card unmask dialog. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
index 6172c6c..7bce4839 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -52,14 +52,14 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 mBillingAddressId, "" /* serverId */));
         // The user also has an incomplete address and an incomplete card saved.
         String mIncompleteAddressId = mHelper.setProfile(new AutofillProfile("",
                 "https://example.com", true, "In Complete", "Google", "344 Main St", "CA", "", "",
                 "90291", "", "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "",
-                "4111111111111111", "1111", "18", "2075", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "18", "2075", "visa", R.drawable.visa_card,
                 mIncompleteAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
index e4d72a6..d7a9fb9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -58,7 +58,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 mBillingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
index 7917fba5..068ed39 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -50,7 +50,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
index e653ece..e9a58e5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -49,7 +49,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
 
         // Add the same profile but with a different address.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
index 486cd42f..4324a007 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -55,7 +55,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "650-253-0000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
index 9e0b35a..67d311f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
@@ -53,12 +53,12 @@
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         // Mastercard card without a billing address.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "5454545454545454", "", "12", "2050", "mastercard", R.drawable.pr_mc,
+                "5454545454545454", "", "12", "2050", "mastercard", R.drawable.mc_card,
                 "" /* billingAddressId */, "" /* serverId */));
         // Visa card with complete set of information.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "", "12", "2050", "visa", R.drawable.pr_visa, billingAddressId,
-                "" /* serverId */));
+                "4111111111111111", "", "12", "2050", "visa", R.drawable.visa_card,
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
index 86a7bff..d969128 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
@@ -55,8 +55,8 @@
         // Visa card with complete set of information. This payment method is always listed
         // behind non-autofill payment instruments in payment request.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "", "12", "2050", "visa", R.drawable.pr_visa, billingAddressId,
-                "" /* serverId */));
+                "4111111111111111", "", "12", "2050", "visa", R.drawable.visa_card,
+                billingAddressId, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
index bd46925..fc11573 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -50,7 +50,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
index d7bf7f5..4f35fb7a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
@@ -53,7 +53,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Alice",
-                "4111111111111111", "1111", "1", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "1", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
         helper.deleteProfile(billingAddressId);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
index 5ac47af..44ee6d60 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
@@ -47,7 +47,7 @@
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         helper.addServerCreditCard(new CreditCard("4754d21d-8773-40b6-b4be-5f7486be834f",
                 "https://example.com", false /* isLocal */, true /* isCached */, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
index e99e614..fcd116f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
@@ -46,7 +46,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "California", "Los Angeles", "", "90291",
                 "", "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
index 396761ca..00f2979 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressTest.java
@@ -47,7 +47,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 firstAddressId, "" /* serverId */));
 
         // The user has a second address.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index c1470c1..509b0bb2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -47,7 +47,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
index 6e292dd..1ff76c0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
@@ -53,7 +53,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 billingAddressId, "" /* serverId */));
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
index f23aff8..4991fc1a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
@@ -53,7 +53,7 @@
                 true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "555-555-5555", "", "en-US"));
         mCreditCardId = mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true,
-                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa,
+                "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
                 mBillingAddressId, "" /* serverId */));
         // Set specific use stats for the profile and credit card.
         mHelper.setProfileUseStatsForTesting(mBillingAddressId, 20, 5000);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
index 18d612d..6d20856 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
@@ -7,8 +7,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.util.Base64;
+
+import com.google.protobuf.nano.MessageNano;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.annotation.Config;
@@ -50,8 +55,11 @@
                     .setLocationAreaCode(11)
                     .setMobileCountryCode(12)
                     .setMobileNetworkCode(13);
-    private static final VisibleCell VISIBLE_CELL1 =
-            sVisibleCellCommunBuilder.setTimestamp(10L).build();
+    private static final VisibleCell VISIBLE_CELL1 = sVisibleCellCommunBuilder.setPhysicalCellId(14)
+                                                             .setPrimaryScramblingCode(15)
+                                                             .setTrackingAreaCode(16)
+                                                             .setTimestamp(10L)
+                                                             .build();
     private static final VisibleCell VISIBLE_CELL1_DIFFERENT_TIMESTAMP =
             sVisibleCellCommunBuilder.setTimestamp(20L).build();
     private static final VisibleCell VISIBLE_CELL2 = VisibleCell.builder(VisibleCell.GSM_RADIO_TYPE)
@@ -61,6 +69,10 @@
                                                              .setMobileNetworkCode(33)
                                                              .setTimestamp(30L)
                                                              .build();
+    private static final VisibleCell EMPTY_CELL =
+            VisibleCell.builder(VisibleCell.UNKNOWN_RADIO_TYPE).build();
+    private static final VisibleWifi EMPTY_WIFI = VisibleWifi.create(null, null, null, null);
+
     private static Set<VisibleCell> sAllVisibleCells =
             new HashSet<VisibleCell>(Arrays.asList(VISIBLE_CELL1, VISIBLE_CELL2));
     private static Set<VisibleCell> sAllVisibleCells2 = new HashSet<VisibleCell>(
@@ -74,6 +86,13 @@
     private static final VisibleNetworks VISIBLE_NETWORKS2 = VisibleNetworks.create(
             VISIBLE_WIFI2, VISIBLE_CELL2, sAllVisibleWifis, sAllVisibleCells2);
 
+    private static final String VISIBLE_CELL1_PROTO_ENCODED =
+            "CAEQDLoBFhIQCAEQChgLIAwoDTAPOA5AEBgBIAo=";
+    private static final String VISIBLE_WIFI1_PROTO_ENCODED =
+            "CAEQDLoBJAoeChExMToxMToxMToxMToxMToxMRD___________8BGAEgCg==";
+    private static final String EMPTY_CELL_PROTO_ENCODED = "CAEQDLoBBhICCAAYAQ==";
+    private static final String EMPTY_WIFI_PROTO_ENCODED = "CAEQDLoBBAoAGAE=";
+
     @Test
     public void testVisibleWifiCreate() {
         VisibleWifi visibleWifi = VisibleWifi.create(SSID1, BSSID1, LEVEL1, TIMESTAMP1);
@@ -119,6 +138,34 @@
     }
 
     @Test
+    public void testVisibleWifiToProto() {
+        boolean connected = true;
+        PartnerLocationDescriptor.VisibleNetwork visibleNetwork = VISIBLE_WIFI1.toProto(connected);
+        PartnerLocationDescriptor.VisibleNetwork.WiFi wifi = visibleNetwork.wifi;
+
+        assertEquals(VISIBLE_WIFI1.bssid(), wifi.bssid);
+        assertEquals(VISIBLE_WIFI1.level(), wifi.levelDbm);
+        assertEquals(VISIBLE_WIFI1.timestampMs(), visibleNetwork.timestampMs);
+        assertEquals(connected, visibleNetwork.connected);
+
+        assertEquals(VISIBLE_WIFI1_PROTO_ENCODED, encodeVisibleNetwork(visibleNetwork));
+    }
+
+    @Test
+    public void testVisibleWifiToProtoEmptyWifi() {
+        boolean connected = true;
+        PartnerLocationDescriptor.VisibleNetwork visibleNetwork = EMPTY_WIFI.toProto(connected);
+        PartnerLocationDescriptor.VisibleNetwork.WiFi wifi = visibleNetwork.wifi;
+
+        assertNull(wifi.bssid);
+        assertNull(wifi.levelDbm);
+        assertNull(visibleNetwork.timestampMs);
+        assertEquals(connected, visibleNetwork.connected);
+
+        assertEquals(EMPTY_WIFI_PROTO_ENCODED, encodeVisibleNetwork(visibleNetwork));
+    }
+
+    @Test
     public void testVisibleCellBuilder() {
         for (@RadioType int radioType : RADIO_TYPES) {
             VisibleCell visibleCell = VisibleCell.builder(radioType).build();
@@ -134,6 +181,9 @@
                         .setLocationAreaCode(VISIBLE_CELL1.locationAreaCode())
                         .setMobileCountryCode(VISIBLE_CELL1.mobileCountryCode())
                         .setMobileNetworkCode(VISIBLE_CELL1.mobileNetworkCode())
+                        .setPhysicalCellId(VISIBLE_CELL1.physicalCellId())
+                        .setPrimaryScramblingCode(VISIBLE_CELL1.primaryScramblingCode())
+                        .setTrackingAreaCode(VISIBLE_CELL1.trackingAreaCode())
                         .setTimestamp(VISIBLE_CELL1.timestampMs())
                         .build();
         assertNotEquals(VISIBLE_CELL2, VISIBLE_CELL1);
@@ -154,6 +204,9 @@
                         .setLocationAreaCode(VISIBLE_CELL1.locationAreaCode())
                         .setMobileCountryCode(VISIBLE_CELL1.mobileCountryCode())
                         .setMobileNetworkCode(VISIBLE_CELL1.mobileNetworkCode())
+                        .setPhysicalCellId(VISIBLE_CELL1.physicalCellId())
+                        .setPrimaryScramblingCode(VISIBLE_CELL1.primaryScramblingCode())
+                        .setTrackingAreaCode(VISIBLE_CELL1.trackingAreaCode())
                         .setTimestamp(VISIBLE_CELL1.timestampMs())
                         .build();
 
@@ -168,6 +221,46 @@
     }
 
     @Test
+    public void testVisibleCellToProto() {
+        boolean connected = true;
+        PartnerLocationDescriptor.VisibleNetwork visibleNetwork = VISIBLE_CELL1.toProto(connected);
+        PartnerLocationDescriptor.VisibleNetwork.Cell cell = visibleNetwork.cell;
+
+        assertEquals(VISIBLE_CELL1.cellId(), cell.cellId);
+        assertEquals(VISIBLE_CELL1.locationAreaCode(), cell.locationAreaCode);
+        assertEquals(VISIBLE_CELL1.mobileCountryCode(), cell.mobileCountryCode);
+        assertEquals(VISIBLE_CELL1.mobileNetworkCode(), cell.mobileNetworkCode);
+        assertEquals(VISIBLE_CELL1.primaryScramblingCode(), cell.primaryScramblingCode);
+        assertEquals(VISIBLE_CELL1.physicalCellId(), cell.physicalCellId);
+        assertEquals(VISIBLE_CELL1.trackingAreaCode(), cell.trackingAreaCode);
+        assertEquals(VISIBLE_CELL1.timestampMs(), visibleNetwork.timestampMs);
+        assertEquals(connected, visibleNetwork.connected);
+        assertEquals(PartnerLocationDescriptor.VisibleNetwork.Cell.GSM, cell.type.intValue());
+
+        assertEquals(VISIBLE_CELL1_PROTO_ENCODED, encodeVisibleNetwork(visibleNetwork));
+    }
+
+    @Test
+    public void testVisibleCellToProtoEmptyCell() {
+        boolean connected = true;
+        PartnerLocationDescriptor.VisibleNetwork visibleNetwork = EMPTY_CELL.toProto(connected);
+        PartnerLocationDescriptor.VisibleNetwork.Cell cell = visibleNetwork.cell;
+
+        assertEquals(VisibleCell.UNKNOWN_RADIO_TYPE, cell.type.intValue());
+        assertNull(cell.cellId);
+        assertNull(cell.locationAreaCode);
+        assertNull(cell.mobileCountryCode);
+        assertNull(cell.mobileNetworkCode);
+        assertNull(cell.primaryScramblingCode);
+        assertNull(cell.physicalCellId);
+        assertNull(cell.trackingAreaCode);
+        assertNull(visibleNetwork.timestampMs);
+        assertEquals(connected, visibleNetwork.connected);
+
+        assertEquals(EMPTY_CELL_PROTO_ENCODED, encodeVisibleNetwork(visibleNetwork));
+    }
+
+    @Test
     public void testVisibleNetworksCreate() {
         Set<VisibleCell> expectedVisibleCells =
                 new HashSet<VisibleCell>(Arrays.asList(VISIBLE_CELL1, VISIBLE_CELL2));
@@ -207,4 +300,17 @@
         assertTrue(visibleNetworks.isEmpty());
         assertFalse(VISIBLE_NETWORKS1.isEmpty());
     }
-}
\ No newline at end of file
+
+    private static String encodeVisibleNetwork(
+            PartnerLocationDescriptor.VisibleNetwork visibleNetwork) {
+        PartnerLocationDescriptor.LocationDescriptor locationDescriptor =
+                new PartnerLocationDescriptor.LocationDescriptor();
+        locationDescriptor.role = PartnerLocationDescriptor.CURRENT_LOCATION;
+        locationDescriptor.producer = PartnerLocationDescriptor.DEVICE_LOCATION;
+        locationDescriptor.visibleNetwork = new PartnerLocationDescriptor.VisibleNetwork[1];
+        locationDescriptor.visibleNetwork[0] = visibleNetwork;
+
+        return Base64.encodeToString(
+                MessageNano.toByteArray(locationDescriptor), Base64.NO_WRAP | Base64.URL_SAFE);
+    }
+}
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index e355c095..7b0a881b 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -66,10 +66,10 @@
 // We use Android's |VectorDrawableCompat| for the following images that are
 // displayed using |DropdownAdapter|.
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_AMEX, R.drawable.amex_card)
-LINK_RESOURCE_ID(IDR_AUTOFILL_CC_DINERS, R.drawable.ic_credit_card_black)
+LINK_RESOURCE_ID(IDR_AUTOFILL_CC_DINERS, R.drawable.diners_card)
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_DISCOVER, R.drawable.discover_card)
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_GENERIC, R.drawable.ic_credit_card_black)
-LINK_RESOURCE_ID(IDR_AUTOFILL_CC_JCB, R.drawable.ic_credit_card_black)
+LINK_RESOURCE_ID(IDR_AUTOFILL_CC_JCB, R.drawable.jcb_card)
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_MASTERCARD, R.drawable.mc_card)
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_MIR, R.drawable.mir_card)
 LINK_RESOURCE_ID(IDR_AUTOFILL_CC_UNIONPAY, R.drawable.unionpay_card)
@@ -86,14 +86,3 @@
 // We use PNG files for the following images.
 LINK_RESOURCE_ID(IDR_CREDIT_CARD_CVC_HINT, R.drawable.cvc_icon)
 LINK_RESOURCE_ID(IDR_CREDIT_CARD_CVC_HINT_AMEX, R.drawable.cvc_icon_amex)
-
-// PaymentRequest images.
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_AMEX, R.drawable.pr_amex)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_DINERS, R.drawable.pr_dinersclub)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_DISCOVER, R.drawable.pr_discover)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_GENERIC, R.drawable.pr_generic)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_JCB, R.drawable.pr_jcb)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_MASTERCARD, R.drawable.pr_mc)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_MIR, R.drawable.pr_mir)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_UNIONPAY, R.drawable.pr_unionpay)
-LINK_RESOURCE_ID(IDR_AUTOFILL_PR_VISA, R.drawable.pr_visa)
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
index af66f76..75fd783 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_data_delegate.h"
@@ -78,18 +77,14 @@
             const base::FilePath& crx_file)
       : client_(client),
         crx_file_(crx_file),
-        success_(false) {
-  }
+        success_(false),
+        task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+            {base::MayBlock(), base::TaskPriority::BACKGROUND,
+             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
   void Start() {
-    base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
-    base::SequencedWorkerPool::SequenceToken token =
-        pool->GetNamedSequenceToken("KioskAppData.CrxLoaderWorker");
-    task_runner_ = pool->GetSequencedTaskRunnerWithShutdownBehavior(
-        token,
-        base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
     task_runner_->PostTask(FROM_HERE,
-                           base::Bind(&CrxLoader::StartOnBlockingPool, this));
+                           base::BindOnce(&CrxLoader::StartInThreadPool, this));
   }
 
   bool success() const { return success_; }
@@ -122,21 +117,21 @@
       icon_ = install_icon;
       required_platform_version_ = info->required_platform_version;
     }
-    NotifyFinishedOnBlockingPool();
+    NotifyFinishedInThreadPool();
   }
   void OnUnpackFailure(const extensions::CrxInstallError& error) override {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     success_ = false;
-    NotifyFinishedOnBlockingPool();
+    NotifyFinishedInThreadPool();
   }
 
-  void StartOnBlockingPool() {
+  void StartInThreadPool() {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     if (!temp_dir_.CreateUniqueTempDir()) {
       success_ = false;
-      NotifyFinishedOnBlockingPool();
+      NotifyFinishedInThreadPool();
       return;
     }
 
@@ -147,7 +142,7 @@
     unpacker->StartWithCrx(extensions::CRXFileInfo(crx_file_));
   }
 
-  void NotifyFinishedOnBlockingPool() {
+  void NotifyFinishedInThreadPool() {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     if (!temp_dir_.Delete()) {
@@ -171,7 +166,7 @@
   base::FilePath crx_file_;
   bool success_;
 
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   base::ScopedTempDir temp_dir_;
 
   // Extracted meta data.
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index e78cf457..435157d 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -18,6 +18,7 @@
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/linux_util.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
@@ -112,6 +113,7 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
+#include "chromeos/dbus/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_policy_controller.h"
 #include "chromeos/dbus/services/console_service_provider.h"
@@ -409,6 +411,42 @@
 
   // Entry point, called on UI thread.
   void Initialize() {
+    // Only start loading the system token once cryptohome is available and only
+    // if the TPM is ready (available && owned && not being owned).
+    DBusThreadManager::Get()
+        ->GetCryptohomeClient()
+        ->WaitForServiceToBeAvailable(
+            base::Bind(&SystemTokenCertDBInitializer::OnCryptohomeAvailable,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+ private:
+  // Called once the cryptohome service is available.
+  void OnCryptohomeAvailable(bool available) {
+    if (!available) {
+      LOG(ERROR) << "SystemTokenCertDBInitializer: Failed to wait for "
+                    "cryptohome to become available.";
+      return;
+    }
+
+    VLOG(1) << "SystemTokenCertDBInitializer: Cryptohome available.";
+    DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsReady(
+        base::Bind(&SystemTokenCertDBInitializer::OnGotTpmIsReady,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  // This is a callback for the cryptohome TpmIsReady query. Note that this is
+  // not a listener which would be called once TPM becomes ready if it was not
+  // ready on startup (e.g. after device enrollment), see crbug.com/725500.
+  void OnGotTpmIsReady(DBusMethodCallStatus call_status, bool tpm_is_ready) {
+    if (!tpm_is_ready) {
+      VLOG(1) << "SystemTokenCertDBInitializer: TPM is not ready - not loading "
+                 "system token.";
+      return;
+    }
+    VLOG(1)
+        << "SystemTokenCertDBInitializer: TPM is ready, loading system token.";
+    TPMTokenLoader::Get()->EnsureStarted();
     base::Callback<void(crypto::ScopedPK11Slot)> callback =
         base::BindRepeating(&SystemTokenCertDBInitializer::InitializeDatabase,
                             weak_ptr_factory_.GetWeakPtr());
@@ -417,7 +455,6 @@
         base::BindOnce(&GetSystemSlotOnIOThread, callback));
   }
 
- private:
   // Initializes the global system token NSSCertDatabase with |system_slot|.
   // Also starts CertLoader with the system token database.
   void InitializeDatabase(crypto::ScopedPK11Slot system_slot) {
@@ -434,6 +471,8 @@
     database->SetSystemSlot(std::move(system_slot_copy));
     system_token_cert_database_ = std::move(database);
 
+    VLOG(1) << "SystemTokenCertDBInitializer: Passing system token NSS "
+               "database to CertLoader.";
     CertLoader::Get()->SetSystemNSSDB(system_token_cert_database_.get());
   }
 
@@ -541,7 +580,6 @@
           content::BrowserThread::IO));
 
   // Initialize NSS database for system token.
-  TPMTokenLoader::Get()->EnsureStarted();
   system_token_certdb_initializer_ =
       base::MakeUnique<internal::SystemTokenCertDBInitializer>();
   system_token_certdb_initializer_->Initialize();
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc
index 468f503..4be75ca 100644
--- a/chrome/browser/chromeos/drive/download_handler.cc
+++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -6,6 +6,8 @@
 
 #include <stddef.h>
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
@@ -104,10 +106,10 @@
 
 // Used to implement CheckForFileExistence().
 void ContinueCheckingForFileExistence(
-    const content::CheckForFileExistenceCallback& callback,
+    content::CheckForFileExistenceCallback callback,
     FileError error,
     std::unique_ptr<ResourceEntry> entry) {
-  callback.Run(error == FILE_ERROR_OK);
+  std::move(callback).Run(error == FILE_ERROR_OK);
 }
 
 // Returns true if |download| is a Drive download created from data persisted
@@ -247,11 +249,11 @@
 
 void DownloadHandler::CheckForFileExistence(
     const DownloadItem* download,
-    const content::CheckForFileExistenceCallback& callback) {
+    content::CheckForFileExistenceCallback callback) {
   file_system_->GetResourceEntry(
       util::ExtractDrivePath(GetTargetPath(download)),
       base::Bind(&ContinueCheckingForFileExistence,
-                 callback));
+                 base::Passed(std::move(callback))));
 }
 
 void DownloadHandler::SetFreeDiskSpaceDelayForTesting(
diff --git a/chrome/browser/chromeos/drive/download_handler.h b/chrome/browser/chromeos/drive/download_handler.h
index d42b845..1cff079 100644
--- a/chrome/browser/chromeos/drive/download_handler.h
+++ b/chrome/browser/chromeos/drive/download_handler.h
@@ -71,9 +71,8 @@
   bool IsDriveDownload(const content::DownloadItem* download);
 
   // Checks a file corresponding to the download item exists in Drive.
-  void CheckForFileExistence(
-      const content::DownloadItem* download,
-      const content::CheckForFileExistenceCallback& callback);
+  void CheckForFileExistence(const content::DownloadItem* download,
+                             content::CheckForFileExistenceCallback callback);
 
   // Calculates request space for |downloads|.
   int64_t CalculateRequestSpace(
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index deae260..16e2bff 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -252,8 +252,8 @@
 }
 #endif
 
-// Callback to GetNSSCertDatabaseForProfile. It starts CertLoader using the
-// provided NSS database. It must be called for primary user only.
+// Callback to GetNSSCertDatabaseForProfile. It passes the user-specific NSS
+// database to CertLoader. It must be called for primary user only.
 void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) {
   if (!CertLoader::IsInitialized())
     return;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 37c55d6..3ecbff8 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -17,7 +18,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -212,8 +212,11 @@
     : profile_(profile),
       next_download_id_(content::DownloadItem::kInvalidId),
       download_prefs_(new DownloadPrefs(profile)),
-      weak_ptr_factory_(this) {
-}
+      check_for_file_existence_task_runner_(
+          base::CreateSequencedTaskRunnerWithTraits(
+              {base::MayBlock(), base::TaskPriority::BACKGROUND,
+               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
+      weak_ptr_factory_(this) {}
 
 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() {
   // If a DownloadManager was set for this, Shutdown() must be called.
@@ -533,29 +536,28 @@
   platform_util::ShowItemInFolder(profile_, platform_path);
 }
 
+void ContinueCheckingForFileExistence(
+    content::CheckForFileExistenceCallback callback) {
+  std::move(callback).Run(false);
+}
+
 void ChromeDownloadManagerDelegate::CheckForFileExistence(
     DownloadItem* download,
-    const content::CheckForFileExistenceCallback& callback) {
+    content::CheckForFileExistenceCallback callback) {
 #if defined(OS_CHROMEOS)
   drive::DownloadHandler* drive_download_handler =
       drive::DownloadHandler::GetForProfile(profile_);
   if (drive_download_handler &&
       drive_download_handler->IsDriveDownload(download)) {
-    drive_download_handler->CheckForFileExistence(download, callback);
+    drive_download_handler->CheckForFileExistence(download,
+                                                  std::move(callback));
     return;
   }
 #endif
-  static const char kSequenceToken[] = "ChromeDMD-FileExistenceChecker";
-  base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
-  scoped_refptr<base::SequencedTaskRunner> task_runner =
-      worker_pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          worker_pool->GetNamedSequenceToken(kSequenceToken),
-          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
   base::PostTaskAndReplyWithResult(
-      task_runner.get(),
-      FROM_HERE,
-      base::Bind(&base::PathExists, download->GetTargetFilePath()),
-      callback);
+      check_for_file_existence_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&base::PathExists, download->GetTargetFilePath()),
+      std::move(callback));
 }
 
 std::string
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index a03a227c..5d9fd8a8 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -16,6 +16,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
 #include "chrome/browser/download/download_path_reservation_tracker.h"
 #include "chrome/browser/download/download_target_determiner_delegate.h"
 #include "chrome/browser/download/download_target_info.h"
@@ -85,7 +86,7 @@
   void ShowDownloadInShell(content::DownloadItem* download) override;
   void CheckForFileExistence(
       content::DownloadItem* download,
-      const content::CheckForFileExistenceCallback& callback) override;
+      content::CheckForFileExistenceCallback callback) override;
   std::string ApplicationClientIdForFileScanning() const override;
 
   // Opens a download using the platform handler. DownloadItem::OpenDownload,
@@ -168,6 +169,12 @@
   IdCallbackVector id_callbacks_;
   std::unique_ptr<DownloadPrefs> download_prefs_;
 
+  // SequencedTaskRunner to check for file existence. A sequence is used so that
+  // a large download history doesn't cause a large number of concurrent disk
+  // operations.
+  const scoped_refptr<base::SequencedTaskRunner>
+      check_for_file_existence_task_runner_;
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   // Maps from pending extension installations to DownloadItem IDs.
   typedef base::hash_map<extensions::CrxInstaller*,
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index 672f7c8..e67ba97 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -156,7 +156,6 @@
   test_config_.reset(new base::DictionaryValue());
   test_config_->SetString(kTestDataDirectory,
                           net::FilePathToFileURL(test_data_dir_).spec());
-  test_config_->SetInteger(kTestWebSocketPort, 0);
   extensions::TestGetConfigFunction::set_test_config_state(
       test_config_.get());
 }
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 6c04bc1..6686bd3c 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -546,6 +546,42 @@
   return true;
 }
 
+bool ChromeNetworkDelegate::OnCanQueueReportingReport(
+    const url::Origin& origin) const {
+  if (!cookie_settings_)
+    return true;
+
+  return cookie_settings_->IsCookieAccessAllowed(origin.GetURL(),
+                                                 origin.GetURL());
+}
+
+bool ChromeNetworkDelegate::OnCanSendReportingReport(
+    const url::Origin& origin) const {
+  if (!cookie_settings_)
+    return true;
+
+  return cookie_settings_->IsCookieAccessAllowed(origin.GetURL(),
+                                                 origin.GetURL());
+}
+
+bool ChromeNetworkDelegate::OnCanSetReportingClient(
+    const url::Origin& origin,
+    const GURL& endpoint) const {
+  if (!cookie_settings_)
+    return true;
+
+  return cookie_settings_->IsCookieAccessAllowed(endpoint, origin.GetURL());
+}
+
+bool ChromeNetworkDelegate::OnCanUseReportingClient(
+    const url::Origin& origin,
+    const GURL& endpoint) const {
+  if (!cookie_settings_)
+    return true;
+
+  return cookie_settings_->IsCookieAccessAllowed(endpoint, origin.GetURL());
+}
+
 void ChromeNetworkDelegate::ReportDataUsageStats(net::URLRequest* request,
                                                  int64_t tx_bytes,
                                                  int64_t rx_bytes) {
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h
index fc0d59a..d4e94a9e 100644
--- a/chrome/browser/net/chrome_network_delegate.h
+++ b/chrome/browser/net/chrome_network_delegate.h
@@ -182,6 +182,12 @@
       const net::URLRequest& request,
       const GURL& target_url,
       const GURL& referrer_url) const override;
+  bool OnCanQueueReportingReport(const url::Origin& origin) const override;
+  bool OnCanSendReportingReport(const url::Origin& origin) const override;
+  bool OnCanSetReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const override;
+  bool OnCanUseReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const override;
 
   // Convenience function for reporting network usage to the
   // |data_use_aggregator_|.
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 6d029c4..30c0dd4 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -165,10 +165,9 @@
 #endif  // OS_ANDROID
 
 void RegisterBookmarkProvider(BookmarkModel* bookmark_model,
-                              ContentSuggestionsService* service,
-                              PrefService* pref_service) {
-  auto provider = base::MakeUnique<BookmarkSuggestionsProvider>(
-      service, bookmark_model, pref_service);
+                              ContentSuggestionsService* service) {
+  auto provider =
+      base::MakeUnique<BookmarkSuggestionsProvider>(service, bookmark_model);
   service->RegisterProvider(std::move(provider));
 }
 
@@ -372,7 +371,7 @@
       BookmarkModelFactory::GetForBrowserContext(profile);
   if (base::FeatureList::IsEnabled(ntp_snippets::kBookmarkSuggestionsFeature) &&
       bookmark_model && !IsChromeHomeEnabled()) {
-    RegisterBookmarkProvider(bookmark_model, service, pref_service);
+    RegisterBookmarkProvider(bookmark_model, service);
   }
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.cc b/chrome/browser/plugins/plugin_infobar_delegates.cc
index 851098c4..6c4d83c 100644
--- a/chrome/browser/plugins/plugin_infobar_delegates.cc
+++ b/chrome/browser/plugins/plugin_infobar_delegates.cc
@@ -53,7 +53,7 @@
   infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
       std::unique_ptr<ConfirmInfoBarDelegate>(new OutdatedPluginInfoBarDelegate(
           installer, std::move(plugin_metadata),
-          l10n_util::GetStringUTF16(IDS_PLUGIN_OUTDATED_PROMPT)))));
+          l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED_PROMPT, name)))));
 }
 
 OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index e1090ec7..09ecf6da 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -79,7 +79,6 @@
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #include "components/metrics/metrics_service.h"
 #include "components/network_time/network_time_tracker.h"
-#include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
 #include "components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h"
@@ -491,7 +490,6 @@
   MediaStreamDevicesController::RegisterProfilePrefs(registry);
   NetHttpSessionParamsObserver::RegisterProfilePrefs(registry);
   NotifierStateTracker::RegisterProfilePrefs(registry);
-  ntp_snippets::BookmarkSuggestionsProvider::RegisterProfilePrefs(registry);
   ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
   ntp_snippets::ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
       registry);
diff --git a/chrome/browser/safe_browsing/OWNERS b/chrome/browser/safe_browsing/OWNERS
index 104ba73..442ab174 100644
--- a/chrome/browser/safe_browsing/OWNERS
+++ b/chrome/browser/safe_browsing/OWNERS
@@ -1,5 +1,6 @@
 mattm@chromium.org
 nparker@chromium.org
-
-# For download-protection- and reporting-related changes:
 jialiul@chromium.org
+
+# For interstitial-related changes:
+per-file safe_browsing_blocking_page*=felt@chromium.org
diff --git a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
index 8a08f9a4c6..ac449ba 100644
--- a/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/contact_info_editor_view_controller.cc
@@ -16,6 +16,7 @@
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/content/payment_request_state.h"
+#include "components/payments/core/payment_request_data_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_combobox_model.h"
@@ -69,6 +70,11 @@
   if (!profile_to_edit_)
     return base::string16();
 
+  if (type == autofill::PHONE_HOME_WHOLE_NUMBER) {
+    return data_util::GetFormattedPhoneNumberForDisplay(
+        *profile_to_edit_, state()->GetApplicationLocale());
+  }
+
   return profile_to_edit_->GetInfo(autofill::AutofillType(type),
                                    state()->GetApplicationLocale());
 }
diff --git a/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
index 3738f155..ca1ddb2 100644
--- a/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/contact_info_editor_view_controller_browsertest.cc
@@ -237,8 +237,9 @@
   OpenContactInfoScreen();
 
   PaymentRequest* request = GetPaymentRequests(GetActiveWebContents()).front();
-  EXPECT_EQ(request->state()->contact_profiles().front(),
-            request->state()->selected_contact_profile());
+
+  // No contact profiles are selected because both are incomplete.
+  EXPECT_EQ(nullptr, request->state()->selected_contact_profile());
 
   views::View* list_view = dialog_view()->GetViewByID(
       static_cast<int>(DialogViewID::CONTACT_INFO_SHEET_LIST_VIEW));
@@ -269,6 +270,7 @@
             profile->GetInfo(autofill::AutofillType(autofill::EMAIL_ADDRESS),
                              GetLocale()));
 
+  // Expect the newly-completed profile to be selected.
   EXPECT_EQ(2U, request->state()->contact_profiles().size());
   EXPECT_EQ(request->state()->contact_profiles().back(), profile);
 }
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/order_summary_view_controller_browsertest.cc
index 77d3fded..7eec7b6 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller_browsertest.cc
@@ -71,7 +71,7 @@
   EXPECT_EQ(
       base::ASCIIToUTF16("ACME, 123 Main Street, Unit 1, Greensdale, MI 48838"),
       shipping_address_labels[1]);
-  EXPECT_EQ(base::ASCIIToUTF16("13105557889"), shipping_address_labels[2]);
+  EXPECT_EQ(base::ASCIIToUTF16("+1 310-555-7889"), shipping_address_labels[2]);
   std::vector<base::string16> shipping_option_labels =
       GetShippingOptionLabelValues(
           DialogViewID::PAYMENT_SHEET_SHIPPING_OPTION_SECTION);
@@ -113,7 +113,7 @@
   EXPECT_EQ(base::ASCIIToUTF16(
                 "Underworld, 666 Erebus St., Apt 8, Elysium, CA 91111"),
             shipping_address_labels[1]);
-  EXPECT_EQ(base::ASCIIToUTF16("16502111111"), shipping_address_labels[2]);
+  EXPECT_EQ(base::ASCIIToUTF16("+1 650-211-1111"), shipping_address_labels[2]);
   shipping_option_labels = GetShippingOptionLabelValues(
       DialogViewID::PAYMENT_SHEET_SHIPPING_OPTION_SECTION);
   EXPECT_EQ(base::ASCIIToUTF16("Free shipping in California"),
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc
index 9d87756d..cc45006 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -20,6 +20,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/payments/core/payment_options_provider.h"
+#include "components/payments/core/payment_request_data_util.h"
 #include "components/payments/core/payments_profile_comparator.h"
 #include "ui/base/default_style.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -132,8 +133,8 @@
 
   base::string16 address = GetAddressFromProfile(profile, locale);
 
-  base::string16 phone = profile.GetInfo(
-      autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), locale);
+  base::string16 phone =
+      data_util::GetFormattedPhoneNumberForDisplay(profile, locale);
 
   return GetBaseProfileLabel(type, name, address, phone, disabled_state);
 }
@@ -200,16 +201,16 @@
 
   views::ColumnSet* columns = layout->AddColumnSet(0);
   // A column for the optional back arrow.
-  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
-                     0, views::GridLayout::USE_PREF, 0, 0);
+  columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
+                     views::GridLayout::USE_PREF, 0, 0);
 
   constexpr int kPaddingBetweenArrowAndTitle = 16;
   if (show_back_arrow)
     columns->AddPaddingColumn(0, kPaddingBetweenArrowAndTitle);
 
   // A column for the title.
-  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
-                     1, views::GridLayout::USE_PREF, 0, 0);
+  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1,
+                     views::GridLayout::USE_PREF, 0, 0);
 
   layout->StartRow(0, 0);
   if (!show_back_arrow) {
@@ -220,8 +221,8 @@
     constexpr int kBackArrowSize = 16;
     back_arrow->SetSize(gfx::Size(kBackArrowSize, kBackArrowSize));
     back_arrow->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
-    back_arrow->set_tag(static_cast<int>(
-        PaymentRequestCommonTags::BACK_BUTTON_TAG));
+    back_arrow->set_tag(
+        static_cast<int>(PaymentRequestCommonTags::BACK_BUTTON_TAG));
     back_arrow->set_id(static_cast<int>(DialogViewID::BACK_BUTTON));
     layout->AddView(back_arrow);
   }
@@ -320,9 +321,7 @@
 
   base::string16 phone =
       options.request_payer_phone()
-          ? profile.GetInfo(
-                autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
-                locale)
+          ? data_util::GetFormattedPhoneNumberForDisplay(profile, locale)
           : base::string16();
 
   base::string16 email =
diff --git a/chrome/browser/ui/views/payments/profile_list_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/profile_list_view_controller_browsertest.cc
new file mode 100644
index 0000000..319443f
--- /dev/null
+++ b/chrome/browser/ui/views/payments/profile_list_view_controller_browsertest.cc
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/guid.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h"
+#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "ui/views/controls/label.h"
+
+namespace payments {
+
+autofill::AutofillProfile CreateProfileWithPartialAddress() {
+  autofill::AutofillProfile profile = autofill::test::GetFullProfile2();
+  profile.SetRawInfo(autofill::ADDRESS_HOME_LINE1, base::ASCIIToUTF16(""));
+  profile.SetRawInfo(autofill::ADDRESS_HOME_LINE2, base::ASCIIToUTF16(""));
+  profile.SetRawInfo(autofill::ADDRESS_HOME_CITY, base::ASCIIToUTF16(""));
+  profile.SetRawInfo(autofill::ADDRESS_HOME_STATE, base::ASCIIToUTF16(""));
+  return profile;
+}
+
+class PaymentRequestProfileListTest : public PaymentRequestBrowserTestBase {
+ protected:
+  PaymentRequestProfileListTest()
+      : PaymentRequestBrowserTestBase(
+            "/payment_request_free_shipping_test.html") {}
+};
+
+IN_PROC_BROWSER_TEST_F(PaymentRequestProfileListTest, PrioritizeCompleteness) {
+  autofill::AutofillProfile complete = autofill::test::GetFullProfile();
+  autofill::AutofillProfile partial = CreateProfileWithPartialAddress();
+  partial.set_use_count(1000);
+
+  AddAutofillProfile(complete);
+  AddAutofillProfile(partial);
+
+  // In the Personal Data Manager, the partial address is more frecent.
+  autofill::PersonalDataManager* personal_data_manager = GetDataManager();
+  std::vector<autofill::AutofillProfile*> profiles =
+      personal_data_manager->GetProfiles();
+  ASSERT_EQ(2UL, profiles.size());
+  EXPECT_EQ(partial, *profiles[0]);
+  EXPECT_EQ(complete, *profiles[1]);
+
+  InvokePaymentRequestUI();
+
+  PaymentRequest* request = GetPaymentRequests(GetActiveWebContents()).front();
+
+  // The complete profile should be selected.
+  ASSERT_TRUE(request->state()->selected_shipping_profile());
+  EXPECT_EQ(complete, *request->state()->selected_shipping_profile());
+
+  // It should appear first in the shipping profiles.
+  ASSERT_EQ(2UL, request->state()->shipping_profiles().size());
+  EXPECT_EQ(complete, *request->state()->shipping_profiles()[0]);
+  EXPECT_EQ(partial, *request->state()->shipping_profiles()[1]);
+
+  // And both should appear in the UI.
+  OpenShippingAddressSectionScreen();
+  views::View* sheet = dialog_view()->GetViewByID(
+      static_cast<int>(DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW));
+  ASSERT_EQ(2, sheet->child_count());
+  views::View* first_label = sheet->child_at(0)->GetViewByID(
+      static_cast<int>(DialogViewID::PROFILE_LABEL_LINE_1));
+  views::View* second_label = sheet->child_at(1)->GetViewByID(
+      static_cast<int>(DialogViewID::PROFILE_LABEL_LINE_1));
+
+  EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"),
+            static_cast<views::Label*>(first_label)->text());
+  EXPECT_EQ(base::ASCIIToUTF16("Jane A. Smith"),
+            static_cast<views::Label*>(second_label)->text());
+}
+
+}  // namespace payments
diff --git a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
index 0d783e3..33d8ee5 100644
--- a/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/shipping_address_editor_view_controller.cc
@@ -25,6 +25,7 @@
 #include "components/autofill/core/browser/validation.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/content/payment_request_state.h"
+#include "components/payments/core/payment_request_data_util.h"
 #include "components/payments/core/payments_profile_comparator.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/libaddressinput/messages.h"
@@ -78,6 +79,11 @@
   if (!profile_to_edit_)
     return base::string16();
 
+  if (type == autofill::PHONE_HOME_WHOLE_NUMBER) {
+    return data_util::GetFormattedPhoneNumberForDisplay(
+        *profile_to_edit_, state()->GetApplicationLocale());
+  }
+
   return profile_to_edit_->GetInfo(autofill::AutofillType(type),
                                    state()->GetApplicationLocale());
 }
diff --git a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
index a4108d9..e1ed5ebe 100644
--- a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
@@ -75,7 +75,7 @@
   EXPECT_EQ(
       base::ASCIIToUTF16("ACME, 123 Main Street, Unit 1, Greensdale, MI 48838"),
       shipping_address_labels[1]);
-  EXPECT_EQ(base::ASCIIToUTF16("13105557889"), shipping_address_labels[2]);
+  EXPECT_EQ(base::ASCIIToUTF16("+1 310-555-7889"), shipping_address_labels[2]);
 
   // The shipping option section exists, and the shipping option is shown.
   std::vector<base::string16> shipping_option_labels =
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 87478f0..53c5a05 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2058,6 +2058,7 @@
         "../browser/ui/views/payments/payment_request_payment_response_browsertest.cc",
         "../browser/ui/views/payments/payment_request_use_stats_browsertest.cc",
         "../browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc",
+        "../browser/ui/views/payments/profile_list_view_controller_browsertest.cc",
         "../browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc",
         "../browser/ui/views/payments/shipping_option_view_controller_browsertest.cc",
         "../browser/ui/views/select_file_dialog_extension_browsertest.cc",
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
index 3bd57a6a..8ba431f 100644
--- a/chrome/test/base/chrome_test_launcher.cc
+++ b/chrome/test/base/chrome_test_launcher.cc
@@ -16,7 +16,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/process/process_metrics.h"
 #include "base/run_loop.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/test/test_file_util.h"
 #include "build/build_config.h"
@@ -30,6 +29,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/test_launcher.h"
 #include "content/public/test/test_utils.h"
+#include "services/service_manager/runner/common/switches.h"
 #include "ui/base/test/ui_controls.h"
 
 #if defined(OS_MACOSX)
@@ -53,7 +53,6 @@
 #endif
 
 #if defined(OS_WIN)
-#include <shellapi.h>
 #include "base/win/registry.h"
 #include "chrome/app/chrome_crash_reporter_client_win.h"
 #include "chrome/install_static/install_util.h"
@@ -63,6 +62,12 @@
 ChromeTestSuiteRunner::~ChromeTestSuiteRunner() {}
 
 int ChromeTestSuiteRunner::RunTestSuite(int argc, char** argv) {
+#if defined(USE_AURA)
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(service_manager::switches::kServicePipeToken))
+    content::GetContentMainParams()->env_mode = aura::Env::Mode::MUS;
+#endif  // defined(USE_AURA)
+
   return ChromeTestSuite(argc, argv).Run();
 }
 
@@ -102,37 +107,26 @@
 
 void ChromeTestLauncherDelegate::PreSharding() {
 #if defined(OS_WIN)
-  // Construct the distribution specific equivalent of
-  // "delete HKCU\\SOFTWARE\\Chromium\\PreferenceMACs /f".
-  base::string16 operation(L"delete HKCU\\");
-  operation.append(install_static::GetRegistryPath());
-  operation.append(L"\\PreferenceMACs /f");
-  // TODO(gab): This is a nuclear option while the cleanup below doesn't work as
-  // the bots are in such bad shape per https://crbug.com/721245 that doing any
-  // registry operations from C++ results in fatal error 1450 (insufficient
-  // resources). Hopefully ShellExecute works...
-  ::ShellExecute(NULL, NULL, L"reg.exe", operation.c_str(), NULL, 0);
+  // Pre-test cleanup for registry state keyed off the profile dir (which can
+  // proliferate with the use of uniquely named scoped_dirs):
+  // https://crbug.com/721245. This needs to be here in order not to be racy
+  // with any tests that will access that state.
+  base::win::RegKey distrubution_key;
+  LONG result = distrubution_key.Open(HKEY_CURRENT_USER,
+                                      install_static::GetRegistryPath().c_str(),
+                                      KEY_SET_VALUE);
 
-// // Pre-test cleanup for registry state keyed off the profile dir (which can
-// // proliferate with the use of uniquely named scoped_dirs):
-// // https://crbug.com/721245. This needs to be here in order not to be racy
-// // with any tests that will access that state.
-// base::win::RegKey distrubution_key;
-// LONG result = distrubution_key.Open(
-//     HKEY_CURRENT_USER, install_static::GetRegistryPath().c_str(),
-//     KEY_SET_VALUE);
+  if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
+    LOG(ERROR) << "Failed to open distribution key for cleanup: " << result;
+    return;
+  }
 
-// if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
-//   LOG(ERROR) << "Failed to open distribution key for cleanup: " << result;
-//   return;
-// }
+  result = distrubution_key.DeleteKey(L"PreferenceMACs");
 
-// result = distrubution_key.DeleteKey(L"PreferenceMACs");
-
-// if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
-//   LOG(ERROR) << "Failed to cleanup PreferenceMACs: " << result;
-//   return;
-// }
+  if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
+    LOG(ERROR) << "Failed to cleanup PreferenceMACs: " << result;
+    return;
+  }
 #endif
 }
 
diff --git a/chrome/test/base/mash_browser_tests_main.cc b/chrome/test/base/mash_browser_tests_main.cc
index 7ff38d4..e5e68a0 100644
--- a/chrome/test/base/mash_browser_tests_main.cc
+++ b/chrome/test/base/mash_browser_tests_main.cc
@@ -153,9 +153,11 @@
 
 std::unique_ptr<content::ServiceManagerConnection>
     CreateServiceManagerConnection(MashTestLauncherDelegate* delegate) {
+  delegate->GetMojoTestConnectorForSingleProcess()->Init();
   std::unique_ptr<content::ServiceManagerConnection> connection(
       content::ServiceManagerConnection::Create(
-          delegate->GetMojoTestConnectorForSingleProcess()->Init(),
+          delegate->GetMojoTestConnectorForSingleProcess()
+              ->InitBackgroundServiceManager(),
           base::ThreadTaskRunnerHandle::Get()));
   connection->Start();
   connection->GetConnector()->StartService(mash::session::mojom::kServiceName);
diff --git a/chrome/test/base/mojo_test_connector.cc b/chrome/test/base/mojo_test_connector.cc
index 2293250..c42f42d9 100644
--- a/chrome/test/base/mojo_test_connector.cc
+++ b/chrome/test/base/mojo_test_connector.cc
@@ -18,6 +18,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/test_launcher.h"
+#include "mash/session/public/interfaces/constants.mojom.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
@@ -43,13 +44,12 @@
 // service manager.
 class MojoTestState : public content::TestState {
  public:
-  explicit MojoTestState(
-      service_manager::BackgroundServiceManager* background_service_manager,
-      base::CommandLine* command_line,
-      base::TestLauncher::LaunchOptions* test_launch_options,
-      const std::string& mus_config_switch,
-      base::OnceClosure on_process_launched)
-      : background_service_manager_(background_service_manager),
+  MojoTestState(MojoTestConnector* connector,
+                base::CommandLine* command_line,
+                base::TestLauncher::LaunchOptions* test_launch_options,
+                const std::string& mus_config_switch,
+                base::OnceClosure on_process_launched)
+      : connector_(connector),
         platform_channel_(base::MakeUnique<mojo::edk::PlatformChannelPair>()),
         main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
         on_process_launched_(std::move(on_process_launched)),
@@ -99,7 +99,10 @@
   // after ChildProcessLaunched as previous test runs will tear down existing
   // connections.
   void SetupService(base::ProcessId pid) {
-    background_service_manager_->RegisterService(
+    connector_->InitBackgroundServiceManager();
+    service_manager::BackgroundServiceManager* background_service_manager =
+        connector_->background_service_manager();
+    background_service_manager->RegisterService(
         service_manager::Identity(content::mojom::kPackagedServicesServiceName,
                                   service_manager::mojom::kRootUserID),
         std::move(service_), mojo::MakeRequest(&pid_receiver_));
@@ -112,7 +115,7 @@
   }
 
   mojo::edk::OutgoingBrokerClientInvitation broker_client_invitation_;
-  service_manager::BackgroundServiceManager* const background_service_manager_;
+  MojoTestConnector* connector_;
 
   // The ServicePtr must be created before child process launch so that the pipe
   // can be set on the command line. It is held until SetupService is called at
@@ -200,7 +203,7 @@
       background_service_manager_(nullptr),
       catalog_contents_(std::move(catalog_contents)) {}
 
-service_manager::mojom::ServiceRequest MojoTestConnector::Init() {
+void MojoTestConnector::Init() {
   // In single-process test mode, browser code will initialize the EDK and IPC.
   // Otherwise we ensure it's initialized here.
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -213,7 +216,10 @@
         ipc_thread_->task_runner(),
         mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST);
   }
+}
 
+service_manager::mojom::ServiceRequest
+MojoTestConnector::InitBackgroundServiceManager() {
   service_manager::mojom::ServicePtr service;
   auto request = mojo::MakeRequest(&service);
 
@@ -223,7 +229,7 @@
   background_service_manager_ =
       base::MakeUnique<service_manager::BackgroundServiceManager>(
           service_process_launcher_delegate_.get(),
-          std::move(catalog_contents_));
+          catalog_contents_->CreateDeepCopy());
   background_service_manager_->RegisterService(
       service_manager::Identity(config_ == MojoTestConnector::Config::MASH
                                     ? kMashTestRunnerName
@@ -240,7 +246,7 @@
     base::TestLauncher::LaunchOptions* test_launch_options,
     base::OnceClosure on_process_launched) {
   return base::MakeUnique<MojoTestState>(
-      background_service_manager_.get(), command_line, test_launch_options,
+      this, command_line, test_launch_options,
       config_ == MojoTestConnector::Config::MASH ? switches::kMash
                                                  : switches::kMus,
       std::move(on_process_launched));
diff --git a/chrome/test/base/mojo_test_connector.h b/chrome/test/base/mojo_test_connector.h
index 441cc8df7..fbeb11c 100644
--- a/chrome/test/base/mojo_test_connector.h
+++ b/chrome/test/base/mojo_test_connector.h
@@ -57,8 +57,15 @@
                     Config config);
   ~MojoTestConnector();
 
+  service_manager::BackgroundServiceManager* background_service_manager() {
+    return background_service_manager_.get();
+  }
+
+  // Initializes the Mojo environment, and IPC thread.
+  void Init();
+
   // Initializes the background thread the ServiceManager runs on.
-  service_manager::mojom::ServiceRequest Init();
+  service_manager::mojom::ServiceRequest InitBackgroundServiceManager();
 
   std::unique_ptr<content::TestState> PrepareForTest(
       base::CommandLine* command_line,
diff --git a/chromeos/cert_loader.h b/chromeos/cert_loader.h
index e575c08..a3704ce 100644
--- a/chromeos/cert_loader.h
+++ b/chromeos/cert_loader.h
@@ -69,20 +69,20 @@
   static std::string GetPkcs11IdAndSlotForCert(const net::X509Certificate& cert,
                                                int* slot_id);
 
-  // Starts the CertLoader with the passed system NSS cert database.
-  // The CertLoader will _not_ take ownership of the database - see comment on
-  // SetUserNSSDB.
-  // CertLoader supports working with only one database or with both (system and
-  // user) databases.
+  // Sets the NSS cert database which CertLoader should use to access system
+  // slot certificates. The CertLoader will _not_ take ownership of the database
+  // - see comment on SetUserNSSDB. CertLoader supports working with only one
+  // database or with both (system and user) databases.
   void SetSystemNSSDB(net::NSSCertDatabase* system_slot_database);
 
-  // Starts the CertLoader with the passed user NSS cert database.
+  // Sets the NSS cert database which CertLoader should use to access user slot
+  // certificates. CertLoader understands the edge case that this database could
+  // also give access to system slot certificates (e.g. for affiliated users).
   // The CertLoader will _not_ take the ownership of the database, but it
   // expects it to stay alive at least until the shutdown starts on the main
-  // thread. This assumes that SetUserNSSDB and other methods directly
-  // using |database_| are not called during shutdown.
-  // CertLoader supports working with only one database or with both (system and
-  // user) databases.
+  // thread. This assumes that SetUserNSSDB and other methods directly using
+  // |database_| are not called during shutdown. CertLoader supports working
+  // with only one database or with both (system and user) databases.
   void SetUserNSSDB(net::NSSCertDatabase* user_database);
 
   void AddObserver(CertLoader::Observer* observer);
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc
index 215b758..6a97a28 100644
--- a/components/autofill/core/browser/autofill_data_util.cc
+++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -25,25 +25,6 @@
 // Mappings from Chrome card types to Payment Request API basic card payment
 // spec types and icons. Note that "generic" is not in the spec.
 // https://w3c.github.io/webpayments-methods-card/#method-id
-#if defined(OS_ANDROID)
-// On Android, use the PR-specific resource IDs.
-const PaymentRequestData kPaymentRequestData[]{
-    {"americanExpressCC", "amex", IDR_AUTOFILL_PR_AMEX, IDS_AUTOFILL_CC_AMEX},
-    {"dinersCC", "diners", IDR_AUTOFILL_PR_DINERS, IDS_AUTOFILL_CC_DINERS},
-    {"discoverCC", "discover", IDR_AUTOFILL_PR_DISCOVER,
-     IDS_AUTOFILL_CC_DISCOVER},
-    {"jcbCC", "jcb", IDR_AUTOFILL_PR_JCB, IDS_AUTOFILL_CC_JCB},
-    {"masterCardCC", "mastercard", IDR_AUTOFILL_PR_MASTERCARD,
-     IDS_AUTOFILL_CC_MASTERCARD},
-    {"mirCC", "mir", IDR_AUTOFILL_PR_MIR, IDS_AUTOFILL_CC_MIR},
-    {"unionPayCC", "unionpay", IDR_AUTOFILL_PR_UNIONPAY,
-     IDS_AUTOFILL_CC_UNION_PAY},
-    {"visaCC", "visa", IDR_AUTOFILL_PR_VISA, IDS_AUTOFILL_CC_VISA},
-};
-const PaymentRequestData kGenericPaymentRequestData = {
-    "genericCC", "generic", IDR_AUTOFILL_PR_GENERIC, IDS_AUTOFILL_CC_GENERIC};
-#else  // !defined(OS_ANDROID)
-// On other platforms, use the Autofill resource IDs.
 const PaymentRequestData kPaymentRequestData[]{
     {"americanExpressCC", "amex", IDR_AUTOFILL_CC_AMEX, IDS_AUTOFILL_CC_AMEX},
     {"dinersCC", "diners", IDR_AUTOFILL_CC_DINERS, IDS_AUTOFILL_CC_DINERS},
@@ -59,7 +40,6 @@
 };
 const PaymentRequestData kGenericPaymentRequestData = {
     "genericCC", "generic", IDR_AUTOFILL_CC_GENERIC, IDS_AUTOFILL_CC_GENERIC};
-#endif
 
 const char* const name_prefixes[] = {
     "1lt",     "1st", "2lt", "2nd",    "3rd",  "admiral", "capt",
diff --git a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc
index 436e8bc..0930a321 100644
--- a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc
+++ b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc
@@ -18,9 +18,6 @@
 #include "components/ntp_snippets/category.h"
 #include "components/ntp_snippets/content_suggestion.h"
 #include "components/ntp_snippets/features.h"
-#include "components/ntp_snippets/pref_names.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/variations/variations_associated_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -41,10 +38,6 @@
 const char* kConsiderDesktopVisitsParamName =
     "bookmarks_consider_desktop_visits";
 
-// TODO(treib,jkrcal): Remove this after M57.
-const char kDeprecatedBookmarksFirstM54StartPref[] =
-    "ntp_suggestions.bookmarks.first_M54_start";
-
 // Any bookmark created or visited after this time will be considered recent.
 // Note that bookmarks can be shown that do not meet this threshold.
 base::Time GetThresholdTime() {
@@ -71,8 +64,7 @@
 
 BookmarkSuggestionsProvider::BookmarkSuggestionsProvider(
     ContentSuggestionsProvider::Observer* observer,
-    bookmarks::BookmarkModel* bookmark_model,
-    PrefService* pref_service)
+    bookmarks::BookmarkModel* bookmark_model)
     : ContentSuggestionsProvider(observer),
       category_status_(CategoryStatus::AVAILABLE_LOADING),
       provided_category_(
@@ -82,7 +74,6 @@
       end_of_list_last_visit_date_(GetThresholdTime()),
       consider_bookmark_visits_from_desktop_(AreDesktopVisitsConsidered()) {
   observer->OnCategoryStatusChanged(this, provided_category_, category_status_);
-  pref_service->ClearPref(kDeprecatedBookmarksFirstM54StartPref);
   bookmark_model_->AddObserver(this);
   FetchBookmarks();
 }
@@ -91,12 +82,6 @@
   bookmark_model_->RemoveObserver(this);
 }
 
-// static
-void BookmarkSuggestionsProvider::RegisterProfilePrefs(
-    PrefRegistrySimple* registry) {
-  registry->RegisterInt64Pref(kDeprecatedBookmarksFirstM54StartPref, 0);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Private methods
 
diff --git a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h
index 64cd6e2..404c8d6 100644
--- a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h
+++ b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h
@@ -15,9 +15,6 @@
 #include "components/ntp_snippets/category_status.h"
 #include "components/ntp_snippets/content_suggestions_provider.h"
 
-class PrefRegistrySimple;
-class PrefService;
-
 namespace ntp_snippets {
 
 // Provides content suggestions from the bookmarks model.
@@ -25,12 +22,9 @@
                                     public bookmarks::BookmarkModelObserver {
  public:
   BookmarkSuggestionsProvider(ContentSuggestionsProvider::Observer* observer,
-                              bookmarks::BookmarkModel* bookmark_model,
-                              PrefService* pref_service);
+                              bookmarks::BookmarkModel* bookmark_model);
   ~BookmarkSuggestionsProvider() override;
 
-  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
  private:
   // ContentSuggestionsProvider implementation.
   CategoryStatus GetCategoryStatus(Category category) override;
diff --git a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider_unittest.cc b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider_unittest.cc
index 92682d5..fda7b18 100644
--- a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider_unittest.cc
+++ b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider_unittest.cc
@@ -18,7 +18,6 @@
 #include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h"
 #include "components/ntp_snippets/category.h"
 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
-#include "components/prefs/testing_pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -53,15 +52,13 @@
                     _, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
                     CategoryStatus::AVAILABLE))
         .RetiresOnSaturation();
-    BookmarkSuggestionsProvider::RegisterProfilePrefs(test_prefs_.registry());
-    provider_ = base::MakeUnique<BookmarkSuggestionsProvider>(
-        &observer_, model_.get(), &test_prefs_);
+    provider_ =
+        base::MakeUnique<BookmarkSuggestionsProvider>(&observer_, model_.get());
   }
 
  protected:
   std::unique_ptr<bookmarks::BookmarkModel> model_;
   StrictMock<MockContentSuggestionsProviderObserver> observer_;
-  TestingPrefServiceSimple test_prefs_;
   std::unique_ptr<BookmarkSuggestionsProvider> provider_;
 };
 
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 12e57cf..350cccf 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -238,26 +238,22 @@
   std::vector<autofill::AutofillProfile*> profiles =
       personal_data_manager_->GetProfilesToSuggest();
 
+  std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
+  raw_profiles_for_filtering.reserve(profiles.size());
+
   // PaymentRequest may outlive the Profiles returned by the Data Manager.
   // Thus, we store copies, and return a vector of pointers to these copies
   // whenever Profiles are requested.
   for (size_t i = 0; i < profiles.size(); i++) {
     profile_cache_.push_back(
         base::MakeUnique<autofill::AutofillProfile>(*profiles[i]));
-
-    shipping_profiles_.push_back(profile_cache_[i].get());
+    raw_profiles_for_filtering.push_back(profile_cache_.back().get());
   }
 
-  std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering(
-      profile_cache_.size());
-  std::transform(profile_cache_.begin(), profile_cache_.end(),
-                 raw_profiles_for_filtering.begin(),
-                 [](const std::unique_ptr<autofill::AutofillProfile>& p) {
-                   return p.get();
-                 });
-
   contact_profiles_ = profile_comparator()->FilterProfilesForContact(
       raw_profiles_for_filtering);
+  shipping_profiles_ = profile_comparator()->FilterProfilesForShipping(
+      raw_profiles_for_filtering);
 
   // Create the list of available instruments. A copy of each card will be made
   // by their respective AutofillPaymentInstrument.
@@ -269,22 +265,17 @@
 
 void PaymentRequestState::SetDefaultProfileSelections() {
   // Only pre-select an address if the merchant provided at least one selected
-  // shipping option.
-  if (!shipping_profiles().empty() && spec_->selected_shipping_option()) {
-    // Choose any complete shipping profile, or default to the most frecent
-    // address if no complete address could be found.
-    selected_shipping_profile_ = shipping_profiles_[0];
-    for (autofill::AutofillProfile* profile : shipping_profiles_) {
-      if (profile_comparator_.IsShippingComplete(profile)) {
-        selected_shipping_profile_ = profile;
-        break;
-      }
-    }
+  // shipping option, and the top profile is complete. Assumes that profiles
+  // have already been sorted for completeness and frecency.
+  if (!shipping_profiles().empty() && spec_->selected_shipping_option() &&
+      profile_comparator()->IsShippingComplete(shipping_profiles_[0])) {
+    selected_shipping_profile_ = shipping_profiles()[0];
   }
 
   // Contact profiles were ordered by completeness in addition to frecency;
   // the first one is the best default selection.
-  if (!contact_profiles().empty())
+  if (!contact_profiles().empty() &&
+      profile_comparator()->IsContactInfoComplete(contact_profiles_[0]))
     selected_contact_profile_ = contact_profiles()[0];
 
   // TODO(crbug.com/702063): Change this code to prioritize instruments by use
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc
index 87ad961..b2b3fcc 100644
--- a/components/payments/core/payment_request_data_util.cc
+++ b/components/payments/core/payment_request_data_util.cc
@@ -152,6 +152,15 @@
   }
 }
 
+base::string16 GetFormattedPhoneNumberForDisplay(
+    const autofill::AutofillProfile& profile,
+    const std::string& locale) {
+  return base::UTF8ToUTF16(FormatPhoneForDisplay(
+      base::UTF16ToUTF8(profile.GetInfo(
+          autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER), locale)),
+      GetCountryCodeWithFallback(&profile, locale)));
+}
+
 std::string FormatPhoneForDisplay(const std::string& phone_number,
                                   const std::string& country_code) {
   return FormatPhoneNumber(phone_number, country_code,
diff --git a/components/payments/core/payment_request_data_util.h b/components/payments/core/payment_request_data_util.h
index 29593f6..c301946d 100644
--- a/components/payments/core/payment_request_data_util.h
+++ b/components/payments/core/payment_request_data_util.h
@@ -52,6 +52,11 @@
     std::vector<std::string>* out_supported_networks,
     std::set<std::string>* out_basic_card_supported_networks);
 
+// Returns the phone number from the given |profile| formatted for display.
+base::string16 GetFormattedPhoneNumberForDisplay(
+    const autofill::AutofillProfile& profile,
+    const std::string& locale);
+
 // Formats the given number |phone_number| to
 // i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL format
 // by using i18n::phonenumbers::PhoneNumberUtil::Format.
diff --git a/components/payments/core/payments_profile_comparator.cc b/components/payments/core/payments_profile_comparator.cc
index 832e005..e295762 100644
--- a/components/payments/core/payments_profile_comparator.cc
+++ b/components/payments/core/payments_profile_comparator.cc
@@ -118,9 +118,6 @@
 
 int PaymentsProfileComparator::GetContactCompletenessScore(
     const autofill::AutofillProfile* profile) const {
-  if (!profile)
-    return 0;
-
   // Create a bitmask of the fields that are both present and required.
   ProfileFields present =
       ~GetMissingProfileFields(profile) & GetRequiredProfileFieldsForContact();
@@ -137,18 +134,42 @@
            GetRequiredProfileFieldsForContact());
 }
 
-bool PaymentsProfileComparator::IsContactMoreComplete(
-    const autofill::AutofillProfile* p1,
-    const autofill::AutofillProfile* p2) const {
-  return GetContactCompletenessScore(p1) > GetContactCompletenessScore(p2);
-}
-
 base::string16 PaymentsProfileComparator::GetStringForMissingContactFields(
     const autofill::AutofillProfile& profile) const {
   return GetStringForMissingFields(GetMissingProfileFields(&profile) &
                                    GetRequiredProfileFieldsForContact());
 }
 
+std::vector<autofill::AutofillProfile*>
+PaymentsProfileComparator::FilterProfilesForShipping(
+    const std::vector<autofill::AutofillProfile*>& profiles) const {
+  // Since we'll be changing the order/contents of the const input vector,
+  // we make a copy.
+  std::vector<autofill::AutofillProfile*> processed = profiles;
+
+  std::stable_sort(
+      processed.begin(), processed.end(),
+      std::bind(&PaymentsProfileComparator::IsShippingMoreComplete, this,
+                std::placeholders::_1, std::placeholders::_2));
+
+  // TODO(crbug.com/722949): Remove profiles with no relevant information, or
+  // which are subsets of more-complete profiles.
+
+  return processed;
+}
+
+int PaymentsProfileComparator::GetShippingCompletenessScore(
+    const autofill::AutofillProfile* profile) const {
+  // Create a bitmask of the fields that are both present and required.
+  ProfileFields present =
+      ~GetMissingProfileFields(profile) & GetRequiredProfileFieldsForShipping();
+
+  // Count how many are set. The completeness of the address is weighted so as
+  // to dominate the other fields.
+  return !!(present & kName) + !!(present & kPhone) +
+         (10 * !!(present & kAddress));
+}
+
 bool PaymentsProfileComparator::IsShippingComplete(
     const autofill::AutofillProfile* profile) const {
   // Mask the fields that are missing with those that are requried. If any bits
@@ -248,4 +269,16 @@
   return autofill::addressinput::HasAllRequiredFields(*data);
 }
 
+bool PaymentsProfileComparator::IsContactMoreComplete(
+    const autofill::AutofillProfile* p1,
+    const autofill::AutofillProfile* p2) const {
+  return GetContactCompletenessScore(p1) > GetContactCompletenessScore(p2);
+}
+
+bool PaymentsProfileComparator::IsShippingMoreComplete(
+    const autofill::AutofillProfile* p1,
+    const autofill::AutofillProfile* p2) const {
+  return GetShippingCompletenessScore(p1) > GetShippingCompletenessScore(p2);
+}
+
 }  // namespace payments
diff --git a/components/payments/core/payments_profile_comparator.h b/components/payments/core/payments_profile_comparator.h
index 2c8b934a..e186e05 100644
--- a/components/payments/core/payments_profile_comparator.h
+++ b/components/payments/core/payments_profile_comparator.h
@@ -71,20 +71,24 @@
   // |profile|.
   bool IsContactInfoComplete(const autofill::AutofillProfile* profile) const;
 
-  // Comparison function suitable for sorting profiles by contact completeness
-  // score with std::sort.
-  bool IsContactMoreComplete(const autofill::AutofillProfile* p1,
-                             const autofill::AutofillProfile* p2) const;
+  // Returns profiles for shipping, ordered by completeness. |profiles| should
+  // be passed in order of frecency, and this order will be preserved among
+  // equally-complete profiles.
+  std::vector<autofill::AutofillProfile*> FilterProfilesForShipping(
+      const std::vector<autofill::AutofillProfile*>& profiles) const;
+
+  int GetShippingCompletenessScore(
+      const autofill::AutofillProfile* profile) const;
+
+  // Returns true iff every field needed to use |profile| as a shipping address
+  // is populated.
+  bool IsShippingComplete(const autofill::AutofillProfile* profile) const;
 
   // Returns a localized string to be displayed in UI indicating what action,
   // if any, must be taken for the given profile to be used as contact info.
   base::string16 GetStringForMissingContactFields(
       const autofill::AutofillProfile& profile) const;
 
-  // Returns true iff every field needed to use |profile| as a shipping address
-  // is populated.
-  bool IsShippingComplete(const autofill::AutofillProfile* profile) const;
-
   // Returns a localized string to be displayed in UI indicating what action,
   // if any, must be taken for the given profile to be used as a shipping
   // address.
@@ -103,6 +107,14 @@
   base::string16 GetStringForMissingFields(ProfileFields fields) const;
   bool AreRequiredAddressFieldsPresent(
       const autofill::AutofillProfile& profile) const;
+
+  // Comparison functions suitable for sorting profiles by completeness
+  // score with std::sort.
+  bool IsContactMoreComplete(const autofill::AutofillProfile* p1,
+                             const autofill::AutofillProfile* p2) const;
+  bool IsShippingMoreComplete(const autofill::AutofillProfile* p1,
+                              const autofill::AutofillProfile* p2) const;
+
   mutable std::map<std::string, ProfileFields> cache_;
   const PaymentOptionsProvider& options_;
 };
diff --git a/components/payments/core/payments_profile_comparator_unittest.cc b/components/payments/core/payments_profile_comparator_unittest.cc
index ac0691e..18f3e58a 100644
--- a/components/payments/core/payments_profile_comparator_unittest.cc
+++ b/components/payments/core/payments_profile_comparator_unittest.cc
@@ -247,6 +247,103 @@
   EXPECT_TRUE(empty_comp.IsContactInfoComplete(nullptr));
 }
 
+TEST(PaymentRequestProfileUtilTest, FilterProfilesForShipping) {
+  MockPaymentOptionsProvider provider(kRequestShipping);
+  PaymentsProfileComparator comp("en-US", provider);
+
+  AutofillProfile address_only = CreateProfileWithCompleteAddress("", "");
+
+  AutofillProfile no_name = CreateProfileWithCompleteAddress("", "6515553226");
+  AutofillProfile no_phone = CreateProfileWithCompleteAddress("Homer", "");
+
+  AutofillProfile empty = CreateProfileWithContactInfo("", "", "");
+
+  AutofillProfile complete1 =
+      CreateProfileWithCompleteAddress("Homer", "6515553226");
+
+  AutofillProfile partial_address =
+      CreateProfileWithPartialAddress("Homer", "6515553226");
+  AutofillProfile no_address =
+      CreateProfileWithContactInfo("Homer", "", "6515553226");
+
+  AutofillProfile complete2 =
+      CreateProfileWithCompleteAddress("Bart", "6515553226");
+
+  AutofillProfile partial_no_phone =
+      CreateProfileWithPartialAddress("", "6515553226");
+  AutofillProfile partial_no_name =
+      CreateProfileWithPartialAddress("Homer", "");
+
+  std::vector<AutofillProfile*> profiles = {
+      &address_only,     &no_name,         &no_phone,   &empty,
+      &complete1,        &partial_address, &no_address, &complete2,
+      &partial_no_phone, &partial_no_name};
+
+  std::vector<AutofillProfile*> filtered =
+      comp.FilterProfilesForShipping(profiles);
+
+  // Current logic does not remove profiles, only reorder them.
+  ASSERT_EQ(10u, filtered.size());
+
+  // First, the complete profiles should be hoisted to the top, keeping their
+  // relative order.
+  EXPECT_EQ(&complete1, filtered[0]);
+  EXPECT_EQ(&complete2, filtered[1]);
+
+  // Next are profiles with a complete address but missing one other field.
+  EXPECT_EQ(&no_name, filtered[2]);
+  EXPECT_EQ(&no_phone, filtered[3]);
+
+  // A profile with only a complete address should still appear before profiles
+  // with partial/empty addresses.
+  EXPECT_EQ(&address_only, filtered[4]);
+
+  // Profiles with partial/no address then are sorted by whether or not they
+  // have names and/or phone numbers.
+  EXPECT_EQ(&partial_address, filtered[5]);
+  EXPECT_EQ(&no_address, filtered[6]);
+
+  EXPECT_EQ(&partial_no_phone, filtered[7]);
+  EXPECT_EQ(&partial_no_name, filtered[8]);
+
+  EXPECT_EQ(&empty, filtered[9]);
+}
+
+TEST(PaymentRequestProfileUtilTest, GetShippingCompletenessScore) {
+  MockPaymentOptionsProvider provider(kRequestShipping);
+  PaymentsProfileComparator comp("en-US", provider);
+
+  // 12 points for a complete profile: 10 for address, 1 each for name/phone.
+  AutofillProfile p1 = CreateProfileWithCompleteAddress("Homer", "6515553226");
+  EXPECT_EQ(12, comp.GetShippingCompletenessScore(&p1));
+
+  // 11 points if name or phone is missing.
+  AutofillProfile p2 = CreateProfileWithCompleteAddress("", "6515553226");
+  AutofillProfile p3 = CreateProfileWithCompleteAddress("Homer", "");
+  EXPECT_EQ(11, comp.GetShippingCompletenessScore(&p2));
+  EXPECT_EQ(11, comp.GetShippingCompletenessScore(&p3));
+
+  // 10 points for complete address only.
+  AutofillProfile p4 = CreateProfileWithCompleteAddress("", "");
+  EXPECT_EQ(10, comp.GetShippingCompletenessScore(&p4));
+
+  // 2 points for name and phone without address.
+  AutofillProfile p5 = CreateProfileWithContactInfo("Homer", "", "6515553226");
+  EXPECT_EQ(2, comp.GetShippingCompletenessScore(&p5));
+
+  // 1 point for name or phone alone.
+  AutofillProfile p6 = CreateProfileWithContactInfo("Homer", "", "");
+  AutofillProfile p7 = CreateProfileWithContactInfo("", "", "6515553226");
+  EXPECT_EQ(1, comp.GetShippingCompletenessScore(&p6));
+  EXPECT_EQ(1, comp.GetShippingCompletenessScore(&p7));
+
+  // No points for empty profile, or profile with only a partial address.
+  AutofillProfile p8 = CreateProfileWithContactInfo("", "", "");
+  AutofillProfile p9 = CreateProfileWithPartialAddress("", "");
+  EXPECT_EQ(0, comp.GetShippingCompletenessScore(&p8));
+  EXPECT_EQ(0, comp.GetShippingCompletenessScore(&p9));
+}
+
 TEST(PaymentRequestProfileUtilTest, IsShippingComplete) {
   MockPaymentOptionsProvider provider(kRequestShipping);
   PaymentsProfileComparator comp("en-US", provider);
diff --git a/components/resources/autofill_scaled_resources.grdp b/components/resources/autofill_scaled_resources.grdp
index b3a3719..5eedb43 100644
--- a/components/resources/autofill_scaled_resources.grdp
+++ b/components/resources/autofill_scaled_resources.grdp
@@ -22,21 +22,6 @@
     <structure type="chrome_scaled_image" name="IDR_AUTOFILL_HTTPS_INVALID_WARNING" file="autofill/cc-generic.png" />
   </if>
 
-   <!-- Payment Request image variants.
-        NOTE: These are placeholders; actual values are not used, since IDs are
-        mapped to drawables in resource_id.h -->
-  <if expr="is_android">
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_AMEX" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DINERS" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_DISCOVER" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_GENERIC" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_JCB" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_MASTERCARD" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_MIR" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_UNIONPAY" file="autofill/cc-generic.png" />
-    <structure type="chrome_scaled_image" name="IDR_AUTOFILL_PR_VISA" file="autofill/cc-generic.png" />
-  </if>
-
   <structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT" file="autofill/credit_card_cvc_hint.png" />
   <structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT_AMEX" file="autofill/credit_card_cvc_hint_amex.png" />
   <if expr="is_ios or is_android">
diff --git a/components/translate/core/browser/mock_translate_ranker.cc b/components/translate/core/browser/mock_translate_ranker.cc
index a96813a..1aa3d14 100644
--- a/components/translate/core/browser/mock_translate_ranker.cc
+++ b/components/translate/core/browser/mock_translate_ranker.cc
@@ -19,9 +19,6 @@
 }
 
 bool MockTranslateRanker::ShouldOfferTranslation(
-    const TranslatePrefs& /* translate_prefs */,
-    const std::string& /* src_lang */,
-    const std::string& /* dst_lang */,
     metrics::TranslateEventProto* /*translate_event */) {
   return should_offer_translation_;
 }
diff --git a/components/translate/core/browser/mock_translate_ranker.h b/components/translate/core/browser/mock_translate_ranker.h
index f2e9d446..51dae4f 100644
--- a/components/translate/core/browser/mock_translate_ranker.h
+++ b/components/translate/core/browser/mock_translate_ranker.h
@@ -20,8 +20,6 @@
 
 namespace translate {
 
-class TranslatePrefs;
-
 namespace testing {
 
 class MockTranslateRanker : public TranslateRanker {
@@ -43,9 +41,6 @@
   // TranslateRanker Implementation:
   uint32_t GetModelVersion() const override;
   bool ShouldOfferTranslation(
-      const TranslatePrefs& translate_prefs,
-      const std::string& src_lang,
-      const std::string& dst_lang,
       metrics::TranslateEventProto* translate_events) override;
   void FlushTranslateEvents(
       std::vector<metrics::TranslateEventProto>* events) override;
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index a9970118..089c6137c 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -220,8 +220,8 @@
 
   // Querying the ranker now, but not exiting immediately so that we may log
   // other potential suppression reasons.
-  bool should_offer_translation = translate_ranker_->ShouldOfferTranslation(
-      *translate_prefs, language_code, target_lang, translate_event_.get());
+  bool should_offer_translation =
+      translate_ranker_->ShouldOfferTranslation(translate_event_.get());
 
   // Nothing to do if either the language Chrome is in or the language of
   // the page is not supported by the translation server.
diff --git a/components/translate/core/browser/translate_ranker.h b/components/translate/core/browser/translate_ranker.h
index 3b095383..9867052 100644
--- a/components/translate/core/browser/translate_ranker.h
+++ b/components/translate/core/browser/translate_ranker.h
@@ -20,8 +20,6 @@
 
 namespace translate {
 
-class TranslatePrefs;
-
 // If enabled, downloads a translate ranker model and uses it to determine
 // whether the user should be given a translation prompt or not.
 class TranslateRanker : public KeyedService {
@@ -32,14 +30,10 @@
   virtual uint32_t GetModelVersion() const = 0;
 
   // Returns true if executing the ranker model in the translation prompt
-  // context described by |translate_prefs|, |src_lang|, |dst_lang| and possibly
+  // context described by |translate_event| and possibly
   // other global browser context attributes suggests that the user should be
   // prompted as to whether translation should be performed.
-  // TODO(hamelphi): Take only the proto as input and extract features from it.
   virtual bool ShouldOfferTranslation(
-      const TranslatePrefs& translate_prefs,
-      const std::string& src_lang,
-      const std::string& dst_lang,
       metrics::TranslateEventProto* translate_event) = 0;
 
   // Transfers cached translate events to the given vector pointer and clears
diff --git a/components/translate/core/browser/translate_ranker_impl.cc b/components/translate/core/browser/translate_ranker_impl.cc
index 6f34fa2..d31d471 100644
--- a/components/translate/core/browser/translate_ranker_impl.cc
+++ b/components/translate/core/browser/translate_ranker_impl.cc
@@ -15,7 +15,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/profiler/scoped_tracker.h"
-#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -23,9 +22,6 @@
 #include "components/translate/core/browser/proto/ranker_model.pb.h"
 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h"
 #include "components/translate/core/browser/ranker_model.h"
-#include "components/translate/core/browser/translate_download_manager.h"
-#include "components/translate/core/browser/translate_prefs.h"
-#include "components/translate/core/browser/translate_url_fetcher.h"
 #include "components/translate/core/common/translate_switches.h"
 #include "components/ukm/public/ukm_entry_builder.h"
 #include "components/ukm/public/ukm_recorder.h"
@@ -106,17 +102,16 @@
       denied_ratio(SafeRatio(denied_count, total_count)),
       ignored_ratio(SafeRatio(ignored_count, total_count)) {}
 
-TranslateRankerFeatures::TranslateRankerFeatures(const TranslatePrefs& prefs,
-                                                 const std::string& src,
-                                                 const std::string& dst,
-                                                 const std::string& locale)
-    : TranslateRankerFeatures(prefs.GetTranslationAcceptedCount(src),
-                              prefs.GetTranslationDeniedCount(src),
-                              prefs.GetTranslationIgnoredCount(src),
-                              src,
-                              dst,
-                              prefs.GetCountry(),
-                              locale) {}
+// TODO(hamelphi): Log locale in TranslateEventProtos.
+TranslateRankerFeatures::TranslateRankerFeatures(
+    const metrics::TranslateEventProto& translate_event)
+    : TranslateRankerFeatures(translate_event.accept_count(),
+                              translate_event.decline_count(),
+                              translate_event.ignore_count(),
+                              translate_event.source_language(),
+                              translate_event.target_language(),
+                              translate_event.country(),
+                              "" /*locale*/) {}
 
 TranslateRankerFeatures::~TranslateRankerFeatures() {}
 
@@ -195,9 +190,6 @@
 }
 
 bool TranslateRankerImpl::ShouldOfferTranslation(
-    const TranslatePrefs& translate_prefs,
-    const std::string& src_lang,
-    const std::string& dst_lang,
     metrics::TranslateEventProto* translate_event) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
   // The ranker is a gate in the "show a translation prompt" flow. To retain
@@ -234,11 +226,8 @@
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
           "646711 translate::TranslateRankerImpl::ShouldOfferTranslation"));
 
-  TranslateRankerFeatures features(
-      translate_prefs, src_lang, dst_lang,
-      TranslateDownloadManager::GetInstance()->application_locale());
+  bool result = GetModelDecision(*translate_event);
 
-  bool result = GetModelDecision(features);
   UMA_HISTOGRAM_BOOLEAN("Translate.Ranker.QueryResult", result);
 
   translate_event->set_ranker_response(
@@ -253,33 +242,38 @@
 }
 
 bool TranslateRankerImpl::GetModelDecision(
-    const TranslateRankerFeatures& features) {
+    const metrics::TranslateEventProto& translate_event) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
   SCOPED_UMA_HISTOGRAM_TIMER("Translate.Ranker.Timer.CalculateScore");
   DCHECK(model_ != nullptr);
-  const TranslateRankerModel::LogisticRegressionModel& logit =
+
+  // TODO(hamelphi): consider deprecating TranslateRankerFeatures and move the
+  // logic here.
+  const TranslateRankerFeatures features(translate_event);
+
+  const TranslateRankerModel::LogisticRegressionModel& lr_model =
       model_->proto().translate().logistic_regression_model();
 
   double dot_product =
-      (features.accepted_count * logit.accept_count_weight()) +
-      (features.denied_count * logit.decline_count_weight()) +
-      (features.ignored_count * logit.ignore_count_weight()) +
-      (features.accepted_ratio * logit.accept_ratio_weight()) +
-      (features.denied_ratio * logit.decline_ratio_weight()) +
-      (features.ignored_ratio * logit.ignore_ratio_weight()) +
-      ScoreComponent(logit.source_language_weight(), features.src_lang) +
-      ScoreComponent(logit.target_language_weight(), features.dst_lang) +
-      ScoreComponent(logit.country_weight(), features.country) +
-      ScoreComponent(logit.locale_weight(), features.app_locale);
+      (features.accepted_count * lr_model.accept_count_weight()) +
+      (features.denied_count * lr_model.decline_count_weight()) +
+      (features.ignored_count * lr_model.ignore_count_weight()) +
+      (features.accepted_ratio * lr_model.accept_ratio_weight()) +
+      (features.denied_ratio * lr_model.decline_ratio_weight()) +
+      (features.ignored_ratio * lr_model.ignore_ratio_weight()) +
+      ScoreComponent(lr_model.source_language_weight(), features.src_lang) +
+      ScoreComponent(lr_model.target_language_weight(), features.dst_lang) +
+      ScoreComponent(lr_model.country_weight(), features.country) +
+      ScoreComponent(lr_model.locale_weight(), features.app_locale);
 
-  double score = Sigmoid(dot_product + logit.bias());
+  double score = Sigmoid(dot_product + lr_model.bias());
 
   DVLOG(2) << "TranslateRankerImpl::GetModelDecision: "
            << "Score = " << score << ", Features=[" << features << "]";
 
   float decision_threshold = kTranslationOfferDefaultThreshold;
-  if (logit.threshold() > 0) {
-    decision_threshold = logit.threshold();
+  if (lr_model.threshold() > 0) {
+    decision_threshold = lr_model.threshold();
   }
 
   return score >= decision_threshold;
diff --git a/components/translate/core/browser/translate_ranker_impl.h b/components/translate/core/browser/translate_ranker_impl.h
index fa3eb4b..abbed4d5 100644
--- a/components/translate/core/browser/translate_ranker_impl.h
+++ b/components/translate/core/browser/translate_ranker_impl.h
@@ -34,8 +34,6 @@
 
 namespace translate {
 
-class TranslatePrefs;
-
 // Features used to enable ranker query, enforcement and logging. Note that
 // enabling enforcement implies (forces) enabling queries.
 extern const base::Feature kTranslateRankerQuery;
@@ -53,10 +51,7 @@
                           const std::string& cntry,
                           const std::string& locale);
 
-  TranslateRankerFeatures(const TranslatePrefs& prefs,
-                          const std::string& src,
-                          const std::string& dst,
-                          const std::string& locale);
+  TranslateRankerFeatures(const metrics::TranslateEventProto& tep);
 
   ~TranslateRankerFeatures();
 
@@ -101,9 +96,6 @@
   // TranslateRanker...
   uint32_t GetModelVersion() const override;
   bool ShouldOfferTranslation(
-      const TranslatePrefs& translate_prefs,
-      const std::string& src_lang,
-      const std::string& dst_lang,
       metrics::TranslateEventProto* translate_event) override;
   void FlushTranslateEvents(
       std::vector<metrics::TranslateEventProto>* events) override;
@@ -120,8 +112,8 @@
       std::unique_ptr<chrome_intelligence::RankerModel> model);
 
   // Get the model decision on whether we should show the translate
-  // UI or not given |features|.
-  bool GetModelDecision(const TranslateRankerFeatures& features);
+  // UI or not given |translate_event|.
+  bool GetModelDecision(const metrics::TranslateEventProto& translate_event);
 
   // Check if the ModelLoader has been initialized. Used to test ModelLoader
   // logic.
diff --git a/components/translate/core/browser/translate_ranker_impl_unittest.cc b/components/translate/core/browser/translate_ranker_impl_unittest.cc
index e3a9743..b61b4b7 100644
--- a/components/translate/core/browser/translate_ranker_impl_unittest.cc
+++ b/components/translate/core/browser/translate_ranker_impl_unittest.cc
@@ -16,13 +16,9 @@
 #include "base/test/scoped_task_environment.h"
 #include "components/metrics/proto/translate_event.pb.h"
 #include "components/metrics/proto/ukm/source.pb.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/translate/core/browser/proto/ranker_model.pb.h"
 #include "components/translate/core/browser/proto/translate_ranker_model.pb.h"
 #include "components/translate/core/browser/ranker_model.h"
-#include "components/translate/core/browser/translate_download_manager.h"
-#include "components/translate/core/browser/translate_prefs.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "components/ukm/ukm_source.h"
 #include "net/url_request/test_url_fetcher_factory.h"
@@ -35,9 +31,7 @@
 using translate::kTranslateRankerEnforcement;
 using translate::kTranslateRankerQuery;
 using translate::kTranslateRankerDecisionOverride;
-using translate::TranslateDownloadManager;
 using translate::TranslateRankerFeatures;
-using translate::TranslatePrefs;
 using translate::TranslateRankerImpl;
 
 constexpr uint32_t kModelVersion = 1234;
@@ -46,15 +40,13 @@
  protected:
   TranslateRankerImplTest();
 
-  void SetUp() override;
-
-  void TearDown() override;
-
   // Initializes the explicitly |enabled| and |disabled| features for this test.
   void InitFeatures(const std::initializer_list<base::Feature>& enabled,
                     const std::initializer_list<base::Feature>& disabled);
 
-  // Returns a TranslateRankerImpl object with |threshold| for testing.
+  // Returns a TranslateRankerImpl object with |threshold| for testing. The
+  // returned ranker is configured with an empty cache path and URL and will not
+  // invoke the model loader.
   std::unique_ptr<TranslateRankerImpl> GetRankerForTest(float threshold);
 
   // Implements the same sigmoid function used by TranslateRankerImpl.
@@ -64,83 +56,36 @@
   static metrics::TranslateEventProto CreateTranslateEvent(
       const std::string& src_lang,
       const std::string& dst_lang,
+      const std::string& country,
       int accept_count,
       int decline_count,
       int ignore_count);
 
-  // The platform-specific name of the preferred language pref.
-  static const char* const kPreferredLanguagePref;
-
-  // Prefs.
-  std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_;
-  std::unique_ptr<translate::TranslatePrefs> translate_prefs_;
+  // Returns a translate event initialized with the given parameters.
+  static metrics::TranslateEventProto CreateDefaultTranslateEvent();
 
   ukm::TestUkmRecorder* GetTestUkmRecorder() { return &test_ukm_recorder_; }
-  metrics::TranslateEventProto tep1_ =
-      CreateTranslateEvent("fr", "en", 1, 0, 3);
-  metrics::TranslateEventProto tep2_ =
-      CreateTranslateEvent("jp", "en", 2, 0, 3);
-  metrics::TranslateEventProto tep3_ =
-      CreateTranslateEvent("es", "de", 4, 5, 6);
+  metrics::TranslateEventProto translate_event1_ =
+      CreateTranslateEvent("fr", "en", "de", 1, 0, 3);
+  metrics::TranslateEventProto translate_event2_ =
+      CreateTranslateEvent("jp", "en", "de", 2, 0, 3);
+  metrics::TranslateEventProto translate_event3_ =
+      CreateTranslateEvent("es", "de", "de", 4, 5, 6);
 
  private:
   ukm::TestUkmRecorder test_ukm_recorder_;
 
-  // Override the default URL fetcher to return custom responses for tests.
-  net::TestURLFetcherFactory url_fetcher_factory_;
-
-  // Used to initialize the translate download manager.
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
-
   // Sets up the task scheduling/task-runner environment for each test.
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   // Manages the enabling/disabling of features within the scope of a test.
   base::test::ScopedFeatureList scoped_feature_list_;
 
-  // Cache and reset the application locale for each test.
-  std::string locale_;
-
   DISALLOW_COPY_AND_ASSIGN(TranslateRankerImplTest);
 };
 
-const char* const TranslateRankerImplTest::kPreferredLanguagePref =
-#if defined(OS_CHROMEOS)
-    "settings.language.preferred_languages";
-#else
-    nullptr;
-#endif
-
 TranslateRankerImplTest::TranslateRankerImplTest() {}
 
-void TranslateRankerImplTest::SetUp() {
-  // Setup the translate download manager.
-  locale_ = TranslateDownloadManager::GetInstance()->application_locale();
-  request_context_ =
-      new net::TestURLRequestContextGetter(base::ThreadTaskRunnerHandle::Get());
-  TranslateDownloadManager::GetInstance()->set_application_locale("zh-CN");
-  TranslateDownloadManager::GetInstance()->set_request_context(
-      request_context_.get());
-
-  // Setup a 50/50 accepted/denied count for "english" when initialize the
-  // prefs and translate prefs.
-  base::DictionaryValue lang_count;
-  lang_count.SetInteger("en", 50);
-  prefs_.reset(new sync_preferences::TestingPrefServiceSyncable());
-  TranslatePrefs::RegisterProfilePrefs(prefs_->registry());
-  prefs_->Set(TranslatePrefs::kPrefTranslateAcceptedCount, lang_count);
-  prefs_->Set(TranslatePrefs::kPrefTranslateDeniedCount, lang_count);
-  translate_prefs_.reset(new TranslatePrefs(
-      prefs_.get(), "intl.accept_languages", kPreferredLanguagePref));
-  translate_prefs_->SetCountry("de");
-}
-
-void TranslateRankerImplTest::TearDown() {
-  base::RunLoop().RunUntilIdle();
-  TranslateDownloadManager::GetInstance()->set_application_locale(locale_);
-  TranslateDownloadManager::GetInstance()->set_request_context(nullptr);
-}
-
 void TranslateRankerImplTest::InitFeatures(
     const std::initializer_list<base::Feature>& enabled,
     const std::initializer_list<base::Feature>& disabled) {
@@ -176,11 +121,6 @@
   country_weight["ca"] = 0.08f;
   country_weight["cn"] = 0.09f;
 
-  auto& locale_weight = *details->mutable_locale_weight();
-  locale_weight["en-us"] = 0.10f;
-  locale_weight["en-ca"] = 0.11f;
-  locale_weight["zh-cn"] = 0.12f;  // Normalized to lowercase.
-
   auto impl = base::MakeUnique<TranslateRankerImpl>(base::FilePath(), GURL(),
                                                     GetTestUkmRecorder());
   impl->OnModelAvailable(std::move(model));
@@ -197,18 +137,27 @@
 metrics::TranslateEventProto TranslateRankerImplTest::CreateTranslateEvent(
     const std::string& src_lang,
     const std::string& dst_lang,
+    const std::string& country,
     int accept_count,
     int decline_count,
     int ignore_count) {
   metrics::TranslateEventProto translate_event;
   translate_event.set_source_language(src_lang);
   translate_event.set_target_language(dst_lang);
+  translate_event.set_country(country);
   translate_event.set_accept_count(accept_count);
   translate_event.set_decline_count(decline_count);
   translate_event.set_ignore_count(ignore_count);
   return translate_event;
 }
 
+// static
+metrics::TranslateEventProto
+TranslateRankerImplTest::CreateDefaultTranslateEvent() {
+  return TranslateRankerImplTest::CreateTranslateEvent("en", "fr", "de", 50, 50,
+                                                       0);
+}
+
 }  // namespace
 
 TEST_F(TranslateRankerImplTest, GetVersion) {
@@ -228,7 +177,7 @@
 TEST_F(TranslateRankerImplTest, GetModelDecision) {
   InitFeatures({kTranslateRankerEnforcement}, {});
   // Calculate the score using: a 50:50 accept/decline ratio; the one-hot
-  // values for the src lang, dest lang, locale and counry; and, the bias.
+  // values for the src lang, dest lang, and country; and, the bias.
   double expected_score =
       Sigmoid(50.0 * 0.13f +   // accept count * weight
               50.0 * -0.14f +  // decline count * weight
@@ -239,90 +188,94 @@
               1.0 * 0.04f +    // one-hot src-language "en" * weight
               1.0 * 0.00f +    // one-hot dst-language "fr" * weight
               1.0 * 0.07f +    // one-hot country "de" * weight
-              1.0 * 0.12f +    // one-hot locale "zh-CN" * weight
               0.5f);           // bias
-  TranslateRankerFeatures features(50, 50, 0, "en", "fr", "de", "zh-CN");
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
 
   const float epsilon = 0.001f;
   auto ranker = GetRankerForTest(expected_score + epsilon);
-  EXPECT_FALSE(ranker->GetModelDecision(features));
+  EXPECT_FALSE(ranker->GetModelDecision(translate_event));
 
   ranker = GetRankerForTest(expected_score - epsilon);
-  EXPECT_TRUE(ranker->GetModelDecision(features));
+  EXPECT_TRUE(ranker->GetModelDecision(translate_event));
 
   ranker = GetRankerForTest(0.0);
-  EXPECT_EQ(expected_score >= 0.5, ranker->GetModelDecision(features));
+  EXPECT_EQ(expected_score >= 0.5, ranker->GetModelDecision(translate_event));
 }
 
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_AllEnabled) {
   InitFeatures({kTranslateRankerQuery, kTranslateRankerEnforcement,
                 kTranslateRankerDecisionOverride},
                {});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
 
   // With a threshold of 0.99, en->fr is not over the threshold.
-  EXPECT_FALSE(GetRankerForTest(0.99f)->ShouldOfferTranslation(
-      *translate_prefs_, "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(kModelVersion, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW, tep.ranker_response());
+  EXPECT_FALSE(
+      GetRankerForTest(0.99f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(kModelVersion, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW,
+            translate_event.ranker_response());
 
   // With a threshold of 0.01, en-fr is over the threshold.
-  tep.Clear();
-  EXPECT_TRUE(GetRankerForTest(0.01f)->ShouldOfferTranslation(
-      *translate_prefs_, "en", "fr", &tep));
-  EXPECT_EQ(metrics::TranslateEventProto::SHOW, tep.ranker_response());
+  translate_event.Clear();
+  EXPECT_TRUE(
+      GetRankerForTest(0.01f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_EQ(metrics::TranslateEventProto::SHOW,
+            translate_event.ranker_response());
 }
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_AllDisabled) {
   InitFeatures({}, {kTranslateRankerQuery, kTranslateRankerEnforcement,
                     kTranslateRankerDecisionOverride});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
   // If query and other flags are turned off, returns true and do not query the
   // ranker.
-  EXPECT_TRUE(GetRankerForTest(0.5f)->ShouldOfferTranslation(*translate_prefs_,
-                                                             "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(kModelVersion, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::NOT_QUERIED, tep.ranker_response());
+  EXPECT_TRUE(GetRankerForTest(0.5f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(kModelVersion, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::NOT_QUERIED,
+            translate_event.ranker_response());
 }
 
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_QueryOnly) {
   InitFeatures({kTranslateRankerQuery},
                {kTranslateRankerEnforcement, kTranslateRankerDecisionOverride});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
   // If enforcement is turned off, returns true even if the decision
   // is not to show.
-  EXPECT_TRUE(GetRankerForTest(0.99f)->ShouldOfferTranslation(
-      *translate_prefs_, "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(kModelVersion, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW, tep.ranker_response());
+  EXPECT_TRUE(
+      GetRankerForTest(0.99f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(kModelVersion, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW,
+            translate_event.ranker_response());
 }
 
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_EnforcementOnly) {
   InitFeatures({kTranslateRankerEnforcement},
                {kTranslateRankerQuery, kTranslateRankerDecisionOverride});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
   // If either enforcement or decision override are turned on, returns the
   // ranker decision.
-  EXPECT_FALSE(GetRankerForTest(0.99f)->ShouldOfferTranslation(
-      *translate_prefs_, "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(kModelVersion, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW, tep.ranker_response());
+  EXPECT_FALSE(
+      GetRankerForTest(0.99f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(kModelVersion, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW,
+            translate_event.ranker_response());
 }
 
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_OverrideOnly) {
   InitFeatures({kTranslateRankerDecisionOverride},
                {kTranslateRankerQuery, kTranslateRankerEnforcement});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
   // If either enforcement or decision override are turned on, returns the
   // ranker decision.
-  EXPECT_FALSE(GetRankerForTest(0.99f)->ShouldOfferTranslation(
-      *translate_prefs_, "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(kModelVersion, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW, tep.ranker_response());
+  EXPECT_FALSE(
+      GetRankerForTest(0.99f)->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(kModelVersion, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::DONT_SHOW,
+            translate_event.ranker_response());
 }
 
 TEST_F(TranslateRankerImplTest, ShouldOfferTranslation_NoModel) {
@@ -331,13 +284,13 @@
   InitFeatures({kTranslateRankerDecisionOverride, kTranslateRankerQuery,
                 kTranslateRankerEnforcement},
                {});
-  metrics::TranslateEventProto tep;
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
   // If we don't have a model, returns true.
-  EXPECT_TRUE(
-      ranker->ShouldOfferTranslation(*translate_prefs_, "en", "fr", &tep));
-  EXPECT_NE(0U, tep.ranker_request_timestamp_sec());
-  EXPECT_EQ(0U, tep.ranker_version());
-  EXPECT_EQ(metrics::TranslateEventProto::NOT_QUERIED, tep.ranker_response());
+  EXPECT_TRUE(ranker->ShouldOfferTranslation(&translate_event));
+  EXPECT_NE(0U, translate_event.ranker_request_timestamp_sec());
+  EXPECT_EQ(0U, translate_event.ranker_version());
+  EXPECT_EQ(metrics::TranslateEventProto::NOT_QUERIED,
+            translate_event.ranker_response());
 }
 
 TEST_F(TranslateRankerImplTest, RecordAndFlushEvents) {
@@ -351,18 +304,21 @@
   ranker->FlushTranslateEvents(&flushed_events);
   EXPECT_EQ(0U, flushed_events.size());
 
-  ranker->RecordTranslateEvent(0, url0, &tep1_);
-  ranker->RecordTranslateEvent(1, GURL(), &tep2_);
-  ranker->RecordTranslateEvent(2, url1, &tep3_);
+  ranker->RecordTranslateEvent(0, url0, &translate_event1_);
+  ranker->RecordTranslateEvent(1, GURL(), &translate_event2_);
+  ranker->RecordTranslateEvent(2, url1, &translate_event3_);
 
   // Capture the data and verify that it is as expected.
   ranker->FlushTranslateEvents(&flushed_events);
   EXPECT_EQ(3U, flushed_events.size());
-  ASSERT_EQ(tep1_.source_language(), flushed_events[0].source_language());
+  ASSERT_EQ(translate_event1_.source_language(),
+            flushed_events[0].source_language());
   ASSERT_EQ(0, flushed_events[0].event_type());
-  ASSERT_EQ(tep2_.source_language(), flushed_events[1].source_language());
+  ASSERT_EQ(translate_event2_.source_language(),
+            flushed_events[1].source_language());
   ASSERT_EQ(1, flushed_events[1].event_type());
-  ASSERT_EQ(tep3_.source_language(), flushed_events[2].source_language());
+  ASSERT_EQ(translate_event3_.source_language(),
+            flushed_events[2].source_language());
   ASSERT_EQ(2, flushed_events[2].event_type());
 
   // Check that the cache has been cleared.
@@ -386,9 +342,9 @@
   ranker->FlushTranslateEvents(&flushed_events);
   EXPECT_EQ(0U, flushed_events.size());
 
-  ranker->RecordTranslateEvent(0, GURL(), &tep1_);
-  ranker->RecordTranslateEvent(1, GURL(), &tep2_);
-  ranker->RecordTranslateEvent(2, GURL(), &tep3_);
+  ranker->RecordTranslateEvent(0, GURL(), &translate_event1_);
+  ranker->RecordTranslateEvent(1, GURL(), &translate_event2_);
+  ranker->RecordTranslateEvent(2, GURL(), &translate_event3_);
 
   // Logging is enabled by default, so events should be cached.
   ranker->FlushTranslateEvents(&flushed_events);
@@ -397,9 +353,9 @@
   // Override the feature setting to disable logging.
   ranker->EnableLogging(false);
 
-  ranker->RecordTranslateEvent(0, GURL(), &tep1_);
-  ranker->RecordTranslateEvent(1, GURL(), &tep2_);
-  ranker->RecordTranslateEvent(2, GURL(), &tep3_);
+  ranker->RecordTranslateEvent(0, GURL(), &translate_event1_);
+  ranker->RecordTranslateEvent(1, GURL(), &translate_event2_);
+  ranker->RecordTranslateEvent(2, GURL(), &translate_event3_);
 
   // Logging is disabled, so no events should be cached.
   ranker->FlushTranslateEvents(&flushed_events);
@@ -411,14 +367,16 @@
   std::unique_ptr<translate::TranslateRankerImpl> ranker =
       GetRankerForTest(0.0f);
   const int kEventType = 12;
-  metrics::TranslateEventProto tep = CreateTranslateEvent("fr", "en", 1, 0, 3);
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
 
-  EXPECT_FALSE(ranker->ShouldOverrideDecision(kEventType, GURL(), &tep));
+  EXPECT_FALSE(
+      ranker->ShouldOverrideDecision(kEventType, GURL(), &translate_event));
 
   std::vector<metrics::TranslateEventProto> flushed_events;
   ranker->FlushTranslateEvents(&flushed_events);
   EXPECT_EQ(1U, flushed_events.size());
-  ASSERT_EQ(tep.source_language(), flushed_events[0].source_language());
+  ASSERT_EQ(translate_event.source_language(),
+            flushed_events[0].source_language());
   ASSERT_EQ(kEventType, flushed_events[0].event_type());
 }
 
@@ -426,16 +384,16 @@
   InitFeatures({kTranslateRankerDecisionOverride}, {});
   std::unique_ptr<translate::TranslateRankerImpl> ranker =
       GetRankerForTest(0.0f);
-  metrics::TranslateEventProto tep = CreateTranslateEvent("fr", "en", 1, 0, 3);
+  metrics::TranslateEventProto translate_event = CreateDefaultTranslateEvent();
 
-  EXPECT_TRUE(ranker->ShouldOverrideDecision(1, GURL(), &tep));
-  EXPECT_TRUE(ranker->ShouldOverrideDecision(2, GURL(), &tep));
+  EXPECT_TRUE(ranker->ShouldOverrideDecision(1, GURL(), &translate_event));
+  EXPECT_TRUE(ranker->ShouldOverrideDecision(2, GURL(), &translate_event));
 
   std::vector<metrics::TranslateEventProto> flushed_events;
   ranker->FlushTranslateEvents(&flushed_events);
   EXPECT_EQ(0U, flushed_events.size());
-  ASSERT_EQ(2, tep.decision_overrides_size());
-  ASSERT_EQ(1, tep.decision_overrides(0));
-  ASSERT_EQ(2, tep.decision_overrides(1));
-  ASSERT_EQ(0, tep.event_type());
+  ASSERT_EQ(2, translate_event.decision_overrides_size());
+  ASSERT_EQ(1, translate_event.decision_overrides(0));
+  ASSERT_EQ(2, translate_event.decision_overrides(1));
+  ASSERT_EQ(0, translate_event.event_type());
 }
diff --git a/components/viz/frame_sinks/mojo_frame_sink_manager.cc b/components/viz/frame_sinks/mojo_frame_sink_manager.cc
index a41c1a4..3e7f681 100644
--- a/components/viz/frame_sinks/mojo_frame_sink_manager.cc
+++ b/components/viz/frame_sinks/mojo_frame_sink_manager.cc
@@ -129,6 +129,9 @@
 void MojoFrameSinkManager::OnSurfaceDamaged(const cc::SurfaceId& surface_id,
                                             bool* changed) {}
 
+void MojoFrameSinkManager::OnSurfaceDiscarded(const cc::SurfaceId& surface_id) {
+}
+
 void MojoFrameSinkManager::OnClientConnectionLost(
     const cc::FrameSinkId& frame_sink_id,
     bool destroy_compositor_frame_sink) {
diff --git a/components/viz/frame_sinks/mojo_frame_sink_manager.h b/components/viz/frame_sinks/mojo_frame_sink_manager.h
index 2539862..8495617 100644
--- a/components/viz/frame_sinks/mojo_frame_sink_manager.h
+++ b/components/viz/frame_sinks/mojo_frame_sink_manager.h
@@ -82,6 +82,7 @@
   void OnSurfaceCreated(const cc::SurfaceInfo& surface_info) override;
   void OnSurfaceDamaged(const cc::SurfaceId& surface_id,
                         bool* changed) override;
+  void OnSurfaceDiscarded(const cc::SurfaceId& surface_id) override;
 
   // GpuCompositorFrameSinkDelegate implementation.
   void OnClientConnectionLost(const cc::FrameSinkId& frame_sink_id,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e6dc149..e81b07b 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -11,12 +11,6 @@
 import("//third_party/WebKit/public/public_features.gni")
 import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
 
-declare_args() {
-  # Include code in the build that is only needed when using the video
-  # capture Mojo service, which is currently experimental.
-  enable_mojo_video_capture = false
-}
-
 source_set("browser") {
   # Only the public target should depend on this. All other targets (even
   # internal content ones) should depend on the public one.
@@ -131,6 +125,8 @@
     "//services/shape_detection/public/interfaces",
     "//services/ui/gpu/interfaces",
     "//services/ui/public/cpp/gpu",
+    "//services/video_capture/public/cpp",
+    "//services/video_capture/public/interfaces:constants",
     "//skia",
     "//sql",
     "//storage/browser",
@@ -1233,6 +1229,12 @@
     "renderer_host/media/renderer_audio_output_stream_factory_context.h",
     "renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc",
     "renderer_host/media/renderer_audio_output_stream_factory_context_impl.h",
+    "renderer_host/media/service_launched_video_capture_device.cc",
+    "renderer_host/media/service_launched_video_capture_device.h",
+    "renderer_host/media/service_video_capture_device_launcher.cc",
+    "renderer_host/media/service_video_capture_device_launcher.h",
+    "renderer_host/media/service_video_capture_provider.cc",
+    "renderer_host/media/service_video_capture_provider.h",
     "renderer_host/media/video_capture_controller.cc",
     "renderer_host/media/video_capture_controller.h",
     "renderer_host/media/video_capture_controller_event_handler.h",
@@ -1244,6 +1246,8 @@
     "renderer_host/media/video_capture_manager.cc",
     "renderer_host/media/video_capture_manager.h",
     "renderer_host/media/video_capture_provider.h",
+    "renderer_host/media/video_capture_provider_switcher.cc",
+    "renderer_host/media/video_capture_provider_switcher.h",
     "renderer_host/native_web_keyboard_event_aura.cc",
     "renderer_host/native_web_keyboard_event_mac.mm",
     "renderer_host/offscreen_canvas_provider_impl.cc",
@@ -1629,22 +1633,6 @@
     ]
   }
 
-  if (enable_mojo_video_capture) {
-    sources += [
-      "renderer_host/media/service_launched_video_capture_device.cc",
-      "renderer_host/media/service_launched_video_capture_device.h",
-      "renderer_host/media/service_video_capture_device_launcher.cc",
-      "renderer_host/media/service_video_capture_device_launcher.h",
-      "renderer_host/media/service_video_capture_provider.cc",
-      "renderer_host/media/service_video_capture_provider.h",
-    ]
-
-    deps += [
-      "//services/video_capture/public/cpp",
-      "//services/video_capture/public/interfaces:constants",
-    ]
-  }
-
   # Desktop screen capture implementations, conditionally built depending on
   # the available implementations for each platform.
   if (is_linux || is_mac || is_win) {
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index 5542a6a..3257869 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -5132,9 +5132,6 @@
   if (owner()->HasState(ui::AX_STATE_EDITABLE))
     ia2_state |= IA2_STATE_EDITABLE;
 
-  if (owner()->HasAction(ui::AX_ACTION_SET_VALUE))
-    ia2_state |= IA2_STATE_EDITABLE;
-
   if (!owner()->GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
     ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
 
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index 264a86b..6a197ca 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -389,8 +389,11 @@
 
   // Fire any events related to changes to the tree.
   for (auto& event : tree_events_) {
+    BrowserAccessibility* event_target = GetFromID(event.second);
+    if (!event_target)
+      continue;
     NotifyAccessibilityEvent(BrowserAccessibilityEvent::FromTreeChange,
-                             event.first, event.second);
+                             event.first, event_target);
   }
   tree_events_.clear();
 
@@ -1190,11 +1193,12 @@
     DCHECK(created_node);
     BrowserAccessibility* object = GetFromAXNode(created_node);
     if (object && object->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) {
+      int32_t id = object->GetId();
       if (object->GetRole() == ui::AX_ROLE_ALERT) {
-        tree_events_.push_back(std::make_pair(ui::AX_EVENT_ALERT, object));
+        tree_events_.push_back(std::make_pair(ui::AX_EVENT_ALERT, id));
       } else {
         tree_events_.push_back(
-            std::make_pair(ui::AX_EVENT_LIVE_REGION_CREATED, object));
+            std::make_pair(ui::AX_EVENT_LIVE_REGION_CREATED, id));
       }
     }
   }
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 6bd0d1b..3f7c5ca 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -441,10 +441,9 @@
   // A mapping from a node id to its wrapper of type BrowserAccessibility.
   base::hash_map<int32_t, BrowserAccessibility*> id_wrapper_map_;
 
-  // A list of accessibility events to fire based on changes to the
-  // accessibility tree. Only used within the scope of one call to
-  // OnAccessibilityEvents, so it's safe to store raw pointers.
-  std::vector<std::pair<ui::AXEvent, BrowserAccessibility*>> tree_events_;
+  // A queue of accessibility events to fire based on changes to the
+  // accessibility tree. Each one is an event and a node id.
+  std::vector<std::pair<ui::AXEvent, int32_t>> tree_events_;
 
   // True if the user has initiated a navigation to another page.
   bool user_is_navigating_away_;
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.cc b/content/browser/renderer_host/input/synthetic_gesture_controller.cc
index 1ab65e7..f6503e8 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller.cc
@@ -41,18 +41,41 @@
 }
 
 void SyntheticGestureController::RequestBeginFrame() {
+  DCHECK(!dispatch_timer_.IsRunning());
   delegate_->RequestBeginFrameForSynthesizedInput(
       base::BindOnce(&SyntheticGestureController::OnBeginFrame,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
 void SyntheticGestureController::OnBeginFrame() {
-  // TODO(sad): Instead of dispatching the events immediately, dispatch after an
-  // offset.
-  DispatchNextEvent();
+  // In order to make sure we get consistent results across runs, we attempt to
+  // start the timer at a fixed offset from the vsync. Starting the timer
+  // shortly after a begin-frame is likely to produce latency close to the worst
+  // cases. We feel 2 milliseconds is a good offset for this.
+  constexpr base::TimeDelta kSynthesizedDispatchDelay =
+      base::TimeDelta::FromMilliseconds(2);
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&SyntheticGestureController::StartTimer,
+                     weak_ptr_factory_.GetWeakPtr()),
+      kSynthesizedDispatchDelay);
+}
+
+void SyntheticGestureController::StartTimer() {
+  // TODO(sad): Change the interval to allow sending multiple events per begin
+  // frame.
+  dispatch_timer_.Start(
+      FROM_HERE, base::TimeDelta::FromMicroseconds(16666),
+      base::BindRepeating(
+          [](base::WeakPtr<SyntheticGestureController> weak_ptr) {
+            if (weak_ptr)
+              weak_ptr->DispatchNextEvent(base::TimeTicks::Now());
+          },
+          weak_ptr_factory_.GetWeakPtr()));
 }
 
 bool SyntheticGestureController::DispatchNextEvent(base::TimeTicks timestamp) {
+  DCHECK(dispatch_timer_.IsRunning());
   TRACE_EVENT0("input", "SyntheticGestureController::Flush");
   if (pending_gesture_queue_.IsEmpty())
     return false;
@@ -63,23 +86,22 @@
             timestamp, gesture_target_.get());
 
     if (result == SyntheticGesture::GESTURE_RUNNING) {
-      RequestBeginFrame();
       return true;
     }
     pending_gesture_queue_.mark_current_gesture_complete(result);
   }
 
-  if (!delegate_->HasGestureStopped()) {
-    RequestBeginFrame();
+  if (!delegate_->HasGestureStopped())
     return true;
-  }
 
   StopGesture(*pending_gesture_queue_.FrontGesture(),
               pending_gesture_queue_.FrontCallback(),
               pending_gesture_queue_.current_gesture_result());
   pending_gesture_queue_.Pop();
-  if (pending_gesture_queue_.IsEmpty())
+  if (pending_gesture_queue_.IsEmpty()) {
+    dispatch_timer_.Stop();
     return false;
+  }
   StartGesture(*pending_gesture_queue_.FrontGesture());
   return true;
 }
@@ -88,7 +110,8 @@
   TRACE_EVENT_ASYNC_BEGIN0("input,benchmark",
                            "SyntheticGestureController::running",
                            &gesture);
-  RequestBeginFrame();
+  if (!dispatch_timer_.IsRunning())
+    RequestBeginFrame();
 }
 
 void SyntheticGestureController::StopGesture(
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.h b/content/browser/renderer_host/input/synthetic_gesture_controller.h
index ed11a5ad..1762300 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller.h
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "content/browser/renderer_host/input/synthetic_gesture.h"
 #include "content/common/content_export.h"
 #include "content/common/input/synthetic_gesture_params.h"
@@ -54,8 +55,11 @@
   bool DispatchNextEvent(base::TimeTicks = base::TimeTicks::Now());
 
  private:
+  friend class SyntheticGestureControllerTestBase;
+
   void RequestBeginFrame();
   void OnBeginFrame();
+  void StartTimer();
 
   void StartGesture(const SyntheticGesture& gesture);
   void StopGesture(const SyntheticGesture& gesture,
@@ -111,6 +115,7 @@
     DISALLOW_COPY_AND_ASSIGN(GestureAndCallbackQueue);
   } pending_gesture_queue_;
 
+  base::RepeatingTimer dispatch_timer_;
   base::WeakPtrFactory<SyntheticGestureController> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SyntheticGestureController);
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 3ebe916..4483b36 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "content/browser/renderer_host/input/synthetic_gesture.h"
 #include "content/browser/renderer_host/input/synthetic_gesture_target.h"
@@ -675,6 +676,8 @@
   DISALLOW_COPY_AND_ASSIGN(DummySyntheticGestureControllerDelegate);
 };
 
+}  // namespace
+
 class SyntheticGestureControllerTestBase {
  public:
   SyntheticGestureControllerTestBase() {}
@@ -697,9 +700,15 @@
   }
 
   void FlushInputUntilComplete() {
+    // Start and stop the timer explicitly here, since the test does not need to
+    // wait for begin-frame to start the timer.
+    controller_->dispatch_timer_.Start(FROM_HERE,
+                                       base::TimeDelta::FromSeconds(1),
+                                       base::Bind(&base::DoNothing));
     do
       time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
     while (controller_->DispatchNextEvent(time_));
+    controller_->dispatch_timer_.Stop();
   }
 
   void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
@@ -712,6 +721,7 @@
 
   base::TimeDelta GetTotalTime() const { return time_ - start_time_; }
 
+  base::test::ScopedTaskEnvironment env_;
   MockSyntheticGestureTarget* target_;
   DummySyntheticGestureControllerDelegate delegate_;
   std::unique_ptr<SyntheticGestureController> controller_;
@@ -845,9 +855,7 @@
   QueueSyntheticGesture(std::move(gesture_1));
   QueueSyntheticGesture(std::move(gesture_2));
 
-  do {
-    time_ += base::TimeDelta::FromMilliseconds(kFlushInputRateInMs);
-  } while (controller_->DispatchNextEvent(time_));
+  FlushInputUntilComplete();
   EXPECT_EQ(2, num_success_);
 }
 
@@ -1761,6 +1769,4 @@
       pointer_mouse_target->SyntheticMouseActionDispatchedCorrectly(param, 1));
 }
 
-}  // namespace
-
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index b6011c3..71546d6 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -33,7 +33,9 @@
 #include "content/browser/renderer_host/media/media_devices_manager.h"
 #include "content/browser/renderer_host/media/media_stream_requester.h"
 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
+#include "content/browser/renderer_host/media/service_video_capture_provider.h"
 #include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/browser/renderer_host/media/video_capture_provider_switcher.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -52,6 +54,7 @@
 #include "media/base/media_switches.h"
 #include "media/capture/video/video_capture_device_factory.h"
 #include "media/capture/video/video_capture_system_impl.h"
+#include "services/video_capture/public/cpp/constants.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -424,6 +427,11 @@
             media::VideoCaptureDeviceFactory::CreateFactory(
                 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI))),
         std::move(device_task_runner));
+    if (base::FeatureList::IsEnabled(video_capture::kMojoVideoCapture)) {
+      video_capture_provider = base::MakeUnique<VideoCaptureProviderSwitcher>(
+          base::MakeUnique<ServiceVideoCaptureProvider>(),
+          std::move(video_capture_provider));
+    }
   }
   InitializeMaybeAsync(std::move(video_capture_provider));
 
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
index b74cf52..4c86c44 100644
--- a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
+++ b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
@@ -88,9 +88,12 @@
     return;
   }
   video_capture::mojom::DevicePtr device;
+  // We need the temporary variable |device_request| in order to guarantee that
+  // mojo::MakeRequest(&device) happens before base::Passed(&device).
+  auto device_request = mojo::MakeRequest(&device);
   (*device_factory_)
       ->CreateDevice(
-          device_id, mojo::MakeRequest(&device),
+          device_id, std::move(device_request),
           base::Bind(
               // Use of Unretained |this| is safe, because |done_cb| guarantees
               // that |this| stays alive.
diff --git a/content/browser/renderer_host/media/video_capture_browsertest.cc b/content/browser/renderer_host/media/video_capture_browsertest.cc
index 19ce4c6..e4c37d1 100644
--- a/content/browser/renderer_host/media/video_capture_browsertest.cc
+++ b/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -14,16 +14,22 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/media_switches.h"
 #include "media/capture/video_capture_types.h"
+#include "services/video_capture/public/cpp/constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using testing::_;
 using testing::AtLeast;
+using testing::Bool;
+using testing::Combine;
 using testing::Invoke;
 using testing::InvokeWithoutArgs;
 using testing::Values;
 
 namespace content {
 
+static const char kFakeDeviceFactoryConfigString[] = "device-count=3";
+static const float kFrameRateToRequest = 15.0f;
+
 class MockVideoCaptureControllerEventHandler
     : public VideoCaptureControllerEventHandler {
  public:
@@ -59,13 +65,33 @@
   MOCK_METHOD2(Aborted, void(MediaStreamType, int));
 };
 
+using DeviceIndex = size_t;
+using Resolution = gfx::Size;
+using ExerciseAcceleratedJpegDecoding = bool;
+using UseMojoService = bool;
+
+// For converting the std::tuple<> used as test parameters back to something
+// human-readable.
 struct TestParams {
-  std::string fake_device_factory_config_string;
+  TestParams() : device_index_to_use(0u) {}
+  TestParams(const std::tuple<DeviceIndex,
+                              Resolution,
+                              ExerciseAcceleratedJpegDecoding,
+                              UseMojoService>& params)
+      : device_index_to_use(std::get<0>(params)),
+        resolution_to_use(std::get<1>(params)),
+        exercise_accelerated_jpeg_decoding(std::get<2>(params)),
+        use_mojo_service(std::get<3>(params)) {}
+
+  media::VideoPixelFormat GetPixelFormatToUse() {
+    return (device_index_to_use == 1u) ? media::PIXEL_FORMAT_Y16
+                                       : media::PIXEL_FORMAT_I420;
+  }
+
   size_t device_index_to_use;
-  media::VideoPixelFormat pixel_format_to_use;
   gfx::Size resolution_to_use;
-  float frame_rate_to_use;
   bool exercise_accelerated_jpeg_decoding;
+  bool use_mojo_service;
 };
 
 struct FrameInfo {
@@ -75,10 +101,17 @@
   base::TimeDelta timestamp;
 };
 
-class VideoCaptureBrowserTest
-    : public ContentBrowserTest,
-      public ::testing::WithParamInterface<TestParams> {
+// Integration test that exercises the VideoCaptureManager instance running in
+// the Browser process.
+class VideoCaptureBrowserTest : public ContentBrowserTest,
+                                public ::testing::WithParamInterface<
+                                    std::tuple<DeviceIndex,
+                                               Resolution,
+                                               ExerciseAcceleratedJpegDecoding,
+                                               UseMojoService>> {
  public:
+  VideoCaptureBrowserTest() { params_ = TestParams(GetParam()); }
+
   void SetUpAndStartCaptureDeviceOnIOThread(base::Closure continuation) {
     video_capture_manager_ = media_stream_manager_->video_capture_manager();
     ASSERT_TRUE(video_capture_manager_);
@@ -90,7 +123,7 @@
 
   void TearDownCaptureDeviceOnIOThread(base::Closure continuation,
                                        bool post_to_end_of_message_queue) {
-    // StopCaptureForClient must not be called synchronously from either the
+    // DisconnectClient() must not be called synchronously from either the
     // |done_cb| passed to StartCaptureForClient() nor any callback made to a
     // VideoCaptureControllerEventHandler. To satisfy this, we have to post our
     // invocation to the end of the IO message queue.
@@ -114,17 +147,20 @@
 
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(
-        switches::kUseFakeDeviceForMediaStream,
-        GetParam().fake_device_factory_config_string);
+    command_line->AppendSwitchASCII(switches::kUseFakeDeviceForMediaStream,
+                                    kFakeDeviceFactoryConfigString);
     command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
-    if (GetParam().exercise_accelerated_jpeg_decoding) {
+    if (params_.exercise_accelerated_jpeg_decoding) {
       base::CommandLine::ForCurrentProcess()->AppendSwitch(
           switches::kUseFakeJpegDecodeAccelerator);
     } else {
       base::CommandLine::ForCurrentProcess()->AppendSwitch(
           switches::kDisableAcceleratedMjpegDecode);
     }
+    if (params_.use_mojo_service) {
+      base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+          switches::kEnableFeatures, video_capture::kMojoVideoCapture.name);
+    }
   }
 
   // This cannot be part of an override of SetUp(), because at the time when
@@ -139,16 +175,16 @@
   void OnDeviceDescriptorsReceived(
       base::Closure continuation,
       const media::VideoCaptureDeviceDescriptors& descriptors) {
-    ASSERT_TRUE(GetParam().device_index_to_use < descriptors.size());
-    const auto& descriptor = descriptors[GetParam().device_index_to_use];
+    ASSERT_TRUE(params_.device_index_to_use < descriptors.size());
+    const auto& descriptor = descriptors[params_.device_index_to_use];
     MediaStreamDevice media_stream_device(
         MEDIA_DEVICE_VIDEO_CAPTURE, descriptor.device_id,
         descriptor.display_name, descriptor.facing);
     session_id_ = video_capture_manager_->Open(media_stream_device);
     media::VideoCaptureParams capture_params;
     capture_params.requested_format = media::VideoCaptureFormat(
-        GetParam().resolution_to_use, GetParam().frame_rate_to_use,
-        GetParam().pixel_format_to_use);
+        params_.resolution_to_use, kFrameRateToRequest,
+        params_.GetPixelFormatToUse());
     video_capture_manager_->ConnectClient(
         session_id_, capture_params, stub_client_id_,
         &mock_controller_event_handler_,
@@ -167,6 +203,7 @@
   }
 
  protected:
+  TestParams params_;
   MediaStreamManager* media_stream_manager_ = nullptr;
   VideoCaptureManager* video_capture_manager_ = nullptr;
   int session_id_ = 0;
@@ -177,6 +214,19 @@
 };
 
 IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest, StartAndImmediatelyStop) {
+#if defined(OS_ANDROID)
+  // Mojo video capture is currently not supported on Android.
+  // TODO(chfremer): Remove this as soon as https://crbug.com/720500 is
+  // resolved.
+  if (params_.use_mojo_service)
+    return;
+#endif
+  // Mojo video capture currently does not support accelerated jpeg decoding.
+  // TODO(chfremer): Remove this as soon as https://crbug.com/720604 is
+  // resolved.
+  if (params_.use_mojo_service && params_.exercise_accelerated_jpeg_decoding)
+    return;
+
   SetUpRequiringBrowserMainLoopOnMainThread();
   base::RunLoop run_loop;
   auto quit_run_loop_on_current_thread_cb =
@@ -194,12 +244,32 @@
 
 IN_PROC_BROWSER_TEST_P(VideoCaptureBrowserTest,
                        ReceiveFramesFromFakeCaptureDevice) {
-// TODO(chfremer): This test case is flaky on Android. Find out cause of
-// flakiness and then re-enable. See crbug.com/709039.
 #if defined(OS_ANDROID)
-  if (GetParam().exercise_accelerated_jpeg_decoding)
+  // TODO(chfremer): This test case is flaky on Android. Find out cause of
+  // flakiness and then re-enable. See https://crbug.com/709039.
+  if (params_.exercise_accelerated_jpeg_decoding)
+    return;
+  // Mojo video capture is currently not supported on Android
+  // TODO(chfremer): Remove this as soon as https://crbug.com/720500 is
+  // resolved.
+  if (params_.use_mojo_service)
     return;
 #endif
+  // Mojo video capture currently does not support accelerated jpeg decoding.
+  // TODO(chfremer): Remove this as soon as https://crbug.com/720604 is
+  // resolved.
+  if (params_.use_mojo_service && params_.exercise_accelerated_jpeg_decoding)
+    return;
+  // Only fake device with index 2 delivers MJPEG.
+  if (params_.exercise_accelerated_jpeg_decoding &&
+      params_.device_index_to_use != 2)
+    return;
+  // There is an intermittent use-after-free in GpuChannelHost::Send() during
+  // Browser shutdown, which causes MSan tests to fail.
+  // TODO(chfremer): Remove this as soon as https://crbug.com/725271 is
+  // resolved.
+  if (params_.exercise_accelerated_jpeg_decoding)
+    return;
 
   SetUpRequiringBrowserMainLoopOnMainThread();
 
@@ -216,7 +286,7 @@
                  std::move(quit_run_loop_on_current_thread_cb), true);
 
   bool must_wait_for_gpu_decode_to_start = false;
-  if (GetParam().exercise_accelerated_jpeg_decoding) {
+  if (params_.exercise_accelerated_jpeg_decoding) {
     // Since the GPU jpeg decoder is created asynchronously while decoding
     // in software is ongoing, we have to keep pushing frames until a message
     // arrives that tells us that the GPU decoder is being used. Otherwise,
@@ -266,9 +336,9 @@
   base::TimeDelta previous_timestamp;
   bool first_frame = true;
   for (const auto& frame_info : received_frame_infos) {
-    EXPECT_EQ(GetParam().pixel_format_to_use, frame_info.pixel_format);
+    EXPECT_EQ(params_.GetPixelFormatToUse(), frame_info.pixel_format);
     EXPECT_EQ(media::PIXEL_STORAGE_CPU, frame_info.storage_type);
-    EXPECT_EQ(GetParam().resolution_to_use, frame_info.size);
+    EXPECT_EQ(params_.resolution_to_use, frame_info.size);
     // Timestamps are expected to increase
     if (!first_frame)
       EXPECT_GT(frame_info.timestamp, previous_timestamp);
@@ -277,20 +347,12 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(
-    ,
-    VideoCaptureBrowserTest,
-    Values(TestParams{"fps=25,device-count=2", 0, media::PIXEL_FORMAT_I420,
-                      gfx::Size(1280, 720), 25.0f, false},
-           // The 2nd device outputs Y16
-           TestParams{"fps=25,device-count=2", 1, media::PIXEL_FORMAT_Y16,
-                      gfx::Size(1280, 720), 25.0f, false},
-           TestParams{"fps=15,device-count=2", 1, media::PIXEL_FORMAT_Y16,
-                      gfx::Size(640, 480), 15.0f, false},
-           // The 3rd device outputs MJPEG, which is converted to I420.
-           TestParams{"fps=15,device-count=3", 2, media::PIXEL_FORMAT_I420,
-                      gfx::Size(640, 480), 25.0f, false},
-           TestParams{"fps=6,device-count=3", 2, media::PIXEL_FORMAT_I420,
-                      gfx::Size(640, 480), 6.0f, true}));
+INSTANTIATE_TEST_CASE_P(,
+                        VideoCaptureBrowserTest,
+                        Combine(Values(0, 1, 2),             // DeviceIndex
+                                Values(gfx::Size(640, 480),  // Resolution
+                                       gfx::Size(1280, 720)),
+                                Bool(),    // ExerciseAcceleratedJpegDecoding
+                                Bool()));  // UseMojoService
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_provider.h b/content/browser/renderer_host/media/video_capture_provider.h
index f0b72bb..10135040 100644
--- a/content/browser/renderer_host/media/video_capture_provider.h
+++ b/content/browser/renderer_host/media/video_capture_provider.h
@@ -68,8 +68,13 @@
                                               base::OnceClosure done_cb) = 0;
 };
 
+// Note: GetDeviceInfosAsync is only relevant for devices with
+// MediaStreamType == MEDIA_DEVICE_VIDEO_CAPTURE, i.e. camera devices.
 class CONTENT_EXPORT VideoCaptureProvider {
  public:
+  using GetDeviceInfosCallback =
+      base::Callback<void(const std::vector<media::VideoCaptureDeviceInfo>&)>;
+
   virtual ~VideoCaptureProvider() {}
 
   virtual void Uninitialize() = 0;
@@ -77,9 +82,7 @@
   // The passed-in |result_callback| must guarantee that the called
   // instance stays alive until |result_callback| is invoked.
   virtual void GetDeviceInfosAsync(
-      const base::Callback<
-          void(const std::vector<media::VideoCaptureDeviceInfo>&)>&
-          result_callback) = 0;
+      const GetDeviceInfosCallback& result_callback) = 0;
 
   virtual std::unique_ptr<VideoCaptureDeviceLauncher>
   CreateDeviceLauncher() = 0;
diff --git a/content/browser/renderer_host/media/video_capture_provider_switcher.cc b/content/browser/renderer_host/media/video_capture_provider_switcher.cc
new file mode 100644
index 0000000..eaeb799
--- /dev/null
+++ b/content/browser/renderer_host/media/video_capture_provider_switcher.cc
@@ -0,0 +1,88 @@
+// 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 "content/browser/renderer_host/media/video_capture_provider_switcher.h"
+
+#include "base/callback_helpers.h"
+
+namespace content {
+
+namespace {
+
+class VideoCaptureDeviceLauncherSwitcher : public VideoCaptureDeviceLauncher {
+ public:
+  VideoCaptureDeviceLauncherSwitcher(
+      std::unique_ptr<VideoCaptureDeviceLauncher> media_device_launcher,
+      std::unique_ptr<VideoCaptureDeviceLauncher> other_types_launcher)
+      : media_device_launcher_(std::move(media_device_launcher)),
+        other_types_launcher_(std::move(other_types_launcher)) {}
+
+  ~VideoCaptureDeviceLauncherSwitcher() override {}
+
+  void LaunchDeviceAsync(const std::string& device_id,
+                         MediaStreamType stream_type,
+                         const media::VideoCaptureParams& params,
+                         base::WeakPtr<media::VideoFrameReceiver> receiver,
+                         Callbacks* callbacks,
+                         base::OnceClosure done_cb) override {
+    if (stream_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
+      // Use of Unretained() is safe, because |media_device_launcher_| is owned
+      // by |this|.
+      abort_launch_cb_ =
+          base::Bind(&VideoCaptureDeviceLauncher::AbortLaunch,
+                     base::Unretained(media_device_launcher_.get()));
+      return media_device_launcher_->LaunchDeviceAsync(
+          device_id, stream_type, params, std::move(receiver), callbacks,
+          std::move(done_cb));
+    }
+    // Use of Unretained() is safe, because |other_types_launcher_| is owned by
+    // |this|.
+    abort_launch_cb_ =
+        base::Bind(&VideoCaptureDeviceLauncher::AbortLaunch,
+                   base::Unretained(other_types_launcher_.get()));
+    return other_types_launcher_->LaunchDeviceAsync(
+        device_id, stream_type, params, std::move(receiver), callbacks,
+        std::move(done_cb));
+  }
+
+  void AbortLaunch() override {
+    if (abort_launch_cb_.is_null())
+      return;
+    base::ResetAndReturn(&abort_launch_cb_).Run();
+  }
+
+ private:
+  const std::unique_ptr<VideoCaptureDeviceLauncher> media_device_launcher_;
+  const std::unique_ptr<VideoCaptureDeviceLauncher> other_types_launcher_;
+  base::OnceClosure abort_launch_cb_;
+};
+
+}  // anonymous namespace
+
+VideoCaptureProviderSwitcher::VideoCaptureProviderSwitcher(
+    std::unique_ptr<VideoCaptureProvider> media_device_capture_provider,
+    std::unique_ptr<VideoCaptureProvider> other_types_capture_provider)
+    : media_device_capture_provider_(std::move(media_device_capture_provider)),
+      other_types_capture_provider_(std::move(other_types_capture_provider)) {}
+
+VideoCaptureProviderSwitcher::~VideoCaptureProviderSwitcher() = default;
+
+void VideoCaptureProviderSwitcher::Uninitialize() {
+  media_device_capture_provider_->Uninitialize();
+  other_types_capture_provider_->Uninitialize();
+}
+
+void VideoCaptureProviderSwitcher::GetDeviceInfosAsync(
+    const GetDeviceInfosCallback& result_callback) {
+  media_device_capture_provider_->GetDeviceInfosAsync(result_callback);
+}
+
+std::unique_ptr<VideoCaptureDeviceLauncher>
+VideoCaptureProviderSwitcher::CreateDeviceLauncher() {
+  return base::MakeUnique<VideoCaptureDeviceLauncherSwitcher>(
+      media_device_capture_provider_->CreateDeviceLauncher(),
+      other_types_capture_provider_->CreateDeviceLauncher());
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_provider_switcher.h b/content/browser/renderer_host/media/video_capture_provider_switcher.h
new file mode 100644
index 0000000..c3207597
--- /dev/null
+++ b/content/browser/renderer_host/media/video_capture_provider_switcher.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_PROVIDER_SWITCHER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_PROVIDER_SWITCHER_H_
+
+#include "content/browser/renderer_host/media/video_capture_provider.h"
+#include "services/video_capture/public/interfaces/device_factory.mojom.h"
+
+namespace content {
+
+// Routes requests for media devices, e.g. cameras, to
+// |media_device_capture_provider| and for all other types of capture, e.g.
+// screen or tab capture, to the given |other_types_capture_provider|.
+class CONTENT_EXPORT VideoCaptureProviderSwitcher
+    : public VideoCaptureProvider {
+ public:
+  VideoCaptureProviderSwitcher(
+      std::unique_ptr<VideoCaptureProvider> media_device_capture_provider,
+      std::unique_ptr<VideoCaptureProvider> other_types_capture_provider);
+  ~VideoCaptureProviderSwitcher() override;
+
+  void Uninitialize() override;
+
+  void GetDeviceInfosAsync(
+      const GetDeviceInfosCallback& result_callback) override;
+
+  std::unique_ptr<VideoCaptureDeviceLauncher> CreateDeviceLauncher() override;
+
+ private:
+  const std::unique_ptr<VideoCaptureProvider> media_device_capture_provider_;
+  const std::unique_ptr<VideoCaptureProvider> other_types_capture_provider_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_PROVIDER_SWITCHER_H_
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 73b9c15..466629c 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -290,6 +290,8 @@
   void OnSurfaceDamaged(const cc::SurfaceId& id, bool* changed) override {
     *changed = true;
   }
+
+  void OnSurfaceDiscarded(const cc::SurfaceId& id) override {}
 };
 
 class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 19a1c5d..cc351b63 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/json/json_reader.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
@@ -52,6 +53,8 @@
 #include "services/service_manager/runner/common/client_util.h"
 #include "services/service_manager/service_manager.h"
 #include "services/shape_detection/public/interfaces/constants.mojom.h"
+#include "services/video_capture/public/cpp/constants.h"
+#include "services/video_capture/public/interfaces/constants.mojom.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/jni_android.h"
@@ -364,6 +367,11 @@
         std::make_pair(content::mojom::kNetworkServiceName,
                        base::ASCIIToUTF16("Network Service")));
   }
+  if (base::FeatureList::IsEnabled(video_capture::kMojoVideoCapture)) {
+    unsandboxed_services.insert(
+        std::make_pair(video_capture::mojom::kServiceName,
+                       base::ASCIIToUTF16("Video Capture Service")));
+  }
 
   for (const auto& service : unsandboxed_services) {
     packaged_services_connection_->AddServiceRequestHandler(
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index e8a49ca..baafcde 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -39,6 +39,7 @@
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
+#include "media/base/media_switches.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "ui/base/ui_base_switches.h"
@@ -312,6 +313,8 @@
 #if defined(OS_MACOSX)
       switches::kEnableSandboxLogging,
 #endif
+      switches::kUseFakeDeviceForMediaStream,
+      switches::kUseFileForFakeVideoCapture,
     };
     cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
                                arraysize(kSwitchNames));
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
index 318f220..8799488 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -819,6 +819,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "crbug.com/725532")
     @Feature({"TextInput", "Main"})
     public void testFinishComposingText() throws Throwable {
         mRule.focusElementAndWaitForStateUpdate("textarea");
@@ -1155,6 +1156,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "crbug.com/725532")
     @Feature({"TextInput", "Main"})
     public void testNavigateTextWithDpadKeyCodes() throws Throwable {
         mRule.focusElementAndWaitForStateUpdate("textarea");
diff --git a/content/public/app/BUILD.gn b/content/public/app/BUILD.gn
index c6a5990..9c9aba4 100644
--- a/content/public/app/BUILD.gn
+++ b/content/public/app/BUILD.gn
@@ -187,6 +187,7 @@
     "//services/device:manifest",
     "//services/resource_coordinator:manifest",
     "//services/shape_detection:manifest",
+    "//services/video_capture:manifest",
   ]
 }
 
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 6f051c5..198a8e38 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -84,7 +84,8 @@
           "text_detection"
 
         ],
-        "resource_coordinator": [ "coordination_unit" ]
+        "resource_coordinator": [ "coordination_unit" ],
+        "video_capture": [ "capture" ]
       }
     },
     "navigation:frame": {
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index 8a26132..dc33ded 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -64,7 +64,7 @@
 using DownloadOpenDelayedCallback = base::Callback<void(bool)>;
 
 // Called with the result of CheckForFileExistence().
-using CheckForFileExistenceCallback = base::Callback<void(bool result)>;
+using CheckForFileExistenceCallback = base::OnceCallback<void(bool result)>;
 
 using DownloadIdCallback = base::Callback<void(uint32_t)>;
 
@@ -152,9 +152,8 @@
   virtual void ShowDownloadInShell(DownloadItem* download) {}
 
   // Checks whether a downloaded file still exists.
-  virtual void CheckForFileExistence(
-      DownloadItem* download,
-      const CheckForFileExistenceCallback& callback) {}
+  virtual void CheckForFileExistence(DownloadItem* download,
+                                     CheckForFileExistenceCallback callback) {}
 
   // Return a GUID string used for identifying the application to the system AV
   // function for scanning downloaded files. If no GUID is provided or if the
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 10426faf..58726bd 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -785,6 +785,7 @@
     "//services/service_manager/public/cpp",
     "//services/ui/gpu/interfaces",
     "//services/ui/public/cpp/gpu",
+    "//services/video_capture/public/cpp",
     "//storage/browser",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/content/utility/BUILD.gn b/content/utility/BUILD.gn
index 0de44b4..c5d9450 100644
--- a/content/utility/BUILD.gn
+++ b/content/utility/BUILD.gn
@@ -46,6 +46,8 @@
     "//services/service_manager/public/interfaces",
     "//services/shape_detection:lib",
     "//services/shape_detection/public/interfaces",
+    "//services/video_capture:lib",
+    "//services/video_capture/public/interfaces:constants",
     "//third_party/WebKit/public:blink_headers",
     "//third_party/WebKit/public:mojo_bindings",
     "//url",
diff --git a/content/utility/DEPS b/content/utility/DEPS
index 95eef3e..1e371033 100644
--- a/content/utility/DEPS
+++ b/content/utility/DEPS
@@ -6,5 +6,6 @@
   "+services/data_decoder",
   "+services/service_manager",
   "+services/shape_detection",
+  "+services/video_capture",
   "+sandbox/win/src",
 ]
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc
index 2420c557..2f95ab6 100644
--- a/content/utility/utility_service_factory.cc
+++ b/content/utility/utility_service_factory.cc
@@ -19,11 +19,21 @@
 #include "services/data_decoder/public/interfaces/constants.mojom.h"
 #include "services/shape_detection/public/interfaces/constants.mojom.h"
 #include "services/shape_detection/shape_detection_service.h"
+#include "services/video_capture/public/interfaces/constants.mojom.h"
+#include "services/video_capture/service_impl.h"
 
 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
 #include "media/mojo/services/media_service_factory.h"  // nogncheck
 #endif
 
+namespace {
+
+std::unique_ptr<service_manager::Service> CreateVideoCaptureService() {
+  return base::MakeUnique<video_capture::ServiceImpl>();
+}
+
+}  // anonymous namespace
+
 namespace content {
 
 namespace {
@@ -43,6 +53,11 @@
 void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
   GetContentClient()->utility()->RegisterServices(services);
 
+  ServiceInfo video_capture_info;
+  video_capture_info.factory = base::Bind(&CreateVideoCaptureService);
+  services->insert(
+      std::make_pair(video_capture::mojom::kServiceName, video_capture_info));
+
 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
   ServiceInfo info;
   info.factory = base::Bind(&media::CreateMediaService);
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index c289ae4..e7ffdbf 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -587,10 +587,27 @@
   }
 }
 
-// TODO(krstnmnlsn): Implement. crbug.com/511025
+// TODO(crbug.com/511025): Handle state < CBCentralManagerStatePoweredOff.
 void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {
   VLOG(1) << "Central manager state updated: "
           << [low_energy_central_manager_ state];
+  // A state with a value lower than CBCentralManagerStatePoweredOn implies that
+  // scanning has stopped and that any connected peripherals have been
+  // disconnected. Call DidDisconnectPeripheral manually to update the devices'
+  // states since macOS doesn't call it.
+  // See
+  // https://developer.apple.com/reference/corebluetooth/cbcentralmanagerdelegate/1518888-centralmanagerdidupdatestate?language=objc
+  if ([low_energy_central_manager_ state] < CBCentralManagerStatePoweredOn) {
+    VLOG(1)
+        << "Central no longer powered on. Notifying of device disconnection.";
+    for (BluetoothDevice* device : GetDevices()) {
+      BluetoothLowEnergyDeviceMac* device_mac =
+          static_cast<BluetoothLowEnergyDeviceMac*>(device);
+      if (device_mac->IsGattConnected()) {
+        device_mac->DidDisconnectPeripheral(nullptr);
+      }
+    }
+  }
 }
 
 void BluetoothAdapterMac::AddPairedDevices() {
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index 0e60fd9..264cc4c 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -741,6 +741,36 @@
 }
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_MACOSX)
+// TODO(crbug.com/725270): Enable on relevant platforms.
+TEST_F(BluetoothTest, TurnOffAdapterWithConnectedDevice) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+
+  InitWithFakeAdapter();
+  TestBluetoothAdapterObserver observer(adapter_);
+
+  StartLowEnergyDiscoverySession();
+  BluetoothDevice* device = SimulateLowEnergyDevice(3);
+
+  device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
+                               GetConnectErrorCallback(Call::NOT_EXPECTED));
+  SimulateGattConnection(device);
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_TRUE(device->IsGattConnected());
+
+  ResetEventCounts();
+  SimulateAdapterPoweredOff();
+
+  EXPECT_EQ(2, observer.device_changed_count());
+  EXPECT_FALSE(device->IsConnected());
+  EXPECT_FALSE(device->IsGattConnected());
+}
+#endif  // defined(OS_MACOSX)
+
 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
 TEST_F(BluetoothTest, RegisterLocalGattServices) {
   InitWithFakeAdapter();
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h
index 0888acb..115d73b 100644
--- a/device/bluetooth/test/bluetooth_test.h
+++ b/device/bluetooth/test/bluetooth_test.h
@@ -142,6 +142,9 @@
   // devices.  Returns false if the current platform always has permission.
   virtual bool DenyPermission();
 
+  // Simulates the Adapter being switched off.
+  virtual void SimulateAdapterPoweredOff() {}
+
   // Create a fake Low Energy device and discover it.
   // |device_ordinal| with the same device address stands for the same fake
   // device with different properties.
diff --git a/device/bluetooth/test/bluetooth_test_mac.h b/device/bluetooth/test/bluetooth_test_mac.h
index 2b97132d..5784ce4 100644
--- a/device/bluetooth/test/bluetooth_test_mac.h
+++ b/device/bluetooth/test/bluetooth_test_mac.h
@@ -42,6 +42,7 @@
   void InitWithoutDefaultAdapter() override;
   void InitWithFakeAdapter() override;
   void ResetEventCounts() override;
+  void SimulateAdapterPoweredOff() override;
   BluetoothDevice* SimulateLowEnergyDevice(int device_ordinal) override;
   void SimulateConnectedLowEnergyDevice(
       ConnectedDeviceType device_ordinal) override;
diff --git a/device/bluetooth/test/bluetooth_test_mac.mm b/device/bluetooth/test/bluetooth_test_mac.mm
index 8bd2b5e0f..3c5e8000 100644
--- a/device/bluetooth/test/bluetooth_test_mac.mm
+++ b/device/bluetooth/test/bluetooth_test_mac.mm
@@ -140,6 +140,20 @@
   last_notify_value_ = false;
 }
 
+void BluetoothTestMac::SimulateAdapterPoweredOff() {
+  [mock_central_manager_->get() setState:CBCentralManagerStatePoweredOff];
+
+  for (BluetoothDevice* device : adapter_->GetDevices()) {
+    MockCBPeripheral* peripheral_mock = GetMockCBPeripheral(device);
+    [peripheral_mock setState:CBPeripheralStateDisconnected];
+  }
+
+  BluetoothLowEnergyCentralManagerDelegate* central_manager_delegate =
+      adapter_mac_->low_energy_central_manager_delegate_;
+  CBCentralManager* central_manager = adapter_mac_->low_energy_central_manager_;
+  [central_manager_delegate centralManagerDidUpdateState:central_manager];
+}
+
 BluetoothDevice* BluetoothTestMac::SimulateLowEnergyDevice(int device_ordinal) {
   TestBluetoothAdapterObserver observer(adapter_);
   CBCentralManager* central_manager = adapter_mac_->low_energy_central_manager_;
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc
index d9815eb..eac3214 100644
--- a/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -50,9 +50,7 @@
 const char kRedirectResponsePath[] = "/server-redirect";
 const char kRedirectResponseFullPath[] = "/guest_redirect.html";
 const char kUserAgentRedirectResponsePath[] = "/detect-user-agent";
-const char kTestDataDirectory[] = "testDataDirectory";
 const char kTestServerPort[] = "testServer.port";
-const char kTestWebSocketPort[] = "testWebSocketPort";
 
 // Handles |request| by serving a redirect response if the |User-Agent| is
 // foobar.
@@ -143,9 +141,6 @@
   PathService::Get(DIR_TEST_DATA, &test_data_dir);
   test_data_dir = test_data_dir.AppendASCII(app_location.c_str());
 
-  test_config_.SetString(kTestDataDirectory,
-                         net::FilePathToFileURL(test_data_dir).spec());
-
   const Extension* extension = extension_system_->LoadApp(test_data_dir);
   ASSERT_TRUE(extension);
   extension_system_->LaunchApp(extension->id());
@@ -186,8 +181,6 @@
   AppShellTest::SetUpOnMainThread();
 
   TestGetConfigFunction::set_test_config_state(&test_config_);
-  base::FilePath test_data_dir;
-  test_config_.SetInteger(kTestWebSocketPort, 0);
 }
 
 void WebViewAPITest::StartTestServer(const std::string& app_location) {
diff --git a/extensions/common/api/test.json b/extensions/common/api/test.json
index bd4402c..97dff284 100644
--- a/extensions/common/api/test.json
+++ b/extensions/common/api/test.json
@@ -51,10 +51,12 @@
                   },
                   "testDataDirectory": {
                     "type": "string",
+                    "optional": true,
                     "description": "file:/// URL for the API test data directory."
                   },
                   "testWebSocketPort": {
                     "type": "integer",
+                    "optional": true,
                     "description": "The port on which the test WebSocket server is listening.",
                     "minimum": 0,
                     "maximum": 65535
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
index e0609fe..bfc489b 100644
--- a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
+++ b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.cc
@@ -15,14 +15,12 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_clock.h"
 #include "base/values.h"
-#include "components/bookmarks/browser/bookmark_model.h"
 #include "components/image_fetcher/core/image_decoder.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
 #include "components/image_fetcher/ios/ios_image_decoder_impl.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
-#include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h"
 #include "components/ntp_snippets/category_rankers/category_ranker.h"
 #include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
 #include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
@@ -42,7 +40,6 @@
 #include "components/version_info/version_info.h"
 #include "google_apis/google_api_keys.h"
 #include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
@@ -54,12 +51,9 @@
 #include "ios/web/public/web_thread.h"
 #include "net/url_request/url_request_context_getter.h"
 
-using bookmarks::BookmarkModel;
 using history::HistoryService;
 using image_fetcher::CreateIOSImageDecoder;
 using image_fetcher::ImageFetcherImpl;
-using ios::BookmarkModelFactory;
-using ntp_snippets::BookmarkSuggestionsProvider;
 using ntp_snippets::ContentSuggestionsService;
 using ntp_snippets::GetFetchEndpoint;
 using ntp_snippets::PersistentScheduler;
@@ -108,7 +102,6 @@
     : BrowserStateKeyedServiceFactory(
           "ContentSuggestionsService",
           BrowserStateDependencyManager::GetInstance()) {
-  DependsOn(BookmarkModelFactory::GetInstance());
   DependsOn(ios::HistoryServiceFactory::GetInstance());
   DependsOn(IOSChromeLargeIconServiceFactory::GetInstance());
   DependsOn(OAuth2TokenServiceFactory::GetInstance());
diff --git a/ios/chrome/browser/payments/BUILD.gn b/ios/chrome/browser/payments/BUILD.gn
index 836535a..b0521bc 100644
--- a/ios/chrome/browser/payments/BUILD.gn
+++ b/ios/chrome/browser/payments/BUILD.gn
@@ -50,10 +50,13 @@
   sources = [
     "payment_request_test_util.h",
     "payment_request_test_util.mm",
+    "test_payment_request.h",
+    "test_payment_request.mm",
   ]
   deps = [
     ":payments",
     "//base",
+    "//components/autofill/core/browser",
     "//components/payments/core",
     "//ios/web",
   ]
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h
index ca271f36..19f8dca 100644
--- a/ios/chrome/browser/payments/payment_request.h
+++ b/ios/chrome/browser/payments/payment_request.h
@@ -70,7 +70,7 @@
   payments::CurrencyFormatter* GetOrCreateCurrencyFormatter();
 
   // Returns the autofill::RegionDataLoader instance for this PaymentRequest.
-  autofill::RegionDataLoader* GetRegionDataLoader();
+  virtual autofill::RegionDataLoader* GetRegionDataLoader();
 
   // Returns the available autofill profiles for this user to be used as
   // shipping profiles.
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm
index da4ec76..5e9683f 100644
--- a/ios/chrome/browser/payments/payment_request.mm
+++ b/ios/chrome/browser/payments/payment_request.mm
@@ -128,29 +128,29 @@
     return;
 
   profile_cache_.reserve(profiles_to_suggest.size());
+
+  std::vector<autofill::AutofillProfile*> raw_profiles_for_filtering;
+  raw_profiles_for_filtering.reserve(profiles_to_suggest.size());
+
   for (const auto* profile : profiles_to_suggest) {
     profile_cache_.push_back(*profile);
-    shipping_profiles_.push_back(&profile_cache_.back());
-  }
-
-  // If the merchant provided a shipping option, select a suitable default
-  // shipping profile. We pick the profile that is most complete, going down
-  // the list in Frecency order.
-  // TODO(crbug.com/719652): Have a proper ordering of shipping addresses by
-  // completeness.
-  if (selected_shipping_option_) {
-    selected_shipping_profile_ = shipping_profiles_[0];
-    for (autofill::AutofillProfile* profile : shipping_profiles_) {
-      if (profile_comparator_.IsShippingComplete(profile)) {
-        selected_shipping_profile_ = profile;
-        break;
-      }
-    }
+    raw_profiles_for_filtering.push_back(&profile_cache_.back());
   }
 
   // Contact profiles are deduped and ordered in completeness.
   contact_profiles_ =
-      profile_comparator_.FilterProfilesForContact(shipping_profiles_);
+      profile_comparator_.FilterProfilesForContact(raw_profiles_for_filtering);
+
+  // Shipping profiles are ordered by completeness.
+  shipping_profiles_ =
+      profile_comparator_.FilterProfilesForShipping(raw_profiles_for_filtering);
+
+  // If the merchant provided a shipping option, and the highest-ranking
+  // shipping profile is usable, select it.
+  if (selected_shipping_option_ && !shipping_profiles_.empty() &&
+      profile_comparator_.IsShippingComplete(shipping_profiles_[0])) {
+    selected_shipping_profile_ = shipping_profiles_[0];
+  }
 
   // If the highest-ranking contact profile is usable, select it. Otherwise,
   // select none.
diff --git a/ios/chrome/browser/payments/test_payment_request.h b/ios/chrome/browser/payments/test_payment_request.h
new file mode 100644
index 0000000..025d38eb
--- /dev/null
+++ b/ios/chrome/browser/payments/test_payment_request.h
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_PAYMENTS_TEST_PAYMENT_REQUEST_H_
+#define IOS_CHROME_BROWSER_PAYMENTS_TEST_PAYMENT_REQUEST_H_
+
+#include "base/macros.h"
+#include "ios/chrome/browser/payments/payment_request.h"
+
+namespace autofill {
+class PersonalDataManager;
+class RegionDataLoader;
+}  // namespace autofill
+
+namespace web {
+class PaymentRequest;
+}  // namespace web
+
+// PaymentRequest for use in tests.
+class TestPaymentRequest : public PaymentRequest {
+ public:
+  // |personal_data_manager| should not be null and should outlive this object.
+  TestPaymentRequest(const web::PaymentRequest& web_payment_request,
+                     autofill::PersonalDataManager* personal_data_manager)
+      : PaymentRequest(web_payment_request, personal_data_manager) {}
+
+  ~TestPaymentRequest() override{};
+
+  void SetRegionDataLoader(autofill::RegionDataLoader* region_data_loader) {
+    region_data_loader_ = region_data_loader;
+  }
+
+  // PaymentRequest
+  autofill::RegionDataLoader* GetRegionDataLoader() override;
+
+ private:
+  // Not owned and must outlive this object.
+  autofill::RegionDataLoader* region_data_loader_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestPaymentRequest);
+};
+
+#endif  // IOS_CHROME_BROWSER_PAYMENTS_TEST_PAYMENT_REQUEST_H_
diff --git a/ios/chrome/browser/payments/test_payment_request.mm b/ios/chrome/browser/payments/test_payment_request.mm
new file mode 100644
index 0000000..37f20d9
--- /dev/null
+++ b/ios/chrome/browser/payments/test_payment_request.mm
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/payments/test_payment_request.h"
+
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/region_data_loader.h"
+#include "ios/web/public/payments/payment_request.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+autofill::RegionDataLoader* TestPaymentRequest::GetRegionDataLoader() {
+  return region_data_loader_;
+}
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 568823b..5a50138d 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -13,7 +13,6 @@
 #import "components/handoff/handoff_manager.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/network_time/network_time_tracker.h"
-#include "components/ntp_snippets/bookmarks/bookmark_suggestions_provider.h"
 #include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
@@ -97,7 +96,6 @@
   gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
   HostContentSettingsMap::RegisterProfilePrefs(registry);
   HttpServerPropertiesManagerFactory::RegisterProfilePrefs(registry);
-  ntp_snippets::BookmarkSuggestionsProvider::RegisterProfilePrefs(registry);
   ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry);
   ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
   ntp_snippets::RemoteSuggestionsProviderImpl::RegisterProfilePrefs(registry);
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index bc1da78..51a1278 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -31,6 +31,7 @@
     "//ui/base",
   ]
   libs = [ "UIKit.framework" ]
+  configs += [ "//build/config/compiler:enable_arc" ]
 }
 
 source_set("tabs_internal") {
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
index c63a9d7..69a4d76f 100644
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -234,7 +234,8 @@
     [tab_ webWillAddPendingURL:userUrl transition:ui::PAGE_TRANSITION_TYPED];
     std::unique_ptr<web::NavigationContext> context1 =
         web::NavigationContextImpl::CreateNavigationContext(
-            web_state_impl_.get(), userUrl);
+            web_state_impl_.get(), userUrl,
+            ui::PageTransition::PAGE_TRANSITION_TYPED);
     web_state_impl_->OnNavigationStarted(context1.get());
     [tab_ webWillAddPendingURL:redirectUrl
                     transition:ui::PAGE_TRANSITION_CLIENT_REDIRECT];
@@ -247,7 +248,8 @@
 
     std::unique_ptr<web::NavigationContext> context2 =
         web::NavigationContextImpl::CreateNavigationContext(
-            web_state_impl_.get(), redirectUrl);
+            web_state_impl_.get(), redirectUrl,
+            ui::PageTransition::PAGE_TRANSITION_TYPED);
     web_state_impl_->OnNavigationStarted(context2.get());
     [[tab_ navigationManagerImpl]->GetSessionController() commitPendingItem];
     web_state_impl_->UpdateHttpResponseHeaders(redirectUrl);
diff --git a/ios/chrome/browser/ui/autofill/autofill_ui_type.h b/ios/chrome/browser/ui/autofill/autofill_ui_type.h
index 82a0de3..9a408bb 100644
--- a/ios/chrome/browser/ui/autofill/autofill_ui_type.h
+++ b/ios/chrome/browser/ui/autofill/autofill_ui_type.h
@@ -17,11 +17,14 @@
   AutofillUITypeCreditCardBillingAddress,
   AutofillUITypeProfileFullName,
   AutofillUITypeProfileCompanyName,
+  AutofillUITypeProfileHomeAddressStreet,
   AutofillUITypeProfileHomeAddressLine1,
   AutofillUITypeProfileHomeAddressLine2,
+  AutofillUITypeProfileHomeAddressDependentLocality,
   AutofillUITypeProfileHomeAddressCity,
   AutofillUITypeProfileHomeAddressState,
   AutofillUITypeProfileHomeAddressZip,
+  AutofillUITypeProfileHomeAddressSortingCode,
   AutofillUITypeProfileHomeAddressCountry,
   AutofillUITypeProfileHomePhoneWholeNumber,
   AutofillUITypeProfileEmailAddress,
diff --git a/ios/chrome/browser/ui/autofill/autofill_ui_type_util.mm b/ios/chrome/browser/ui/autofill/autofill_ui_type_util.mm
index e9e0ed6..db2192e 100644
--- a/ios/chrome/browser/ui/autofill/autofill_ui_type_util.mm
+++ b/ios/chrome/browser/ui/autofill/autofill_ui_type_util.mm
@@ -26,16 +26,22 @@
       return AutofillUITypeProfileFullName;
     case autofill::COMPANY_NAME:
       return AutofillUITypeProfileCompanyName;
+    case autofill::ADDRESS_HOME_STREET_ADDRESS:
+      return AutofillUITypeProfileHomeAddressStreet;
     case autofill::ADDRESS_HOME_LINE1:
       return AutofillUITypeProfileHomeAddressLine1;
     case autofill::ADDRESS_HOME_LINE2:
       return AutofillUITypeProfileHomeAddressLine2;
+    case autofill::ADDRESS_HOME_DEPENDENT_LOCALITY:
+      return AutofillUITypeProfileHomeAddressDependentLocality;
     case autofill::ADDRESS_HOME_CITY:
       return AutofillUITypeProfileHomeAddressCity;
     case autofill::ADDRESS_HOME_STATE:
       return AutofillUITypeProfileHomeAddressState;
     case autofill::ADDRESS_HOME_ZIP:
       return AutofillUITypeProfileHomeAddressZip;
+    case autofill::ADDRESS_HOME_SORTING_CODE:
+      return AutofillUITypeProfileHomeAddressSortingCode;
     case autofill::ADDRESS_HOME_COUNTRY:
       return AutofillUITypeProfileHomeAddressCountry;
     case autofill::PHONE_HOME_WHOLE_NUMBER:
@@ -64,16 +70,22 @@
       return autofill::NAME_FULL;
     case AutofillUITypeProfileCompanyName:
       return autofill::COMPANY_NAME;
+    case AutofillUITypeProfileHomeAddressStreet:
+      return autofill::ADDRESS_HOME_STREET_ADDRESS;
     case AutofillUITypeProfileHomeAddressLine1:
       return autofill::ADDRESS_HOME_LINE1;
     case AutofillUITypeProfileHomeAddressLine2:
       return autofill::ADDRESS_HOME_LINE2;
+    case AutofillUITypeProfileHomeAddressDependentLocality:
+      return autofill::ADDRESS_HOME_DEPENDENT_LOCALITY;
     case AutofillUITypeProfileHomeAddressCity:
       return autofill::ADDRESS_HOME_CITY;
     case AutofillUITypeProfileHomeAddressState:
       return autofill::ADDRESS_HOME_STATE;
     case AutofillUITypeProfileHomeAddressZip:
       return autofill::ADDRESS_HOME_ZIP;
+    case AutofillUITypeProfileHomeAddressSortingCode:
+      return autofill::ADDRESS_BILLING_SORTING_CODE;
     case AutofillUITypeProfileHomeAddressCountry:
       return autofill::ADDRESS_HOME_COUNTRY;
     case AutofillUITypeProfileHomePhoneWholeNumber:
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h
index 31c3eab5..7729ca2 100644
--- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h
+++ b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h
@@ -24,6 +24,9 @@
 // An image corresponding to the type of the credit card, if any.
 @property(nonatomic, copy) UIImage* cardTypeIcon;
 
+// The inputView for the text field, if any.
+@property(nonatomic, strong) UIPickerView* inputView;
+
 // The field type this item is describing.
 @property(nonatomic, assign) AutofillUIType autofillUIType;
 
diff --git a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm
index f4d9655e..406a69e 100644
--- a/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm
+++ b/ios/chrome/browser/ui/autofill/cells/autofill_edit_item.mm
@@ -29,6 +29,7 @@
 @synthesize textFieldName = _textFieldName;
 @synthesize textFieldValue = _textFieldValue;
 @synthesize cardTypeIcon = _cardTypeIcon;
+@synthesize inputView = _inputView;
 @synthesize textFieldEnabled = _textFieldEnabled;
 @synthesize autofillUIType = _autofillUIType;
 @synthesize required = _required;
@@ -60,6 +61,7 @@
   [cell.textField addTarget:self
                      action:@selector(textFieldChanged:)
            forControlEvents:UIControlEventEditingChanged];
+  cell.textField.inputView = self.inputView;
   cell.cardTypeIconView.image = self.cardTypeIcon;
 }
 
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn
index d06f1e8..c1fa194 100644
--- a/ios/chrome/browser/ui/payments/BUILD.gn
+++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -82,6 +82,7 @@
     "//ios/third_party/material_roboto_font_loader_ios",
     "//ios/web",
     "//third_party/libaddressinput",
+    "//third_party/libaddressinput:strings_grit",
     "//ui/base",
   ]
   libs = [ "UIKit.framework" ]
@@ -163,6 +164,7 @@
     "//components/autofill/core/browser",
     "//components/autofill/core/browser:test_support",
     "//components/payments/core",
+    "//components/prefs:prefs",
     "//components/strings",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.h b/ios/chrome/browser/ui/payments/address_edit_coordinator.h
index e207f94..799fb224 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator.h
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.h
@@ -7,6 +7,7 @@
 
 #import "ios/chrome/browser/chrome_coordinator.h"
 #import "ios/chrome/browser/ui/payments/address_edit_view_controller.h"
+#import "ios/chrome/browser/ui/payments/country_selection_coordinator.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h"
 
 namespace autofill {
@@ -38,7 +39,8 @@
 // provided in the initializer.
 @interface AddressEditCoordinator
     : ChromeCoordinator<AddressEditViewControllerDelegate,
-                        PaymentRequestEditViewControllerValidator>
+                        PaymentRequestEditViewControllerValidator,
+                        CountrySelectionCoordinatorDelegate>
 
 // The address to be edited, if any. This pointer is not owned by this class
 // and should outlive it.
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
index 2adcfab2..b660f86 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
@@ -23,6 +23,9 @@
 
 @interface AddressEditCoordinator ()
 
+@property(nonatomic, strong)
+    CountrySelectionCoordinator* countrySelectionCoordinator;
+
 @property(nonatomic, strong) AddressEditViewController* viewController;
 
 @property(nonatomic, strong) AddressEditMediator* mediator;
@@ -34,6 +37,7 @@
 @synthesize address = _address;
 @synthesize paymentRequest = _paymentRequest;
 @synthesize delegate = _delegate;
+@synthesize countrySelectionCoordinator = _countrySelectionCoordinator;
 @synthesize viewController = _viewController;
 @synthesize mediator = _mediator;
 
@@ -50,6 +54,7 @@
   self.mediator =
       [[AddressEditMediator alloc] initWithPaymentRequest:self.paymentRequest
                                                   address:self.address];
+  [self.mediator setConsumer:self.viewController];
   [self.viewController setDataSource:self.mediator];
   [self.viewController loadModel];
 
@@ -61,6 +66,8 @@
 
 - (void)stop {
   [self.viewController.navigationController popViewControllerAnimated:YES];
+  [self.countrySelectionCoordinator stop];
+  self.countrySelectionCoordinator = nil;
   self.viewController = nil;
 }
 
@@ -79,7 +86,13 @@
             (PaymentRequestEditViewController*)controller
                           didSelectField:(EditorField*)field {
   if (field.autofillUIType == AutofillUITypeProfileHomeAddressCountry) {
-    // TODO(crbug.com/602666): Change the fields according to the selection.
+    self.countrySelectionCoordinator = [[CountrySelectionCoordinator alloc]
+        initWithBaseViewController:self.viewController];
+    [self.countrySelectionCoordinator setCountries:self.mediator.countries];
+    [self.countrySelectionCoordinator
+        setSelectedCountryCode:self.mediator.selectedCountryCode];
+    [self.countrySelectionCoordinator setDelegate:self];
+    [self.countrySelectionCoordinator start];
   }
 }
 
@@ -95,4 +108,17 @@
   [self.delegate addressEditCoordinatorDidCancel:self];
 }
 
+#pragma mark - CountrySelectionCoordinatorDelegate
+
+- (void)countrySelectionCoordinator:(CountrySelectionCoordinator*)coordinator
+           didSelectCountryWithCode:(NSString*)countryCode {
+  if (self.mediator.selectedCountryCode != countryCode) {
+    [self.mediator setSelectedCountryCode:countryCode];
+    [self.viewController loadModel];
+    [self.viewController.collectionView reloadData];
+  }
+  [self.countrySelectionCoordinator stop];
+  self.countrySelectionCoordinator = nil;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm
index 9971899..c2f0904 100644
--- a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm
@@ -9,9 +9,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/ios/wait_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "ios/chrome/browser/payments/payment_request.h"
+#include "components/autofill/core/browser/test_region_data_loader.h"
+#include "components/prefs/pref_service.h"
 #include "ios/chrome/browser/payments/payment_request_test_util.h"
+#include "ios/chrome/browser/payments/test_payment_request.h"
 #import "ios/chrome/browser/ui/payments/address_edit_view_controller.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -24,14 +27,24 @@
 
 class PaymentRequestAddressEditCoordinatorTest : public PlatformTest {
  protected:
-  PaymentRequestAddressEditCoordinatorTest() {
-    payment_request_ = base::MakeUnique<PaymentRequest>(
+  PaymentRequestAddressEditCoordinatorTest()
+      : pref_service_(autofill::test::PrefServiceForTesting()) {
+    personal_data_manager_.SetTestingPrefService(pref_service_.get());
+    payment_request_ = base::MakeUnique<TestPaymentRequest>(
         payment_request_test_util::CreateTestWebPaymentRequest(),
         &personal_data_manager_);
+    test_region_data_loader_.set_synchronous_callback(true);
+    payment_request_->SetRegionDataLoader(&test_region_data_loader_);
+  }
+
+  void TearDown() override {
+    personal_data_manager_.SetTestingPrefService(nullptr);
   }
 
   autofill::TestPersonalDataManager personal_data_manager_;
-  std::unique_ptr<PaymentRequest> payment_request_;
+  std::unique_ptr<PrefService> pref_service_;
+  std::unique_ptr<TestPaymentRequest> payment_request_;
+  autofill::TestRegionDataLoader test_region_data_loader_;
 };
 
 // Tests that invoking start and stop on the coordinator presents and dismisses
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.h b/ios/chrome/browser/ui/payments/address_edit_mediator.h
index a2898fd3..cae2146 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.h
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_PAYMENTS_ADDRESS_EDIT_MEDIATOR_H_
 
 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h"
+#import "ios/chrome/browser/ui/payments/region_data_loader.h"
 
 class PaymentRequest;
 @protocol PaymentRequestEditConsumer;
@@ -16,12 +17,22 @@
 
 // Serves as data source for AddressEditViewController.
 @interface AddressEditMediator
-    : NSObject<PaymentRequestEditViewControllerDataSource>
+    : NSObject<PaymentRequestEditViewControllerDataSource,
+               RegionDataLoaderConsumer>
 
 // The consumer for this object. This can change during the lifetime of this
 // object and may be nil.
 @property(nonatomic, weak) id<PaymentRequestEditConsumer> consumer;
 
+// The map of country codes to country names.
+@property(nonatomic, strong) NSDictionary<NSString*, NSString*>* countries;
+
+// The country code for the currently selected country, if any.
+@property(nonatomic, strong) NSString* selectedCountryCode;
+
+// The list of region names used for the autofill::ADDRESS_HOME_STATE field.
+@property(nonatomic, strong) NSArray<NSString*>* regions;
+
 // Initializes this object with an instance of PaymentRequest which has a copy
 // of web::PaymentRequest as provided by the page invoking the Payment Request
 // API as well as |address| which is the address to be edited, if any.
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
index cbb1291..33be5424 100644
--- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -4,15 +4,39 @@
 
 #import "ios/chrome/browser/ui/payments/address_edit_mediator.h"
 
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/values.h"
+#include "components/autofill/core/browser/autofill_address_util.h"
+#include "components/autofill/core/browser/autofill_country.h"
 #include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/country_combobox_model.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/payments/payment_request.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
+#import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h"
 #import "ios/chrome/browser/ui/payments/payment_request_edit_consumer.h"
+#import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "third_party/libaddressinput/messages.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@interface AddressEditMediator ()
+@interface AddressEditMediator () {
+  std::unique_ptr<RegionDataLoader> _regionDataLoader;
+}
 
 // The PaymentRequest object owning an instance of web::PaymentRequest as
 // provided by the page invoking the Payment Request API. This is a weak
@@ -23,14 +47,32 @@
 // should outlive it.
 @property(nonatomic, assign) autofill::AutofillProfile* address;
 
+// The map of autofill types to the cached editor fields. Helps reuse the editor
+// fields and therefore maintain their existing values when the selected country
+// changes and the editor fields get updated.
+@property(nonatomic, strong)
+    NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap;
+
+// The list of current editor fields.
+@property(nonatomic, strong) NSMutableArray<EditorField*>* fields;
+
+// The reference to the autofill::ADDRESS_HOME_STATE field, if any.
+@property(nonatomic, strong) EditorField* regionField;
+
 @end
 
 @implementation AddressEditMediator
 
 @synthesize state = _state;
 @synthesize consumer = _consumer;
+@synthesize countries = _countries;
+@synthesize selectedCountryCode = _selectedCountryCode;
+@synthesize regions = _regions;
 @synthesize paymentRequest = _paymentRequest;
 @synthesize address = _address;
+@synthesize fieldsMap = _fieldsMap;
+@synthesize fields = _fields;
+@synthesize regionField = _regionField;
 
 - (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest
                                address:(autofill::AutofillProfile*)address {
@@ -40,6 +82,8 @@
     _address = address;
     _state =
         _address ? EditViewControllerStateEdit : EditViewControllerStateCreate;
+    _fieldsMap = [[NSMutableDictionary alloc] init];
+    [self loadCountries];
   }
   return self;
 }
@@ -48,7 +92,20 @@
 
 - (void)setConsumer:(id<PaymentRequestEditConsumer>)consumer {
   _consumer = consumer;
+
   [self.consumer setEditorFields:[self createEditorFields]];
+  if (self.regionField)
+    [self loadRegions];
+}
+
+- (void)setSelectedCountryCode:(NSString*)selectedCountryCode {
+  if (_selectedCountryCode == selectedCountryCode)
+    return;
+  _selectedCountryCode = selectedCountryCode;
+
+  [self.consumer setEditorFields:[self createEditorFields]];
+  if (self.regionField)
+    [self loadRegions];
 }
 
 #pragma mark - CreditCardEditViewControllerDataSource
@@ -61,10 +118,159 @@
   return NO;
 }
 
+#pragma mark - RegionDataLoaderConsumer
+
+- (void)regionDataLoaderDidSucceedWithRegions:
+    (NSMutableArray<NSString*>*)regions {
+  self.regions = regions;
+  // Notify the view controller asynchronously to allow for the view to update.
+  __weak AddressEditMediator* weakSelf = self;
+  dispatch_async(dispatch_get_main_queue(), ^{
+    [weakSelf.consumer setOptions:weakSelf.regions
+                   forEditorField:weakSelf.regionField];
+  });
+}
+
 #pragma mark - Helper methods
 
+// Loads the country codes and names and sets the default selected country code.
+- (void)loadCountries {
+  autofill::CountryComboboxModel countryModel;
+  countryModel.SetCountries(*_paymentRequest->GetPersonalDataManager(),
+                            base::Callback<bool(const std::string&)>(),
+                            GetApplicationContext()->GetApplicationLocale());
+  const autofill::CountryComboboxModel::CountryVector& countriesVector =
+      countryModel.countries();
+
+  NSMutableDictionary<NSString*, NSString*>* countries =
+      [[NSMutableDictionary alloc]
+          initWithCapacity:static_cast<NSUInteger>(countriesVector.size())];
+  for (size_t i = 0; i < countriesVector.size(); ++i) {
+    if (countriesVector[i].get()) {
+      [countries setObject:base::SysUTF16ToNSString(countriesVector[i]->name())
+                    forKey:base::SysUTF8ToNSString(
+                               countriesVector[i]->country_code())];
+    }
+  }
+  _countries = countries;
+  _selectedCountryCode =
+      base::SysUTF8ToNSString(countryModel.GetDefaultCountryCode());
+}
+
+// Queries the region names based on the selected country code.
+- (void)loadRegions {
+  _regionDataLoader = base::MakeUnique<RegionDataLoader>(self);
+  _regionDataLoader->LoadRegionData(
+      base::SysNSStringToUTF8(self.selectedCountryCode),
+      _paymentRequest->GetRegionDataLoader());
+}
+
+// Returns an array of editor fields based on the selected country code. Caches
+// the fields to be reused when the selected country code changes.
 - (NSArray<EditorField*>*)createEditorFields {
-  return @[];
+  self.fields = [[NSMutableArray alloc] init];
+
+  self.regionField = nil;
+
+  base::ListValue addressComponents;
+  std::string unused;
+  autofill::GetAddressComponents(
+      base::SysNSStringToUTF8(self.selectedCountryCode),
+      GetApplicationContext()->GetApplicationLocale(), &addressComponents,
+      &unused);
+
+  for (size_t lineIndex = 0; lineIndex < addressComponents.GetSize();
+       ++lineIndex) {
+    const base::ListValue* line = nullptr;
+    if (!addressComponents.GetList(lineIndex, &line)) {
+      NOTREACHED();
+      return @[];
+    }
+    for (size_t componentIndex = 0; componentIndex < line->GetSize();
+         ++componentIndex) {
+      const base::DictionaryValue* component = nullptr;
+      if (!line->GetDictionary(componentIndex, &component)) {
+        NOTREACHED();
+        return @[];
+      }
+
+      std::string autofillType;
+      if (!component->GetString(autofill::kFieldTypeKey, &autofillType)) {
+        NOTREACHED();
+        return @[];
+      }
+      AutofillUIType autofillUIType = AutofillUITypeFromAutofillType(
+          autofill::GetFieldTypeFromString(autofillType));
+
+      NSNumber* fieldKey = [NSNumber numberWithInt:autofillUIType];
+      EditorField* field = self.fieldsMap[fieldKey];
+      if (!field) {
+        BOOL required = autofillUIType != AutofillUITypeProfileCompanyName;
+        field =
+            [[EditorField alloc] initWithAutofillUIType:autofillUIType
+                                              fieldType:EditorFieldTypeTextField
+                                                  label:nil
+                                                  value:nil
+                                               required:required];
+        [self.fieldsMap setObject:field forKey:fieldKey];
+      }
+
+      std::string fieldLabel;
+      if (!component->GetString(autofill::kFieldNameKey, &fieldLabel)) {
+        NOTREACHED();
+        return @[];
+      }
+      field.label = base::SysUTF8ToNSString(fieldLabel);
+
+      // Keep a reference to the field for the autofill::ADDRESS_HOME_STATE. Set
+      // its value to "Loading..." and disable it until the regions are loaded.
+      if (autofillUIType == AutofillUITypeProfileHomeAddressState) {
+        self.regionField = field;
+        field.value = l10n_util::GetNSString(IDS_AUTOFILL_LOADING_REGIONS);
+        field.enabled = NO;
+      }
+
+      [self.fields addObject:field];
+
+      // Insert the country field right after the full name field.
+      if (autofillUIType == AutofillUITypeProfileFullName) {
+        NSNumber* countryFieldKey =
+            [NSNumber numberWithInt:AutofillUITypeProfileHomeAddressCountry];
+        EditorField* field = self.fieldsMap[countryFieldKey];
+        if (!field) {
+          NSString* label = l10n_util::GetNSString(
+              IDS_LIBADDRESSINPUT_COUNTRY_OR_REGION_LABEL);
+          field = [[EditorField alloc]
+              initWithAutofillUIType:AutofillUITypeProfileHomeAddressCountry
+                           fieldType:EditorFieldTypeSelector
+                               label:label
+                               value:nil
+                            required:YES];
+          [self.fieldsMap setObject:field forKey:countryFieldKey];
+        }
+        field.value = self.selectedCountryCode;
+        field.displayValue = self.countries[self.selectedCountryCode];
+        [self.fields addObject:field];
+      }
+    }
+  }
+
+  // Always add phone number field at the end.
+  NSNumber* phoneNumberFieldKey =
+      [NSNumber numberWithInt:AutofillUITypeProfileHomePhoneWholeNumber];
+  EditorField* field = self.fieldsMap[phoneNumberFieldKey];
+  if (!field) {
+    field = [[EditorField alloc]
+        initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber
+                     fieldType:EditorFieldTypeTextField
+                         label:l10n_util::GetNSString(IDS_IOS_AUTOFILL_PHONE)
+                         value:nil
+                      required:YES];
+    [self.fieldsMap setObject:field forKey:phoneNumberFieldKey];
+  }
+  [self.fields addObject:field];
+
+  return self.fields;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_consumer.h b/ios/chrome/browser/ui/payments/payment_request_edit_consumer.h
index dd2dbf7f..3d07516 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_consumer.h
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_consumer.h
@@ -15,6 +15,10 @@
 // Sets the list of field definitions for the editor.
 - (void)setEditorFields:(NSArray<EditorField*>*)fields;
 
+// Sets the options to choose from for |field|.
+- (void)setOptions:(NSArray<NSString*>*)options
+    forEditorField:(EditorField*)field;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_PAYMENTS_PAYMENT_REQUEST_EDIT_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
index 9e5c00a..9f58aa8 100644
--- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
@@ -68,18 +68,31 @@
 
 }  // namespace
 
-@interface PaymentRequestEditViewController ()<
-    AutofillEditAccessoryDelegate,
-    UITextFieldDelegate> {
+@interface PaymentRequestEditViewController ()<AutofillEditAccessoryDelegate,
+                                               UITextFieldDelegate,
+                                               UIPickerViewDataSource,
+                                               UIPickerViewDelegate> {
   // The currently focused cell. May be nil.
   __weak AutofillEditCell* _currentEditingCell;
 
   AutofillEditAccessoryView* _accessoryView;
 }
 
+// The map of autofill types to the fields definitions for the editor.
+@property(nonatomic, strong)
+    NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap;
+
 // The list of field definitions for the editor.
 @property(nonatomic, strong) NSArray<EditorField*>* fields;
 
+// The map of autofill types to lists of UIPickerView options.
+@property(nonatomic, strong)
+    NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options;
+
+// The map of autofill types to UIPickerView views.
+@property(nonatomic, strong)
+    NSMutableDictionary<NSNumber*, UIPickerView*>* pickerViews;
+
 // Returns the indexPath for the same row as that of |indexPath| in a section
 // with the given offset relative to that of |indexPath|. May return nil.
 - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset
@@ -106,12 +119,17 @@
 @synthesize dataSource = _dataSource;
 @synthesize delegate = _delegate;
 @synthesize validatorDelegate = _validatorDelegate;
+@synthesize fieldsMap = _fieldsMap;
 @synthesize fields = _fields;
+@synthesize options = _options;
+@synthesize pickerViews = _pickerViews;
 
 - (instancetype)initWithStyle:(CollectionViewControllerStyle)style {
   self = [super initWithStyle:style];
   if (self) {
     _accessoryView = [[AutofillEditAccessoryView alloc] initWithDelegate:self];
+    _options = [[NSMutableDictionary alloc] init];
+    _pickerViews = [[NSMutableDictionary alloc] init];
   }
   return self;
 }
@@ -139,6 +157,8 @@
   [super loadModel];
   CollectionViewModel* model = self.collectionViewModel;
 
+  [self.pickerViews removeAllObjects];
+
   CollectionViewItem* headerItem = [_dataSource headerItem];
   if (headerItem) {
     [headerItem setType:ItemTypeHeader];
@@ -147,21 +167,22 @@
   }
 
   // Iterate over the fields and add the respective sections and items.
-  int sectionIdentifier = static_cast<int>(SectionIdentifierFirstField);
-  for (EditorField* field in self.fields) {
+  [self.fields enumerateObjectsUsingBlock:^(EditorField* field,
+                                            NSUInteger index, BOOL* stop) {
+    NSInteger sectionIdentifier = SectionIdentifierFirstField + index;
     [model addSectionWithIdentifier:sectionIdentifier];
     switch (field.fieldType) {
       case EditorFieldTypeTextField: {
         AutofillEditItem* item =
             [[AutofillEditItem alloc] initWithType:ItemTypeTextField];
         item.textFieldName = field.label;
-        item.textFieldEnabled = YES;
+        item.textFieldEnabled = field.enabled;
         item.textFieldValue = field.value;
         item.required = field.isRequired;
         item.autofillUIType = field.autofillUIType;
-        [model addItem:item
-            toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
+        [model addItem:item toSectionWithIdentifier:sectionIdentifier];
         field.item = item;
+
         break;
       }
       case EditorFieldTypeSelector: {
@@ -172,8 +193,7 @@
         item.required = field.isRequired;
         item.autofillUIType = field.autofillUIType;
         item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
-        [model addItem:item
-            toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
+        [model addItem:item toSectionWithIdentifier:sectionIdentifier];
         field.item = item;
         break;
       }
@@ -181,9 +201,8 @@
         NOTREACHED();
     }
 
-    field.sectionIdentifier = static_cast<NSInteger>(sectionIdentifier);
-    ++sectionIdentifier;
-  }
+    field.sectionIdentifier = sectionIdentifier;
+  }];
 
   [self loadFooterItems];
 }
@@ -204,6 +223,42 @@
 
 - (void)setEditorFields:(NSArray<EditorField*>*)fields {
   self.fields = fields;
+  self.fieldsMap = [[NSMutableDictionary alloc] initWithCapacity:fields.count];
+  // Iterate over the fields and populate the map.
+  [self.fields enumerateObjectsUsingBlock:^(EditorField* field,
+                                            NSUInteger index, BOOL* stop) {
+    NSNumber* key = [NSNumber numberWithInt:field.autofillUIType];
+    [self.fieldsMap setObject:field forKey:key];
+  }];
+}
+
+- (void)setOptions:(NSArray<NSString*>*)options
+    forEditorField:(EditorField*)field {
+  DCHECK(field.fieldType == EditorFieldTypeTextField);
+  AutofillEditItem* item =
+      base::mac::ObjCCastStrict<AutofillEditItem>(field.item);
+
+  // Enable the previously disabled text field and reset its value.
+  item.textFieldEnabled = YES;
+  item.textFieldValue = nil;
+
+  // Cache the options if there are any and set the text field's UIPickerView.
+  if (options.count) {
+    NSNumber* key = [NSNumber numberWithInt:field.autofillUIType];
+    [self.options setObject:options forKey:key];
+
+    UIPickerView* pickerView = [[UIPickerView alloc] initWithFrame:CGRectZero];
+    pickerView.delegate = self;
+    pickerView.dataSource = self;
+    [self.pickerViews setObject:pickerView forKey:key];
+    item.inputView = pickerView;
+  }
+
+  // Reload the item.
+  NSIndexPath* indexPath =
+      [self.collectionViewModel indexPathForItemType:ItemTypeTextField
+                                   sectionIdentifier:field.sectionIdentifier];
+  [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
 }
 
 #pragma mark - UITextFieldDelegate
@@ -217,23 +272,20 @@
 - (void)textFieldDidEndEditing:(UITextField*)textField {
   DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField));
 
-  // Validate the text field.
   CollectionViewModel* model = self.collectionViewModel;
 
   NSIndexPath* indexPath = [self indexPathForCurrentTextField];
   AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
       [model itemAtIndexPath:indexPath]);
 
-  // Create a dummy EditorField for validation only.
-  EditorField* fieldForValidation =
-      [[EditorField alloc] initWithAutofillUIType:item.autofillUIType
-                                        fieldType:EditorFieldTypeTextField
-                                            label:nil
-                                            value:textField.text
-                                         required:item.required];
+  // Find and validate the respective editor field.
+  NSNumber* key = [NSNumber numberWithInt:item.autofillUIType];
+  EditorField* field = self.fieldsMap[key];
+  DCHECK(field);
+  field.value = textField.text;
   NSString* errorMessage =
       [_validatorDelegate paymentRequestEditViewController:self
-                                             validateField:fieldForValidation];
+                                             validateField:field];
   NSInteger sectionIdentifier =
       [model sectionIdentifierForSection:[indexPath section]];
   [self addOrRemoveErrorMessage:errorMessage
@@ -272,6 +324,42 @@
   [[_currentEditingCell textField] resignFirstResponder];
 }
 
+#pragma mark - UIPickerViewDataSource methods
+
+- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)thePickerView {
+  return 1;
+}
+
+- (NSInteger)pickerView:(UIPickerView*)thePickerView
+    numberOfRowsInComponent:(NSInteger)component {
+  NSArray<NSNumber*>* indices =
+      [self.pickerViews allKeysForObject:thePickerView];
+  DCHECK(indices.count == 1);
+  NSArray<NSString*>* options = self.options[indices[0]];
+  return options.count;
+}
+
+#pragma mark - UIPickerViewDelegate methods
+
+- (NSString*)pickerView:(UIPickerView*)thePickerView
+            titleForRow:(NSInteger)row
+           forComponent:(NSInteger)component {
+  NSArray<NSNumber*>* indices =
+      [self.pickerViews allKeysForObject:thePickerView];
+  DCHECK(indices.count == 1);
+  NSArray<NSString*>* options = self.options[indices[0]];
+  DCHECK(row < static_cast<NSInteger>(options.count));
+  return options[row];
+}
+
+- (void)pickerView:(UIPickerView*)thePickerView
+      didSelectRow:(NSInteger)row
+       inComponent:(NSInteger)component {
+  DCHECK(_currentEditingCell);
+  _currentEditingCell.textField.text =
+      [self pickerView:thePickerView titleForRow:row forComponent:component];
+}
+
 #pragma mark - UICollectionViewDataSource
 
 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
@@ -332,9 +420,13 @@
           hasSectionForSectionIdentifier:SectionIdentifierHeader])
     index--;
   DCHECK(index >= 0 && index < static_cast<NSInteger>(self.fields.count));
-  [_delegate
-      paymentRequestEditViewController:self
-                        didSelectField:[self.fields objectAtIndex:index]];
+  EditorField* field = [self.fields objectAtIndex:index];
+
+  // If a selector field is selected, blur the focused text field.
+  if (field.fieldType == EditorFieldTypeSelector)
+    [[_currentEditingCell textField] resignFirstResponder];
+
+  [_delegate paymentRequestEditViewController:self didSelectField:field];
 }
 
 #pragma mark MDCCollectionViewStylingDelegate
diff --git a/ios/chrome/browser/ui/payments/payment_request_editor_field.h b/ios/chrome/browser/ui/payments/payment_request_editor_field.h
index def8ee85..8f54213 100644
--- a/ios/chrome/browser/ui/payments/payment_request_editor_field.h
+++ b/ios/chrome/browser/ui/payments/payment_request_editor_field.h
@@ -34,6 +34,8 @@
 @property(nonatomic, copy) NSString* displayValue;
 // Whether the field is required.
 @property(nonatomic, getter=isRequired) BOOL required;
+// Whether the field is enabled.
+@property(nonatomic, getter=isEnabled) BOOL enabled;
 // The associated CollectionViewItem instance. May be nil.
 @property(nonatomic, strong) CollectionViewItem* item;
 // The section identifier for the associated AutofillEditItem.
diff --git a/ios/chrome/browser/ui/payments/payment_request_editor_field.mm b/ios/chrome/browser/ui/payments/payment_request_editor_field.mm
index 68740c4..e861027 100644
--- a/ios/chrome/browser/ui/payments/payment_request_editor_field.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_editor_field.mm
@@ -16,6 +16,7 @@
 @synthesize value = _value;
 @synthesize displayValue = _displayValue;
 @synthesize required = _required;
+@synthesize enabled = _enabled;
 @synthesize item = _item;
 @synthesize sectionIdentifier = _sectionIdentifier;
 
@@ -31,6 +32,7 @@
     _label = label;
     _value = value;
     _required = required;
+    _enabled = YES;
   }
   return self;
 }
diff --git a/ios/web/public/test/fakes/crw_test_web_state_observer.mm b/ios/web/public/test/fakes/crw_test_web_state_observer.mm
index 51280fb..e133138 100644
--- a/ios/web/public/test/fakes/crw_test_web_state_observer.mm
+++ b/ios/web/public/test/fakes/crw_test_web_state_observer.mm
@@ -132,7 +132,8 @@
   _didStartNavigationInfo->web_state = webState;
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(
-          navigation->GetWebState(), navigation->GetUrl());
+          navigation->GetWebState(), navigation->GetUrl(),
+          navigation->GetPageTransition());
   context->SetIsSameDocument(navigation->IsSameDocument());
   context->SetError(navigation->GetError());
   _didStartNavigationInfo->context = std::move(context);
@@ -154,7 +155,8 @@
   _didFinishNavigationInfo->web_state = webState;
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(
-          navigation->GetWebState(), navigation->GetUrl());
+          navigation->GetWebState(), navigation->GetUrl(),
+          navigation->GetPageTransition());
   context->SetIsSameDocument(navigation->IsSameDocument());
   context->SetError(navigation->GetError());
   _didFinishNavigationInfo->context = std::move(context);
diff --git a/ios/web/public/test/fakes/test_web_state_observer.mm b/ios/web/public/test/fakes/test_web_state_observer.mm
index 5521fad1..c184f6e 100644
--- a/ios/web/public/test/fakes/test_web_state_observer.mm
+++ b/ios/web/public/test/fakes/test_web_state_observer.mm
@@ -65,7 +65,8 @@
   did_start_navigation_info_->web_state = web_state();
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(
-          navigation->GetWebState(), navigation->GetUrl());
+          navigation->GetWebState(), navigation->GetUrl(),
+          navigation->GetPageTransition());
   context->SetIsSameDocument(navigation->IsSameDocument());
   context->SetError(navigation->GetError());
   did_start_navigation_info_->context = std::move(context);
@@ -78,7 +79,8 @@
   did_finish_navigation_info_->web_state = web_state();
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(
-          navigation->GetWebState(), navigation->GetUrl());
+          navigation->GetWebState(), navigation->GetUrl(),
+          navigation->GetPageTransition());
   context->SetIsSameDocument(navigation->IsSameDocument());
   context->SetError(navigation->GetError());
   did_finish_navigation_info_->context = std::move(context);
diff --git a/ios/web/public/web_state/navigation_context.h b/ios/web/public/web_state/navigation_context.h
index b8d5b46..ee7073b 100644
--- a/ios/web/public/web_state/navigation_context.h
+++ b/ios/web/public/web_state/navigation_context.h
@@ -7,6 +7,8 @@
 
 #import <Foundation/Foundation.h>
 
+#include "ui/base/page_transition_types.h"
+
 class GURL;
 
 namespace net {
@@ -30,6 +32,9 @@
   // The URL the WebState is navigating to.
   virtual const GURL& GetUrl() const = 0;
 
+  // Returns the page transition type for this navigation.
+  virtual ui::PageTransition GetPageTransition() const = 0;
+
   // Whether the navigation happened within the same document. Examples of same
   // document navigations are:
   // * reference fragment navigations
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm
index edd8ad3..e2dd64038 100644
--- a/ios/web/test/web_int_test.mm
+++ b/ios/web/test/web_int_test.mm
@@ -104,6 +104,7 @@
 void WebIntTest::LoadUrl(const GURL& url) {
   ExecuteBlockAndWaitForLoad(url, ^{
     web::NavigationManager::WebLoadParams params(url);
+    params.transition_type = ui::PageTransition::PAGE_TRANSITION_TYPED;
     navigation_manager()->LoadURLWithParams(params);
   });
 }
diff --git a/ios/web/web_state/navigation_callbacks_inttest.mm b/ios/web/web_state/navigation_callbacks_inttest.mm
index cee1fd5..085212aa 100644
--- a/ios/web/web_state/navigation_callbacks_inttest.mm
+++ b/ios/web/web_state/navigation_callbacks_inttest.mm
@@ -16,6 +16,7 @@
 #import "ios/web/test/web_int_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 #include "url/scheme_host_port.h"
 
@@ -33,6 +34,9 @@
   ASSERT_TRUE(*context);
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(
+      PageTransitionCoreTypeIs(ui::PageTransition::PAGE_TRANSITION_TYPED,
+                               (*context)->GetPageTransition()));
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   ASSERT_FALSE((*context)->GetResponseHeaders());
@@ -50,6 +54,9 @@
   ASSERT_TRUE((*context));
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(
+      PageTransitionCoreTypeIs(ui::PageTransition::PAGE_TRANSITION_TYPED,
+                               (*context)->GetPageTransition()));
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   ASSERT_TRUE((*context)->GetResponseHeaders());
@@ -65,11 +72,17 @@
 // Verifies correctness of |NavigationContext| (|arg0|) for same page navigation
 // passed to |DidFinishNavigation|. Stores |NavigationContext| in |context|
 // pointer.
-ACTION_P3(VerifySameDocumentStartedContext, web_state, url, context) {
+ACTION_P4(VerifySameDocumentStartedContext,
+          web_state,
+          url,
+          context,
+          page_transition) {
   *context = arg0;
   ASSERT_TRUE(*context);
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      page_transition, (*context)->GetPageTransition()));
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
@@ -78,11 +91,17 @@
 // Verifies correctness of |NavigationContext| (|arg0|) for same page navigation
 // passed to |DidFinishNavigation|. Asserts that |NavigationContext| the same as
 // |context|.
-ACTION_P3(VerifySameDocumentFinishedContext, web_state, url, context) {
+ACTION_P4(VerifySameDocumentFinishedContext,
+          web_state,
+          url,
+          context,
+          page_transition) {
   ASSERT_EQ(*context, arg0);
   ASSERT_TRUE(*context);
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      page_transition, (*context)->GetPageTransition()));
   EXPECT_TRUE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
@@ -100,6 +119,9 @@
   ASSERT_TRUE(*context);
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(
+      PageTransitionCoreTypeIs(ui::PageTransition::PAGE_TRANSITION_TYPED,
+                               (*context)->GetPageTransition()));
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
@@ -116,6 +138,9 @@
   ASSERT_TRUE(*context);
   EXPECT_EQ(web_state, (*context)->GetWebState());
   EXPECT_EQ(url, (*context)->GetUrl());
+  EXPECT_TRUE(
+      PageTransitionCoreTypeIs(ui::PageTransition::PAGE_TRANSITION_TYPED,
+                               (*context)->GetPageTransition()));
   EXPECT_FALSE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
@@ -184,18 +209,24 @@
   // Perform same-page navigation.
   const GURL hash_url = HttpServer::MakeUrl("http://chromium.test#1");
   EXPECT_CALL(*observer_, DidStartNavigation(_))
-      .WillOnce(
-          VerifySameDocumentStartedContext(web_state(), hash_url, &context));
+      .WillOnce(VerifySameDocumentStartedContext(
+          web_state(), hash_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_TYPED));
   EXPECT_CALL(*observer_, DidFinishNavigation(_))
-      .WillOnce(
-          VerifySameDocumentFinishedContext(web_state(), hash_url, &context));
+      .WillOnce(VerifySameDocumentFinishedContext(
+          web_state(), hash_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_TYPED));
   LoadUrl(hash_url);
 
   // Perform same-page navigation by going back.
   EXPECT_CALL(*observer_, DidStartNavigation(_))
-      .WillOnce(VerifySameDocumentStartedContext(web_state(), url, &context));
+      .WillOnce(VerifySameDocumentStartedContext(
+          web_state(), url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   EXPECT_CALL(*observer_, DidFinishNavigation(_))
-      .WillOnce(VerifySameDocumentFinishedContext(web_state(), url, &context));
+      .WillOnce(VerifySameDocumentFinishedContext(
+          web_state(), url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   ExecuteBlockAndWaitForLoad(url, ^{
     navigation_manager()->GoBack();
   });
@@ -219,11 +250,13 @@
   // Perform same-page navigation using JavaScript.
   const GURL hash_url = HttpServer::MakeUrl("http://chromium.test#1");
   EXPECT_CALL(*observer_, DidStartNavigation(_))
-      .WillOnce(
-          VerifySameDocumentStartedContext(web_state(), hash_url, &context));
+      .WillOnce(VerifySameDocumentStartedContext(
+          web_state(), hash_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   EXPECT_CALL(*observer_, DidFinishNavigation(_))
-      .WillOnce(
-          VerifySameDocumentFinishedContext(web_state(), hash_url, &context));
+      .WillOnce(VerifySameDocumentFinishedContext(
+          web_state(), hash_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   ExecuteJavaScript(@"window.location.hash = '#1'");
 }
 
@@ -245,21 +278,25 @@
   // Perform push state using JavaScript.
   const GURL push_url = HttpServer::MakeUrl("http://chromium.test/test.html");
   EXPECT_CALL(*observer_, DidStartNavigation(_))
-      .WillOnce(
-          VerifySameDocumentStartedContext(web_state(), push_url, &context));
+      .WillOnce(VerifySameDocumentStartedContext(
+          web_state(), push_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   EXPECT_CALL(*observer_, DidFinishNavigation(_))
-      .WillOnce(
-          VerifySameDocumentFinishedContext(web_state(), push_url, &context));
+      .WillOnce(VerifySameDocumentFinishedContext(
+          web_state(), push_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   ExecuteJavaScript(@"window.history.pushState('', 'Test', 'test.html')");
 
   // Perform replace state using JavaScript.
   const GURL replace_url = HttpServer::MakeUrl("http://chromium.test/1.html");
   EXPECT_CALL(*observer_, DidStartNavigation(_))
-      .WillOnce(
-          VerifySameDocumentStartedContext(web_state(), replace_url, &context));
+      .WillOnce(VerifySameDocumentStartedContext(
+          web_state(), replace_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   EXPECT_CALL(*observer_, DidFinishNavigation(_))
-      .WillOnce(VerifySameDocumentFinishedContext(web_state(), replace_url,
-                                                  &context));
+      .WillOnce(VerifySameDocumentFinishedContext(
+          web_state(), replace_url, &context,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT));
   ExecuteJavaScript(@"window.history.replaceState('', 'Test', '1.html')");
 }
 
diff --git a/ios/web/web_state/navigation_context_impl.h b/ios/web/web_state/navigation_context_impl.h
index 5ea8139..ebb6608 100644
--- a/ios/web/web_state/navigation_context_impl.h
+++ b/ios/web/web_state/navigation_context_impl.h
@@ -22,7 +22,8 @@
   // Response headers will ne null.
   static std::unique_ptr<NavigationContextImpl> CreateNavigationContext(
       WebState* web_state,
-      const GURL& url);
+      const GURL& url,
+      ui::PageTransition page_transition);
 
 #ifndef NDEBUG
   // Returns human readable description of this object.
@@ -32,6 +33,7 @@
   // NavigationContext overrides:
   WebState* GetWebState() override;
   const GURL& GetUrl() const override;
+  ui::PageTransition GetPageTransition() const override;
   bool IsSameDocument() const override;
   NSError* GetError() const override;
   net::HttpResponseHeaders* GetResponseHeaders() const override;
@@ -48,10 +50,13 @@
   void SetNavigationItemUniqueID(int unique_id);
 
  private:
-  NavigationContextImpl(WebState* web_state, const GURL& url);
+  NavigationContextImpl(WebState* web_state,
+                        const GURL& url,
+                        ui::PageTransition page_transition);
 
   WebState* web_state_ = nullptr;
   GURL url_;
+  ui::PageTransition page_transition_;
   bool is_same_document_ = false;
   base::scoped_nsobject<NSError> error_;
   scoped_refptr<net::HttpResponseHeaders> response_headers_;
diff --git a/ios/web/web_state/navigation_context_impl.mm b/ios/web/web_state/navigation_context_impl.mm
index 5e971304..80a09c4 100644
--- a/ios/web/web_state/navigation_context_impl.mm
+++ b/ios/web/web_state/navigation_context_impl.mm
@@ -13,10 +13,12 @@
 
 // static
 std::unique_ptr<NavigationContextImpl>
-NavigationContextImpl::CreateNavigationContext(WebState* web_state,
-                                               const GURL& url) {
+NavigationContextImpl::CreateNavigationContext(
+    WebState* web_state,
+    const GURL& url,
+    ui::PageTransition page_transition) {
   std::unique_ptr<NavigationContextImpl> result(
-      new NavigationContextImpl(web_state, url));
+      new NavigationContextImpl(web_state, url, page_transition));
   return result;
 }
 
@@ -38,6 +40,10 @@
   return url_;
 }
 
+ui::PageTransition NavigationContextImpl::GetPageTransition() const {
+  return page_transition_;
+}
+
 bool NavigationContextImpl::IsSameDocument() const {
   return is_same_document_;
 }
@@ -72,9 +78,11 @@
 }
 
 NavigationContextImpl::NavigationContextImpl(WebState* web_state,
-                                             const GURL& url)
+                                             const GURL& url,
+                                             ui::PageTransition page_transition)
     : web_state_(web_state),
       url_(url),
+      page_transition_(page_transition),
       is_same_document_(false),
       error_(nil),
       response_headers_(nullptr) {}
diff --git a/ios/web/web_state/navigation_context_impl_unittest.mm b/ios/web/web_state/navigation_context_impl_unittest.mm
index 7566deb..9729d51 100644
--- a/ios/web/web_state/navigation_context_impl_unittest.mm
+++ b/ios/web/web_state/navigation_context_impl_unittest.mm
@@ -33,10 +33,14 @@
 // Tests CreateNavigationContext factory method.
 TEST_F(NavigationContextImplTest, NavigationContext) {
   std::unique_ptr<NavigationContext> context =
-      NavigationContextImpl::CreateNavigationContext(&web_state_, url_);
+      NavigationContextImpl::CreateNavigationContext(
+          &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK);
   ASSERT_TRUE(context);
 
   EXPECT_EQ(&web_state_, context->GetWebState());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      context->GetPageTransition(),
+      ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK));
   EXPECT_EQ(url_, context->GetUrl());
   EXPECT_FALSE(context->IsSameDocument());
   EXPECT_FALSE(context->GetError());
@@ -46,7 +50,8 @@
 // Tests NavigationContextImpl Setters.
 TEST_F(NavigationContextImplTest, Setters) {
   std::unique_ptr<NavigationContextImpl> context =
-      NavigationContextImpl::CreateNavigationContext(&web_state_, url_);
+      NavigationContextImpl::CreateNavigationContext(
+          &web_state_, url_, ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK);
   ASSERT_TRUE(context);
 
   ASSERT_FALSE(context->IsSameDocument());
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 77d6a767..a47f2f09c 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1340,7 +1340,7 @@
                   transition:(ui::PageTransition)transition {
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(_webStateImpl,
-                                                          pageURL);
+                                                          pageURL, transition);
   _webStateImpl->OnNavigationStarted(context.get());
   [[self sessionController] pushNewItemWithURL:pageURL
                                    stateObject:stateObject
@@ -1353,8 +1353,9 @@
 - (void)replaceStateWithPageURL:(const GURL&)pageURL
                     stateObject:(NSString*)stateObject {
   std::unique_ptr<web::NavigationContextImpl> context =
-      web::NavigationContextImpl::CreateNavigationContext(_webStateImpl,
-                                                          pageURL);
+      web::NavigationContextImpl::CreateNavigationContext(
+          _webStateImpl, pageURL,
+          ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT);
   _webStateImpl->OnNavigationStarted(context.get());
   [[self sessionController] updateCurrentItemWithURL:pageURL
                                          stateObject:stateObject];
@@ -1529,8 +1530,8 @@
         web::NavigationManager::UserAgentOverrideOption::INHERIT);
   }
   std::unique_ptr<web::NavigationContextImpl> context =
-      web::NavigationContextImpl::CreateNavigationContext(_webStateImpl,
-                                                          requestURL);
+      web::NavigationContextImpl::CreateNavigationContext(
+          _webStateImpl, requestURL, transition);
 
   web::NavigationItem* item = self.navigationManagerImpl->GetPendingItem();
   // TODO(crbug.com/676129): AddPendingItem does not always create a pending
@@ -4176,17 +4177,18 @@
   [_navigationStates setState:web::WKNavigationState::REQUESTED
                 forNavigation:navigation];
   std::unique_ptr<web::NavigationContextImpl> context;
+  const ui::PageTransition loadHTMLTransition =
+      ui::PageTransition::PAGE_TRANSITION_TYPED;
   if (_webStateImpl->HasWebUI()) {
     // WebUI uses |loadHTML:forURL:| to feed the content to web view. This
     // should not be treated as a navigation, but WKNavigationDelegate callbacks
     // still expect a valid context.
-    context =
-        web::NavigationContextImpl::CreateNavigationContext(_webStateImpl, URL);
+    context = web::NavigationContextImpl::CreateNavigationContext(
+        _webStateImpl, URL, loadHTMLTransition);
   } else {
-    context = [self
-        registerLoadRequestForURL:URL
-                         referrer:web::Referrer()
-                       transition:ui::PageTransition::PAGE_TRANSITION_TYPED];
+    context = [self registerLoadRequestForURL:URL
+                                     referrer:web::Referrer()
+                                   transition:loadHTMLTransition];
   }
   [_navigationStates setContext:std::move(context) forNavigation:navigation];
 }
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
index 600b692d..d6988e8 100644
--- a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
+++ b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
@@ -69,8 +69,9 @@
 
   // navigation_3 is added later and hence the latest.
   std::unique_ptr<web::NavigationContextImpl> context =
-      NavigationContextImpl::CreateNavigationContext(nullptr /*web_state*/,
-                                                     GURL(kTestUrl1));
+      NavigationContextImpl::CreateNavigationContext(
+          nullptr /*web_state*/, GURL(kTestUrl1),
+          ui::PageTransition::PAGE_TRANSITION_SERVER_REDIRECT);
   [states_ setContext:std::move(context) forNavigation:navigation3_];
   EXPECT_EQ(navigation3_, [states_ lastAddedNavigation]);
   EXPECT_EQ(WKNavigationState::NONE, [states_ lastAddedNavigationState]);
@@ -84,8 +85,9 @@
 
   // Add first context.
   std::unique_ptr<web::NavigationContextImpl> context1 =
-      NavigationContextImpl::CreateNavigationContext(nullptr /*web_state*/,
-                                                     GURL(kTestUrl1));
+      NavigationContextImpl::CreateNavigationContext(
+          nullptr /*web_state*/, GURL(kTestUrl1),
+          ui::PageTransition::PAGE_TRANSITION_RELOAD);
   context1->SetIsSameDocument(true);
   [states_ setContext:std::move(context1) forNavigation:navigation1_];
   EXPECT_FALSE([states_ contextForNavigation:navigation2_]);
@@ -98,8 +100,9 @@
 
   // Replace existing context.
   std::unique_ptr<web::NavigationContextImpl> context2 =
-      NavigationContextImpl::CreateNavigationContext(nullptr /*web_state*/,
-                                                     GURL(kTestUrl2));
+      NavigationContextImpl::CreateNavigationContext(
+          nullptr /*web_state*/, GURL(kTestUrl2),
+          ui::PageTransition::PAGE_TRANSITION_GENERATED);
   NSError* error = [[[NSError alloc] init] autorelease];
   context2->SetError(error);
   [states_ setContext:std::move(context2) forNavigation:navigation1_];
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm
index 58dee9b..e919761 100644
--- a/ios/web/web_state/web_state_impl_unittest.mm
+++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -350,7 +350,9 @@
   ASSERT_FALSE(observer->did_finish_navigation_info());
   const GURL url("http://test");
   std::unique_ptr<web::NavigationContext> context =
-      NavigationContextImpl::CreateNavigationContext(web_state_.get(), url);
+      NavigationContextImpl::CreateNavigationContext(
+          web_state_.get(), url,
+          ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK);
   web_state_->OnNavigationFinished(context.get());
   ASSERT_TRUE(observer->did_finish_navigation_info());
   EXPECT_EQ(web_state_.get(),
@@ -358,6 +360,8 @@
   NavigationContext* actual_context =
       observer->did_finish_navigation_info()->context.get();
   EXPECT_EQ(context->GetUrl(), actual_context->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      context->GetPageTransition(), actual_context->GetPageTransition()));
   EXPECT_FALSE(actual_context->IsSameDocument());
   EXPECT_FALSE(actual_context->GetError());
   EXPECT_FALSE(actual_context->GetResponseHeaders());
@@ -369,6 +373,8 @@
   EXPECT_EQ(web_state_.get(), observer->did_start_navigation_info()->web_state);
   actual_context = observer->did_start_navigation_info()->context.get();
   EXPECT_EQ(context->GetUrl(), actual_context->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      context->GetPageTransition(), actual_context->GetPageTransition()));
   EXPECT_FALSE(actual_context->IsSameDocument());
   EXPECT_FALSE(actual_context->GetError());
   EXPECT_FALSE(actual_context->GetResponseHeaders());
diff --git a/ios/web/web_state/web_state_observer_bridge_unittest.mm b/ios/web/web_state/web_state_observer_bridge_unittest.mm
index 38daf32b..9b19baa 100644
--- a/ios/web/web_state/web_state_observer_bridge_unittest.mm
+++ b/ios/web/web_state/web_state_observer_bridge_unittest.mm
@@ -44,8 +44,9 @@
 
   GURL url("https://chromium.test/");
   std::unique_ptr<web::NavigationContext> context =
-      web::NavigationContextImpl::CreateNavigationContext(&test_web_state_,
-                                                          url);
+      web::NavigationContextImpl::CreateNavigationContext(
+          &test_web_state_, url,
+          ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK);
   bridge_->DidStartNavigation(context.get());
 
   ASSERT_TRUE([observer_ didStartNavigationInfo]);
@@ -57,6 +58,9 @@
   EXPECT_EQ(context->IsSameDocument(), actual_context->IsSameDocument());
   EXPECT_EQ(context->GetError(), actual_context->GetError());
   EXPECT_EQ(context->GetUrl(), actual_context->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK,
+      actual_context->GetPageTransition()));
   EXPECT_EQ(context->GetResponseHeaders(),
             actual_context->GetResponseHeaders());
 }
@@ -67,8 +71,9 @@
 
   GURL url("https://chromium.test/");
   std::unique_ptr<web::NavigationContext> context =
-      web::NavigationContextImpl::CreateNavigationContext(&test_web_state_,
-                                                          url);
+      web::NavigationContextImpl::CreateNavigationContext(
+          &test_web_state_, url,
+          ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR);
   bridge_->DidFinishNavigation(context.get());
 
   ASSERT_TRUE([observer_ didFinishNavigationInfo]);
@@ -80,6 +85,9 @@
   EXPECT_EQ(context->IsSameDocument(), actual_context->IsSameDocument());
   EXPECT_EQ(context->GetError(), actual_context->GetError());
   EXPECT_EQ(context->GetUrl(), actual_context->GetUrl());
+  EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
+      ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR,
+      actual_context->GetPageTransition()));
   EXPECT_EQ(context->GetResponseHeaders(),
             actual_context->GetResponseHeaders());
 }
diff --git a/ios/web/webui/crw_web_ui_manager_unittest.mm b/ios/web/webui/crw_web_ui_manager_unittest.mm
index fd9d107..22a1043 100644
--- a/ios/web/webui/crw_web_ui_manager_unittest.mm
+++ b/ios/web/webui/crw_web_ui_manager_unittest.mm
@@ -148,8 +148,9 @@
   GURL url(kTestWebUIUrl);
   EXPECT_CALL(*web_state_impl_, LoadWebUIHtml(html, url));
   std::unique_ptr<web::NavigationContext> context =
-      NavigationContextImpl::CreateNavigationContext(web_state_impl_.get(),
-                                                     url);
+      NavigationContextImpl::CreateNavigationContext(
+          web_state_impl_.get(), url,
+          ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK);
   web_state_impl_->OnNavigationStarted(context.get());
 }
 
diff --git a/media/capture/video/video_capture_system.h b/media/capture/video/video_capture_system.h
index 3897a20d..81257fe7 100644
--- a/media/capture/video/video_capture_system.h
+++ b/media/capture/video/video_capture_system.h
@@ -21,7 +21,8 @@
 
   // The passed-in |result_callback| must have ownership of the called
   // VideoCaptureSystem instance to guarantee that it stays alive during the
-  // asynchronous operation.
+  // asynchronous operation. |result_callback| is invoked on the same thread
+  // that calls GetDeviceInfosAsync()
   virtual void GetDeviceInfosAsync(
       const DeviceInfoCallback& result_callback) = 0;
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 74dd238..fa4ef1b 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -36,6 +36,7 @@
 
 use_v8_in_net = !is_ios && !is_proto_quic
 enable_built_in_dns = !is_ios && !is_proto_quic
+enable_net_mojo = !is_ios && !is_android && !is_proto_quic
 
 # True if certificates are represented with DER byte buffers. This can be true
 # in addition to use_openssl_certs or use_nss_certs, in that case byte certs
@@ -2494,6 +2495,8 @@
     "test/embedded_test_server/http_response.h",
     "test/embedded_test_server/request_handler_util.cc",
     "test/embedded_test_server/request_handler_util.h",
+    "test/embedded_test_server/simple_connection_listener.cc",
+    "test/embedded_test_server/simple_connection_listener.h",
     "test/event_waiter.h",
     "test/gtest_util.h",
     "test/net_test_suite.cc",
@@ -2636,7 +2639,7 @@
   }
 }
 
-if (!is_ios && !is_android && !is_proto_quic) {
+if (enable_net_mojo) {
   source_set("net_browser_services") {
     sources = [
       "dns/mojo_host_resolver_impl.cc",
@@ -2680,6 +2683,33 @@
   }
 }
 
+if (use_v8_in_net) {
+  source_set("net_context_builder_with_v8") {
+    sources = [
+      "url_request/url_request_context_builder_v8.cc",
+      "url_request/url_request_context_builder_v8.h",
+    ]
+
+    defines = []
+
+    deps = [
+      ":net",
+      ":net_with_v8",
+      "//base",
+    ]
+
+    if (enable_net_mojo) {
+      deps += [
+        ":net_browser_services",
+        "//mojo/public/cpp/bindings",
+        "//net/interfaces",
+      ]
+
+      defines += [ "ENABLE_NET_MOJO" ]
+    }
+  }
+}
+
 if (!is_ios && !is_android) {
   executable("cert_verify_tool") {
     testonly = true
@@ -4560,6 +4590,8 @@
     "proxy/proxy_server_unittest.cc",
     "proxy/proxy_service_mojo_unittest.cc",
     "proxy/proxy_service_unittest.cc",
+    "proxy/test_mojo_proxy_resolver_factory.cc",
+    "proxy/test_mojo_proxy_resolver_factory.h",
     "quic/chromium/bidirectional_stream_quic_impl_unittest.cc",
     "quic/chromium/crypto/proof_test_chromium.cc",
     "quic/chromium/crypto/proof_verifier_chromium_test.cc",
@@ -4896,6 +4928,7 @@
     "url_request/url_fetcher_impl_unittest.cc",
     "url_request/url_fetcher_response_writer_unittest.cc",
     "url_request/url_request_context_builder_unittest.cc",
+    "url_request/url_request_context_builder_v8_unittest.cc",
     "url_request/url_request_context_unittest.cc",
     "url_request/url_request_data_job_unittest.cc",
     "url_request/url_request_file_dir_job_unittest.cc",
@@ -5155,21 +5188,27 @@
   }
 
   if (use_v8_in_net) {
-    deps += [ ":net_with_v8" ]
+    deps += [
+      ":net_context_builder_with_v8",
+      ":net_with_v8",
+    ]
   } else {
     sources -= [
       "proxy/proxy_resolver_v8_tracing_unittest.cc",
       "proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc",
       "proxy/proxy_resolver_v8_unittest.cc",
+      "url_request/url_request_context_builder_v8_unittest.cc",
     ]
   }
 
-  if (use_v8_in_net && !is_android) {
+  if (enable_net_mojo) {
     deps += [
       ":net_browser_services",
       ":net_utility_services",
       "//mojo/edk/system",
     ]
+
+    defines += [ "ENABLE_NET_MOJO" ]
   } else {
     sources -= [
       "dns/host_resolver_mojo_unittest.cc",
@@ -5179,6 +5218,8 @@
       "proxy/mojo_proxy_resolver_v8_tracing_bindings_unittest.cc",
       "proxy/proxy_resolver_factory_mojo_unittest.cc",
       "proxy/proxy_service_mojo_unittest.cc",
+      "proxy/test_mojo_proxy_resolver_factory.cc",
+      "proxy/test_mojo_proxy_resolver_factory.h",
     ]
   }
 
diff --git a/net/base/layered_network_delegate.cc b/net/base/layered_network_delegate.cc
index f99d6e1..41c22c1 100644
--- a/net/base/layered_network_delegate.cc
+++ b/net/base/layered_network_delegate.cc
@@ -254,4 +254,44 @@
         const GURL& referrer_url) const {
 }
 
+bool LayeredNetworkDelegate::OnCanQueueReportingReport(
+    const url::Origin& origin) const {
+  OnCanQueueReportingReportInternal(origin);
+  return nested_network_delegate_->CanQueueReportingReport(origin);
+}
+
+void LayeredNetworkDelegate::OnCanQueueReportingReportInternal(
+    const url::Origin& origin) const {}
+
+bool LayeredNetworkDelegate::OnCanSendReportingReport(
+    const url::Origin& origin) const {
+  OnCanSendReportingReportInternal(origin);
+  return nested_network_delegate_->CanSendReportingReport(origin);
+}
+
+void LayeredNetworkDelegate::OnCanSendReportingReportInternal(
+    const url::Origin& origin) const {}
+
+bool LayeredNetworkDelegate::OnCanSetReportingClient(
+    const url::Origin& origin,
+    const GURL& endpoint) const {
+  OnCanSetReportingClientInternal(origin, endpoint);
+  return nested_network_delegate_->CanSetReportingClient(origin, endpoint);
+}
+
+void LayeredNetworkDelegate::OnCanSetReportingClientInternal(
+    const url::Origin& origin,
+    const GURL& endpoint) const {}
+
+bool LayeredNetworkDelegate::OnCanUseReportingClient(
+    const url::Origin& origin,
+    const GURL& endpoint) const {
+  OnCanUseReportingClientInternal(origin, endpoint);
+  return nested_network_delegate_->CanUseReportingClient(origin, endpoint);
+}
+
+void LayeredNetworkDelegate::OnCanUseReportingClientInternal(
+    const url::Origin& origin,
+    const GURL& endpoint) const {}
+
 }  // namespace net
diff --git a/net/base/layered_network_delegate.h b/net/base/layered_network_delegate.h
index 1666d86a..562ca0f7 100644
--- a/net/base/layered_network_delegate.h
+++ b/net/base/layered_network_delegate.h
@@ -87,6 +87,16 @@
       const GURL& target_url,
       const GURL& referrer_url) const final;
 
+  bool OnCanQueueReportingReport(const url::Origin& origin) const final;
+
+  bool OnCanSendReportingReport(const url::Origin& origin) const final;
+
+  bool OnCanSetReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const final;
+
+  bool OnCanUseReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const final;
+
  protected:
   virtual void OnBeforeURLRequestInternal(URLRequest* request,
                                           const CompletionCallback& callback,
@@ -157,6 +167,18 @@
       const GURL& target_url,
       const GURL& referrer_url) const;
 
+  virtual void OnCanQueueReportingReportInternal(
+      const url::Origin& origin) const;
+
+  virtual void OnCanSendReportingReportInternal(
+      const url::Origin& origin) const;
+
+  virtual void OnCanSetReportingClientInternal(const url::Origin& origin,
+                                               const GURL& endpoint) const;
+
+  virtual void OnCanUseReportingClientInternal(const url::Origin& origin,
+                                               const GURL& endpoint) const;
+
  private:
   std::unique_ptr<NetworkDelegate> nested_network_delegate_;
 };
diff --git a/net/base/layered_network_delegate_unittest.cc b/net/base/layered_network_delegate_unittest.cc
index cd9f5d24..b92ee03 100644
--- a/net/base/layered_network_delegate_unittest.cc
+++ b/net/base/layered_network_delegate_unittest.cc
@@ -335,6 +335,30 @@
                       "violating_referrer_header_count"]);
   }
 
+  void OnCanQueueReportingReportInternal(
+      const url::Origin& origin) const override {
+    ++(*counters_)["on_can_queue_reporting_report_count"];
+    EXPECT_EQ(1, (*counters_)["on_can_queue_reporting_report_count"]);
+  }
+
+  void OnCanSendReportingReportInternal(
+      const url::Origin& origin) const override {
+    ++(*counters_)["on_can_send_reporting_report_count"];
+    EXPECT_EQ(1, (*counters_)["on_can_send_reporting_report_count"]);
+  }
+
+  void OnCanSetReportingClientInternal(const url::Origin& origin,
+                                       const GURL& endpoint) const override {
+    ++(*counters_)["on_can_set_reporting_client_count"];
+    EXPECT_EQ(1, (*counters_)["on_can_set_reporting_client_count"]);
+  }
+
+  void OnCanUseReportingClientInternal(const url::Origin& origin,
+                                       const GURL& endpoint) const override {
+    ++(*counters_)["on_can_use_reporting_client_count"];
+    EXPECT_EQ(1, (*counters_)["on_can_use_reporting_client_count"]);
+  }
+
  private:
   TestURLRequestContext context_;
   TestDelegate delegate_;
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index 960f05f..6344e4d 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -185,6 +185,28 @@
       request, target_url, referrer_url);
 }
 
+bool NetworkDelegate::CanQueueReportingReport(const url::Origin& origin) const {
+  DCHECK(CalledOnValidThread());
+  return OnCanQueueReportingReport(origin);
+}
+
+bool NetworkDelegate::CanSendReportingReport(const url::Origin& origin) const {
+  DCHECK(CalledOnValidThread());
+  return OnCanSendReportingReport(origin);
+}
+
+bool NetworkDelegate::CanSetReportingClient(const url::Origin& origin,
+                                            const GURL& endpoint) const {
+  DCHECK(CalledOnValidThread());
+  return OnCanSetReportingClient(origin, endpoint);
+}
+
+bool NetworkDelegate::CanUseReportingClient(const url::Origin& origin,
+                                            const GURL& endpoint) const {
+  DCHECK(CalledOnValidThread());
+  return OnCanUseReportingClient(origin, endpoint);
+}
+
 void NetworkDelegate::OnResponseStarted(URLRequest* request, int net_error) {
   OnResponseStarted(request);
 }
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index f602f3c..eaa1e30 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -24,6 +24,10 @@
 class FilePath;
 }
 
+namespace url {
+class Origin;
+}
+
 namespace net {
 
 // NOTE: Layering violations!
@@ -112,6 +116,13 @@
       const GURL& target_url,
       const GURL& referrer_url) const;
 
+  bool CanQueueReportingReport(const url::Origin& origin) const;
+  bool CanSendReportingReport(const url::Origin& origin) const;
+  bool CanSetReportingClient(const url::Origin& origin,
+                             const GURL& endpoint) const;
+  bool CanUseReportingClient(const url::Origin& origin,
+                             const GURL& endpoint) const;
+
  private:
   // This is the interface for subclasses of NetworkDelegate to implement. These
   // member functions will be called by the respective public notification
@@ -292,6 +303,16 @@
       const URLRequest& request,
       const GURL& target_url,
       const GURL& referrer_url) const = 0;
+
+  virtual bool OnCanQueueReportingReport(const url::Origin& origin) const = 0;
+
+  virtual bool OnCanSendReportingReport(const url::Origin& origin) const = 0;
+
+  virtual bool OnCanSetReportingClient(const url::Origin& origin,
+                                       const GURL& endpoint) const = 0;
+
+  virtual bool OnCanUseReportingClient(const url::Origin& origin,
+                                       const GURL& endpoint) const = 0;
 };
 
 }  // namespace net
diff --git a/net/base/network_delegate_impl.cc b/net/base/network_delegate_impl.cc
index 52d4efc..3ca66c1 100644
--- a/net/base/network_delegate_impl.cc
+++ b/net/base/network_delegate_impl.cc
@@ -114,4 +114,24 @@
   return false;
 }
 
+bool NetworkDelegateImpl::OnCanQueueReportingReport(
+    const url::Origin& origin) const {
+  return true;
+}
+
+bool NetworkDelegateImpl::OnCanSendReportingReport(
+    const url::Origin& origin) const {
+  return true;
+}
+
+bool NetworkDelegateImpl::OnCanSetReportingClient(const url::Origin& origin,
+                                                  const GURL& endpoint) const {
+  return true;
+}
+
+bool NetworkDelegateImpl::OnCanUseReportingClient(const url::Origin& origin,
+                                                  const GURL& endpoint) const {
+  return true;
+}
+
 }  // namespace net
diff --git a/net/base/network_delegate_impl.h b/net/base/network_delegate_impl.h
index a46942a..16f2d603 100644
--- a/net/base/network_delegate_impl.h
+++ b/net/base/network_delegate_impl.h
@@ -20,6 +20,10 @@
 class FilePath;
 }
 
+namespace url {
+class Origin;
+}
+
 namespace net {
 
 class CookieOptions;
@@ -98,6 +102,16 @@
       const URLRequest& request,
       const GURL& target_url,
       const GURL& referrer_url) const override;
+
+  bool OnCanQueueReportingReport(const url::Origin& origin) const override;
+
+  bool OnCanSendReportingReport(const url::Origin& origin) const override;
+
+  bool OnCanSetReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const override;
+
+  bool OnCanUseReportingClient(const url::Origin& origin,
+                               const GURL& endpoint) const override;
 };
 
 }  // namespace net
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index c1bebe74..a1a7e5e 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -39,7 +39,7 @@
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
+#include "net/test/embedded_test_server/simple_connection_listener.h"
 #include "net/test/gtest_util.h"
 #include "net/url_request/url_request_context_storage.h"
 #include "net/url_request/url_request_file_job.h"
@@ -74,36 +74,6 @@
   base::string16 text;
 };
 
-// Waits for the specified number of connection attempts to be seen.
-class WaitForConnectionsListener
-    : public test_server::EmbeddedTestServerConnectionListener {
- public:
-  explicit WaitForConnectionsListener(int expected_num_connections)
-      : expected_num_connections_(expected_num_connections),
-        task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
-
-  void AcceptedSocket(const StreamSocket& socket) override {
-    ++seen_connections_;
-    EXPECT_LE(seen_connections_, expected_num_connections_);
-    if (expected_num_connections_ == seen_connections_)
-      task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
-  }
-
-  void ReadFromSocket(const StreamSocket& socket, int rv) override {}
-
-  void Wait() { run_loop_.Run(); }
-
- private:
-  int seen_connections_ = 0;
-  int expected_num_connections_;
-
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(WaitForConnectionsListener);
-};
-
 // A non-mock URL request which can access http:// and file:// urls, in the case
 // the tests were built with file support.
 class RequestContext : public URLRequestContext {
@@ -543,7 +513,9 @@
   int num_requests = 10 + ClientSocketPoolManager::max_sockets_per_pool(
                               HttpNetworkSession::NORMAL_SOCKET_POOL);
 
-  WaitForConnectionsListener connection_listener(num_requests);
+  net::test_server::SimpleConnectionListener connection_listener(
+      num_requests, net::test_server::SimpleConnectionListener::
+                        FAIL_ON_ADDITIONAL_CONNECTIONS);
   test_server_.SetConnectionListener(&connection_listener);
   ASSERT_TRUE(test_server_.Start());
 
@@ -562,7 +534,7 @@
     pac_fetchers.push_back(std::move(pac_fetcher));
   }
 
-  connection_listener.Wait();
+  connection_listener.WaitForConnections();
   // None of the callbacks should have been invoked - all jobs should still be
   // hung.
   EXPECT_FALSE(callback.have_result());
diff --git a/net/proxy/proxy_service_mojo_unittest.cc b/net/proxy/proxy_service_mojo_unittest.cc
index d2b3526f..46338339 100644
--- a/net/proxy/proxy_service_mojo_unittest.cc
+++ b/net/proxy/proxy_service_mojo_unittest.cc
@@ -11,10 +11,8 @@
 
 #include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/singleton.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/base/network_delegate_impl.h"
 #include "net/base/test_completion_callback.h"
 #include "net/dns/mock_host_resolver.h"
@@ -25,9 +23,9 @@
 #include "net/proxy/dhcp_proxy_script_fetcher.h"
 #include "net/proxy/mock_proxy_script_fetcher.h"
 #include "net/proxy/mojo_proxy_resolver_factory.h"
-#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/proxy/proxy_service.h"
+#include "net/proxy/test_mojo_proxy_resolver_factory.h"
 #include "net/test/event_waiter.h"
 #include "net/test/gtest_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -124,34 +122,6 @@
   }
 };
 
-class InProcessMojoProxyResolverFactory : public MojoProxyResolverFactory {
- public:
-  static InProcessMojoProxyResolverFactory* GetInstance() {
-    return base::Singleton<InProcessMojoProxyResolverFactory>::get();
-  }
-
-  // Overridden from MojoProxyResolverFactory:
-  std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
-      const std::string& pac_script,
-      mojo::InterfaceRequest<interfaces::ProxyResolver> req,
-      interfaces::ProxyResolverFactoryRequestClientPtr client) override {
-    factory_->CreateResolver(pac_script, std::move(req), std::move(client));
-    return nullptr;
-  }
-
- private:
-  InProcessMojoProxyResolverFactory() {
-    mojo::MakeStrongBinding(base::MakeUnique<MojoProxyResolverFactoryImpl>(),
-                            mojo::MakeRequest(&factory_));
-  }
-  ~InProcessMojoProxyResolverFactory() override = default;
-  friend struct base::DefaultSingletonTraits<InProcessMojoProxyResolverFactory>;
-
-  interfaces::ProxyResolverFactoryPtr factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(InProcessMojoProxyResolverFactory);
-};
-
 }  // namespace
 
 class ProxyServiceMojoTest : public testing::Test,
@@ -172,7 +142,7 @@
       const std::string& pac_script,
       mojo::InterfaceRequest<interfaces::ProxyResolver> req,
       interfaces::ProxyResolverFactoryRequestClientPtr client) override {
-    InProcessMojoProxyResolverFactory::GetInstance()->CreateResolver(
+    TestMojoProxyResolverFactory::GetInstance()->CreateResolver(
         pac_script, std::move(req), std::move(client));
     return base::MakeUnique<base::ScopedClosureRunner>(
         on_delete_closure_.closure());
diff --git a/net/proxy/test_mojo_proxy_resolver_factory.cc b/net/proxy/test_mojo_proxy_resolver_factory.cc
new file mode 100644
index 0000000..9a0223a2
--- /dev/null
+++ b/net/proxy/test_mojo_proxy_resolver_factory.cc
@@ -0,0 +1,34 @@
+// 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 "net/proxy/test_mojo_proxy_resolver_factory.h"
+
+#include "base/memory/ptr_util.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
+
+namespace net {
+
+TestMojoProxyResolverFactory* TestMojoProxyResolverFactory::GetInstance() {
+  return base::Singleton<TestMojoProxyResolverFactory>::get();
+}
+
+std::unique_ptr<base::ScopedClosureRunner>
+TestMojoProxyResolverFactory::CreateResolver(
+    const std::string& pac_script,
+    mojo::InterfaceRequest<interfaces::ProxyResolver> req,
+    interfaces::ProxyResolverFactoryRequestClientPtr client) {
+  resolver_created_ = true;
+  factory_->CreateResolver(pac_script, std::move(req), std::move(client));
+  return nullptr;
+}
+
+TestMojoProxyResolverFactory::TestMojoProxyResolverFactory() {
+  mojo::MakeStrongBinding(base::MakeUnique<MojoProxyResolverFactoryImpl>(),
+                          mojo::MakeRequest(&factory_));
+}
+
+TestMojoProxyResolverFactory::~TestMojoProxyResolverFactory() = default;
+
+}  // namespace net
diff --git a/net/proxy/test_mojo_proxy_resolver_factory.h b/net/proxy/test_mojo_proxy_resolver_factory.h
new file mode 100644
index 0000000..7be0be4
--- /dev/null
+++ b/net/proxy/test_mojo_proxy_resolver_factory.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_PROXY_TEST_MOJO_PROXY_RESOLVER_FACTORY_H_
+#define NET_PROXY_TEST_MOJO_PROXY_RESOLVER_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "net/proxy/mojo_proxy_resolver_factory.h"
+
+namespace net {
+
+// MojoProxyResolverFactory that runs PAC scripts in-process, for tests.
+class TestMojoProxyResolverFactory : public MojoProxyResolverFactory {
+ public:
+  static TestMojoProxyResolverFactory* GetInstance();
+
+  // Returns true if CreateResolver was called.
+  bool resolver_created() { return resolver_created_; }
+
+  // Sets the value returned by resolver_created. Since this is a singleton,
+  // Serves to avoid with test fixture reuse.
+  void set_resolver_created(bool resolver_created) {
+    resolver_created_ = resolver_created;
+  }
+
+  // Overridden from MojoProxyResolverFactory:
+  std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
+      const std::string& pac_script,
+      mojo::InterfaceRequest<interfaces::ProxyResolver> req,
+      interfaces::ProxyResolverFactoryRequestClientPtr client) override;
+
+ private:
+  TestMojoProxyResolverFactory();
+  ~TestMojoProxyResolverFactory() override;
+
+  friend struct base::DefaultSingletonTraits<TestMojoProxyResolverFactory>;
+
+  interfaces::ProxyResolverFactoryPtr factory_;
+
+  bool resolver_created_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(TestMojoProxyResolverFactory);
+};
+
+}  // namespace net
+
+#endif  // NET_PROXY_TEST_MOJO_PROXY_RESOLVER_FACTORY_H_
diff --git a/net/reporting/reporting_context.cc b/net/reporting/reporting_context.cc
index f8b3820..6d022be4 100644
--- a/net/reporting/reporting_context.cc
+++ b/net/reporting/reporting_context.cc
@@ -40,7 +40,8 @@
       : ReportingContext(policy,
                          base::MakeUnique<base::DefaultClock>(),
                          base::MakeUnique<base::DefaultTickClock>(),
-                         ReportingUploader::Create(request_context)) {}
+                         ReportingUploader::Create(request_context),
+                         ReportingDelegate::Create(request_context)) {}
 };
 
 }  // namespace
@@ -72,12 +73,13 @@
 ReportingContext::ReportingContext(const ReportingPolicy& policy,
                                    std::unique_ptr<base::Clock> clock,
                                    std::unique_ptr<base::TickClock> tick_clock,
-                                   std::unique_ptr<ReportingUploader> uploader)
+                                   std::unique_ptr<ReportingUploader> uploader,
+                                   std::unique_ptr<ReportingDelegate> delegate)
     : policy_(policy),
       clock_(std::move(clock)),
       tick_clock_(std::move(tick_clock)),
       uploader_(std::move(uploader)),
-      delegate_(ReportingDelegate::Create()),
+      delegate_(std::move(delegate)),
       cache_(base::MakeUnique<ReportingCache>(this)),
       endpoint_manager_(base::MakeUnique<ReportingEndpointManager>(this)),
       delivery_agent_(ReportingDeliveryAgent::Create(this)),
diff --git a/net/reporting/reporting_context.h b/net/reporting/reporting_context.h
index c3517da..4467cb0 100644
--- a/net/reporting/reporting_context.h
+++ b/net/reporting/reporting_context.h
@@ -72,7 +72,8 @@
   ReportingContext(const ReportingPolicy& policy,
                    std::unique_ptr<base::Clock> clock,
                    std::unique_ptr<base::TickClock> tick_clock,
-                   std::unique_ptr<ReportingUploader> uploader);
+                   std::unique_ptr<ReportingUploader> uploader,
+                   std::unique_ptr<ReportingDelegate> delegate);
 
  private:
   ReportingPolicy policy_;
diff --git a/net/reporting/reporting_delegate.cc b/net/reporting/reporting_delegate.cc
index 88ff913..25dfdf14 100644
--- a/net/reporting/reporting_delegate.cc
+++ b/net/reporting/reporting_delegate.cc
@@ -5,6 +5,8 @@
 #include "net/reporting/reporting_delegate.h"
 
 #include "base/memory/ptr_util.h"
+#include "net/base/network_delegate.h"
+#include "net/url_request/url_request_context.h"
 
 namespace net {
 
@@ -12,30 +14,49 @@
 
 class ReportingDelegateImpl : public ReportingDelegate {
  public:
-  ReportingDelegateImpl() {}
+  ReportingDelegateImpl(URLRequestContext* request_context)
+      : request_context_(request_context) {
+    DCHECK(request_context);
+  }
 
   ~ReportingDelegateImpl() override {}
 
-  bool CanQueueReport(const url::Origin& origin) const override { return true; }
+  bool CanQueueReport(const url::Origin& origin) const override {
+    return network_delegate() &&
+           network_delegate()->CanQueueReportingReport(origin);
+  }
 
-  bool CanSendReport(const url::Origin& origin) const override { return true; }
+  bool CanSendReport(const url::Origin& origin) const override {
+    return network_delegate() &&
+           network_delegate()->CanSendReportingReport(origin);
+  }
 
   bool CanSetClient(const url::Origin& origin,
                     const GURL& endpoint) const override {
-    return true;
+    return network_delegate() &&
+           network_delegate()->CanSetReportingClient(origin, endpoint);
   }
 
   bool CanUseClient(const url::Origin& origin,
                     const GURL& endpoint) const override {
-    return true;
+    return network_delegate() &&
+           network_delegate()->CanUseReportingClient(origin, endpoint);
   }
+
+ private:
+  const NetworkDelegate* network_delegate() const {
+    return request_context_->network_delegate();
+  }
+
+  URLRequestContext* request_context_;
 };
 
 }  // namespace
 
 // static
-std::unique_ptr<ReportingDelegate> ReportingDelegate::Create() {
-  return base::MakeUnique<ReportingDelegateImpl>();
+std::unique_ptr<ReportingDelegate> ReportingDelegate::Create(
+    URLRequestContext* request_context) {
+  return base::MakeUnique<ReportingDelegateImpl>(request_context);
 }
 
 ReportingDelegate::~ReportingDelegate() {}
diff --git a/net/reporting/reporting_delegate.h b/net/reporting/reporting_delegate.h
index 7acf4c76..d2052f6e 100644
--- a/net/reporting/reporting_delegate.h
+++ b/net/reporting/reporting_delegate.h
@@ -18,6 +18,8 @@
 
 namespace net {
 
+class URLRequestContext;
+
 class NET_EXPORT ReportingDelegate {
  public:
   virtual ~ReportingDelegate();
@@ -38,7 +40,8 @@
   virtual bool CanUseClient(const url::Origin& origin,
                             const GURL& endpoint) const = 0;
 
-  static std::unique_ptr<ReportingDelegate> Create();
+  static std::unique_ptr<ReportingDelegate> Create(
+      URLRequestContext* request_context);
 };
 
 }  // namespace net
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc
index 2a7d1e0c..0b8237fb 100644
--- a/net/reporting/reporting_test_util.cc
+++ b/net/reporting/reporting_test_util.cc
@@ -17,6 +17,7 @@
 #include "net/reporting/reporting_cache.h"
 #include "net/reporting/reporting_client.h"
 #include "net/reporting/reporting_context.h"
+#include "net/reporting/reporting_delegate.h"
 #include "net/reporting/reporting_delivery_agent.h"
 #include "net/reporting/reporting_garbage_collector.h"
 #include "net/reporting/reporting_persister.h"
@@ -103,11 +104,34 @@
       url, json, callback, base::Bind(&ErasePendingUpload, &pending_uploads_)));
 }
 
+TestReportingDelegate::TestReportingDelegate() {}
+
+TestReportingDelegate::~TestReportingDelegate() {}
+
+bool TestReportingDelegate::CanQueueReport(const url::Origin& origin) const {
+  return true;
+}
+
+bool TestReportingDelegate::CanSendReport(const url::Origin& origin) const {
+  return true;
+}
+
+bool TestReportingDelegate::CanSetClient(const url::Origin& origin,
+                                         const GURL& endpoint) const {
+  return true;
+}
+
+bool TestReportingDelegate::CanUseClient(const url::Origin& origin,
+                                         const GURL& endpoint) const {
+  return true;
+}
+
 TestReportingContext::TestReportingContext(const ReportingPolicy& policy)
     : ReportingContext(policy,
                        base::MakeUnique<base::SimpleTestClock>(),
                        base::MakeUnique<base::SimpleTestTickClock>(),
-                       base::MakeUnique<TestReportingUploader>()),
+                       base::MakeUnique<TestReportingUploader>(),
+                       base::MakeUnique<TestReportingDelegate>()),
       delivery_timer_(new base::MockTimer(/* retain_user_task= */ false,
                                           /* is_repeating= */ false)),
       garbage_collection_timer_(
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h
index 6e64870..9343278 100644
--- a/net/reporting/reporting_test_util.h
+++ b/net/reporting/reporting_test_util.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "net/reporting/reporting_context.h"
+#include "net/reporting/reporting_delegate.h"
 #include "net/reporting/reporting_uploader.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -76,6 +77,28 @@
   DISALLOW_COPY_AND_ASSIGN(TestReportingUploader);
 };
 
+class TestReportingDelegate : public ReportingDelegate {
+ public:
+  TestReportingDelegate();
+
+  // ReportingDelegate implementation:
+
+  ~TestReportingDelegate() override;
+
+  bool CanQueueReport(const url::Origin& origin) const override;
+
+  bool CanSendReport(const url::Origin& origin) const override;
+
+  bool CanSetClient(const url::Origin& origin,
+                    const GURL& endpoint) const override;
+
+  bool CanUseClient(const url::Origin& origin,
+                    const GURL& endpoint) const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestReportingDelegate);
+};
+
 // A test implementation of ReportingContext that uses test versions of
 // Clock, TickClock, Timer, and ReportingUploader.
 class TestReportingContext : public ReportingContext {
@@ -96,6 +119,9 @@
   TestReportingUploader* test_uploader() {
     return reinterpret_cast<TestReportingUploader*>(uploader());
   }
+  TestReportingDelegate* test_delegate() {
+    return reinterpret_cast<TestReportingDelegate*>(delegate());
+  }
 
  private:
   // Owned by the Persister and GarbageCollector, respectively, but referenced
diff --git a/net/test/embedded_test_server/http_request.cc b/net/test/embedded_test_server/http_request.cc
index ef624dc..ecac880 100644
--- a/net/test/embedded_test_server/http_request.cc
+++ b/net/test/embedded_test_server/http_request.cc
@@ -110,7 +110,7 @@
     // know) anything about the server address.
     GURL url(header_line_tokens[1]);
     if (url.is_valid()) {
-      http_request_->relative_url = url.path();
+      http_request_->relative_url = url.PathForRequest();
     } else if (header_line_tokens[1][0] == '/') {
       http_request_->relative_url = header_line_tokens[1];
     } else {
diff --git a/net/test/embedded_test_server/simple_connection_listener.cc b/net/test/embedded_test_server/simple_connection_listener.cc
new file mode 100644
index 0000000..7cbe4dc
--- /dev/null
+++ b/net/test/embedded_test_server/simple_connection_listener.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/test/embedded_test_server/simple_connection_listener.h"
+
+#include "base/location.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test_server {
+
+SimpleConnectionListener::SimpleConnectionListener(
+    int expected_connections,
+    AllowAdditionalConnections allow_additional_connections)
+    : expected_connections_(expected_connections),
+      allow_additional_connections_(allow_additional_connections),
+      run_loop_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+
+SimpleConnectionListener::~SimpleConnectionListener() {}
+
+void SimpleConnectionListener::AcceptedSocket(const StreamSocket& socket) {
+  ++seen_connections_;
+  if (allow_additional_connections_ != ALLOW_ADDITIONAL_CONNECTIONS)
+    EXPECT_LE(seen_connections_, expected_connections_);
+  if (seen_connections_ == expected_connections_)
+    run_loop_task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
+}
+
+void SimpleConnectionListener::ReadFromSocket(const StreamSocket& socket,
+                                              int rv) {}
+
+void SimpleConnectionListener::WaitForConnections() {
+  EXPECT_TRUE(run_loop_task_runner_->RunsTasksOnCurrentThread());
+  run_loop_.Run();
+}
+
+}  // namespace test_server
+}  // namespace net
diff --git a/net/test/embedded_test_server/simple_connection_listener.h b/net/test/embedded_test_server/simple_connection_listener.h
new file mode 100644
index 0000000..3370cf3
--- /dev/null
+++ b/net/test/embedded_test_server/simple_connection_listener.h
@@ -0,0 +1,67 @@
+// 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 NET_TEST_EMBEDDED_TEST_SERVER_SIMPLE_CONNECTION_LISTENER_H_
+#define NET_TEST_EMBEDDED_TEST_SERVER_SIMPLE_CONNECTION_LISTENER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace net {
+
+class StreamSocket;
+
+namespace test_server {
+
+// Waits for a specified number of connection attempts to be seen.
+class SimpleConnectionListener : public EmbeddedTestServerConnectionListener {
+ public:
+  enum AllowAdditionalConnections {
+    // Add an expect failure if more than the specified number of connections
+    // are seen.
+    FAIL_ON_ADDITIONAL_CONNECTIONS,
+    // Silently ignores extra connection attempts.
+    ALLOW_ADDITIONAL_CONNECTIONS
+  };
+
+  // A connection listener that waits for the specified number of total
+  // connections when WaitForConnections() is called.  Must be created on a
+  // thread with a SingleThreadedTaskRunner.
+  SimpleConnectionListener(
+      int expected_connections,
+      AllowAdditionalConnections allow_additional_connections);
+
+  // Must be torn down only after the EmbeddedTestServer it's attached to is
+  // shut down.
+  ~SimpleConnectionListener() override;
+
+  void AcceptedSocket(const StreamSocket& socket) override;
+  void ReadFromSocket(const StreamSocket& socket, int rv) override;
+
+  // Wait until the expected number of connections have been seen.
+  void WaitForConnections();
+
+ private:
+  int seen_connections_ = 0;
+
+  const int expected_connections_;
+  const AllowAdditionalConnections allow_additional_connections_;
+
+  const scoped_refptr<base::SequencedTaskRunner> run_loop_task_runner_;
+
+  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleConnectionListener);
+};
+
+}  // namespace test_server
+}  // namespace net
+
+#endif  // NET_TEST_EMBEDDED_TEST_SERVER_SIMPLE_CONNECTION_LISTENER_H_
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 40e842d..3309974b 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -133,13 +133,23 @@
 };
 
 // Define a context class that can self-manage the ownership of its components
-// via a UrlRequestContextStorage object.
-class ContainerURLRequestContext : public URLRequestContext {
+// via a UrlRequestContextStorage object. Since it cancels requests in its
+// destructor, it's not safe to subclass this.
+class ContainerURLRequestContext final : public URLRequestContext {
  public:
   explicit ContainerURLRequestContext(
       const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
       : file_task_runner_(file_task_runner), storage_(this) {}
-  ~ContainerURLRequestContext() override { AssertNoURLRequests(); }
+
+  ~ContainerURLRequestContext() override {
+    // Shut down the ProxyService, as it may have pending URLRequests using this
+    // context. Since this cancels requests, it's not safe to subclass this, as
+    // some parts of the URLRequestContext may then be torn down before this
+    // cancels the ProxyService's URLRequests.
+    proxy_service()->OnShutdown();
+
+    AssertNoURLRequests();
+  }
 
   URLRequestContextStorage* storage() {
     return &storage_;
@@ -358,22 +368,6 @@
   }
   storage->set_host_resolver(std::move(host_resolver_));
 
-  if (!proxy_service_) {
-    // TODO(willchan): Switch to using this code when
-    // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
-#if !defined(OS_LINUX) && !defined(OS_ANDROID)
-    if (!proxy_config_service_) {
-      proxy_config_service_ = ProxyService::CreateSystemProxyConfigService(
-          base::ThreadTaskRunnerHandle::Get().get(),
-          context->GetFileTaskRunner());
-    }
-#endif  // !defined(OS_LINUX) && !defined(OS_ANDROID)
-    proxy_service_ = ProxyService::CreateUsingSystemProxyResolver(
-        std::move(proxy_config_service_),
-        context->net_log());
-  }
-  storage->set_proxy_service(std::move(proxy_service_));
-
   storage->set_ssl_config_service(new SSLConfigServiceDefaults);
 
   if (!http_auth_handler_factory_) {
@@ -440,6 +434,23 @@
         base::MakeUnique<URLRequestThrottlerManager>());
   }
 
+  if (!proxy_service_) {
+#if !defined(OS_LINUX) && !defined(OS_ANDROID)
+    // TODO(willchan): Switch to using this code when
+    // ProxyService::CreateSystemProxyConfigService()'s signature doesn't suck.
+    if (!proxy_config_service_) {
+      proxy_config_service_ = ProxyService::CreateSystemProxyConfigService(
+          base::ThreadTaskRunnerHandle::Get().get(),
+          context->GetFileTaskRunner());
+    }
+#endif  // !defined(OS_LINUX) && !defined(OS_ANDROID)
+    proxy_service_ =
+        CreateProxyService(std::move(proxy_config_service_), context.get(),
+                           context->host_resolver(),
+                           context->network_delegate(), context->net_log());
+  }
+  storage->set_proxy_service(std::move(proxy_service_));
+
   HttpNetworkSession::Params network_session_params;
   SetHttpNetworkSessionComponents(context.get(), &network_session_params);
   http_network_session_params_.ConfigureSessionParams(&network_session_params);
@@ -525,4 +536,14 @@
   return std::move(context);
 }
 
+std::unique_ptr<ProxyService> URLRequestContextBuilder::CreateProxyService(
+    std::unique_ptr<ProxyConfigService> proxy_config_service,
+    URLRequestContext* url_request_context,
+    HostResolver* host_resolver,
+    NetworkDelegate* network_delegate,
+    NetLog* net_log) {
+  return ProxyService::CreateUsingSystemProxyResolver(
+      std::move(proxy_config_service), net_log);
+}
+
 }  // namespace net
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 2c04437..a622625 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -112,7 +112,7 @@
   };
 
   URLRequestContextBuilder();
-  ~URLRequestContextBuilder();
+  virtual ~URLRequestContextBuilder();
 
   // Sets a name for this URLRequestContext. Currently the name is used in
   // MemoryDumpProvier to annotate memory usage. The name does not need to be
@@ -143,6 +143,11 @@
       std::unique_ptr<ProxyConfigService> proxy_config_service) {
     proxy_config_service_ = std::move(proxy_config_service);
   }
+
+  // Sets the proxy service. If one is not provided, by default, uses system
+  // libraries to evaluate PAC scripts, if available (And if not, skips PAC
+  // resolution). Subclasses may override CreateProxyService for different
+  // default behavior.
   void set_proxy_service(std::unique_ptr<ProxyService> proxy_service) {
     proxy_service_ = std::move(proxy_service);
   }
@@ -331,6 +336,17 @@
 
   std::unique_ptr<URLRequestContext> Build();
 
+ protected:
+  // Lets subclasses override ProxyService creation, using a ProxyService that
+  // uses the URLRequestContext itself to get PAC scripts. When this method is
+  // invoked, the URLRequestContext is not yet ready to service requests.
+  virtual std::unique_ptr<ProxyService> CreateProxyService(
+      std::unique_ptr<ProxyConfigService> proxy_config_service,
+      URLRequestContext* url_request_context,
+      HostResolver* host_resolver,
+      NetworkDelegate* network_delegate,
+      NetLog* net_log);
+
  private:
   const char* name_;
   bool enable_brotli_;
diff --git a/net/url_request/url_request_context_builder_v8.cc b/net/url_request/url_request_context_builder_v8.cc
new file mode 100644
index 0000000..d16f4d7
--- /dev/null
+++ b/net/url_request/url_request_context_builder_v8.cc
@@ -0,0 +1,64 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/url_request/url_request_context_builder_v8.h"
+
+#include "base/logging.h"
+#include "net/proxy/proxy_config_service.h"
+#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/proxy_service_v8.h"
+
+#ifdef ENABLE_NET_MOJO
+#include "net/proxy/proxy_service_mojo.h"
+#endif
+
+namespace net {
+
+URLRequestContextBuilderV8::URLRequestContextBuilderV8()
+    : dhcp_fetcher_factory_(new DhcpProxyScriptFetcherFactory()) {}
+
+URLRequestContextBuilderV8::~URLRequestContextBuilderV8() = default;
+
+std::unique_ptr<ProxyService> URLRequestContextBuilderV8::CreateProxyService(
+    std::unique_ptr<ProxyConfigService> proxy_config_service,
+    URLRequestContext* url_request_context,
+    HostResolver* host_resolver,
+    NetworkDelegate* network_delegate,
+    NetLog* net_log) {
+  DCHECK(url_request_context);
+  DCHECK(host_resolver);
+
+  if (!use_v8_) {
+    return URLRequestContextBuilder::CreateProxyService(
+        std::move(proxy_config_service), url_request_context, host_resolver,
+        network_delegate, net_log);
+  }
+
+  std::unique_ptr<net::DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher =
+      dhcp_fetcher_factory_->Create(url_request_context);
+  std::unique_ptr<net::ProxyScriptFetcher> proxy_script_fetcher =
+      base::MakeUnique<ProxyScriptFetcherImpl>(url_request_context);
+  std::unique_ptr<ProxyService> proxy_service;
+#ifdef ENABLE_NET_MOJO
+  if (mojo_proxy_resolver_factory_) {
+    proxy_service = CreateProxyServiceUsingMojoFactory(
+        mojo_proxy_resolver_factory_, std::move(proxy_config_service),
+        proxy_script_fetcher.release(), std::move(dhcp_proxy_script_fetcher),
+        host_resolver, net_log, network_delegate);
+  }
+#endif  // ENABLE_NET_MOJO
+  if (!proxy_service) {
+    proxy_service = CreateProxyServiceUsingV8ProxyResolver(
+        std::move(proxy_config_service), proxy_script_fetcher.release(),
+        std::move(dhcp_proxy_script_fetcher), host_resolver, net_log,
+        network_delegate);
+  }
+
+  proxy_service->set_quick_check_enabled(quick_check_enabled_);
+  proxy_service->set_sanitize_url_policy(sanitize_url_policy_);
+
+  return proxy_service;
+}
+
+}  // namespace net
diff --git a/net/url_request/url_request_context_builder_v8.h b/net/url_request/url_request_context_builder_v8.h
new file mode 100644
index 0000000..e44c359
--- /dev/null
+++ b/net/url_request/url_request_context_builder_v8.h
@@ -0,0 +1,92 @@
+// 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 NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_
+#define NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/proxy_service.h"
+#include "net/url_request/url_request_context_builder.h"
+
+namespace net {
+
+class HostResolver;
+class NetLog;
+class NetworkDelegate;
+class MojoProxyResolverFactory;
+class URLRequestContext;
+
+// Specialization of URLRequestContextBuilder that can create a ProxyService
+// that uses a V8 ProxyResolver. PAC scripts are run by V8 in process, by
+// default, but a Mojo factory can be passed in for out-of-process resolution.
+// PAC scripts will be fetched using the request context itself. If a
+// PoxyService is set directly via the URLRequestContextBuilder API, it will be
+// used instead of the one this class normally creates.
+class URLRequestContextBuilderV8 : public URLRequestContextBuilder {
+ public:
+  URLRequestContextBuilderV8();
+  ~URLRequestContextBuilderV8() override;
+
+  // If set to false, the URLrequestContextBuilder will create a ProxyService,
+  // which won't use V8. Defaults to true.
+  void set_use_v8(bool use_v8) { use_v8_ = use_v8; }
+
+  // Sets whether quick PAC checks are enabled. Defaults to true. Ignored if
+  // use_v8 is false.
+  void set_quick_check_enabled(bool quick_check_enabled) {
+    quick_check_enabled_ = quick_check_enabled;
+  }
+
+  // Sets policy for sanitizing URLs before passing them a PAC. Defaults to
+  // ProxyService::SanitizeUrlPolicy::SAFE. Ignored if use_v8 is false.
+  void set_pac_sanitize_url_policy(
+      net::ProxyService::SanitizeUrlPolicy sanitize_url_policy) {
+    sanitize_url_policy_ = sanitize_url_policy;
+  }
+
+  // Overrides default DhcpProxyScriptFetcherFactory. Ignored if use_v8 is
+  // false.
+  void set_dhcp_fetcher_factory(
+      std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory) {
+    dhcp_fetcher_factory = std::move(dhcp_fetcher_factory_);
+  }
+
+#ifdef ENABLE_NET_MOJO
+  // Sets Mojo factory used to create ProxyResolvers. If not set, V8 will be
+  // used in process instead of Mojo. Ignored if use_v8 is false. The passed in
+  // factory must outlive the URLRequestContext the builder creates.
+  void set_mojo_proxy_resolver_factory(
+      MojoProxyResolverFactory* mojo_proxy_resolver_factory) {
+    mojo_proxy_resolver_factory_ = mojo_proxy_resolver_factory;
+  }
+#endif  // ENABLE_NET_MOJO
+
+ private:
+  std::unique_ptr<ProxyService> CreateProxyService(
+      std::unique_ptr<ProxyConfigService> proxy_config_service,
+      URLRequestContext* url_request_context,
+      HostResolver* host_resolver,
+      NetworkDelegate* network_delegate,
+      NetLog* net_log) override;
+
+  bool use_v8_ = true;
+  bool quick_check_enabled_ = true;
+  net::ProxyService::SanitizeUrlPolicy sanitize_url_policy_ =
+      net::ProxyService::SanitizeUrlPolicy::SAFE;
+
+  std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory_;
+
+#ifdef ENABLE_NET_MOJO
+  MojoProxyResolverFactory* mojo_proxy_resolver_factory_ = nullptr;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilderV8);
+};
+
+}  // namespace net
+
+#endif  // NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_
diff --git a/net/url_request/url_request_context_builder_v8_unittest.cc b/net/url_request/url_request_context_builder_v8_unittest.cc
new file mode 100644
index 0000000..f302d35
--- /dev/null
+++ b/net/url_request/url_request_context_builder_v8_unittest.cc
@@ -0,0 +1,131 @@
+// 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 "net/url_request/url_request_context_builder_v8.h"
+
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "net/base/host_port_pair.h"
+#include "net/proxy/proxy_config.h"
+#include "net/proxy/proxy_config_service_fixed.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/embedded_test_server/simple_connection_listener.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#include "url/gurl.h"
+
+#ifdef ENABLE_NET_MOJO
+#include "net/proxy/test_mojo_proxy_resolver_factory.h"
+#endif
+
+namespace net {
+
+namespace {
+
+const char kPacPath[] = "/super.pac";
+
+// When kPacPath is requested, returns a PAC script that uses the test server
+// itself as the proxy.
+std::unique_ptr<test_server::HttpResponse> HandlePacRequest(
+    const test_server::HttpRequest& request) {
+  if (request.relative_url != kPacPath)
+    return nullptr;
+  std::unique_ptr<test_server::BasicHttpResponse> response =
+      base::MakeUnique<test_server::BasicHttpResponse>();
+  response->set_content(base::StringPrintf(
+      "function FindProxyForURL(url, host) { return 'PROXY %s;'; }",
+      HostPortPair::FromURL(request.base_url).ToString().c_str()));
+  response->set_content_type("text/html");
+  return std::move(response);
+}
+
+class URLRequestContextBuilderV8Test : public PlatformTest {
+ protected:
+  URLRequestContextBuilderV8Test() {
+    test_server_.RegisterRequestHandler(base::Bind(&HandlePacRequest));
+    test_server_.AddDefaultHandlers(
+        base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
+  }
+
+  EmbeddedTestServer test_server_;
+  URLRequestContextBuilderV8 builder_;
+};
+
+TEST_F(URLRequestContextBuilderV8Test, V8InProcess) {
+  EXPECT_TRUE(test_server_.Start());
+
+  builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>(
+      ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL(kPacPath))));
+  std::unique_ptr<URLRequestContext> context(builder_.Build());
+
+  TestDelegate delegate;
+  std::unique_ptr<URLRequest> request(context->CreateRequest(
+      GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
+  request->SetExtraRequestHeaderByName("Foo", "Bar", false);
+  request->Start();
+  base::RunLoop().Run();
+  EXPECT_EQ("Bar", delegate.data_received());
+}
+
+// Makes sure that pending PAC requests are correctly shutdown during teardown.
+TEST_F(URLRequestContextBuilderV8Test, V8InProcessShutdownWithHungRequest) {
+  test_server::SimpleConnectionListener connection_listener(
+      1, test_server::SimpleConnectionListener::FAIL_ON_ADDITIONAL_CONNECTIONS);
+  test_server_.SetConnectionListener(&connection_listener);
+  EXPECT_TRUE(test_server_.Start());
+
+  builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>(
+      ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL("/hung"))));
+
+  std::unique_ptr<URLRequestContext> context(builder_.Build());
+  TestDelegate delegate;
+  std::unique_ptr<URLRequest> request(context->CreateRequest(
+      GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
+  request->Start();
+  connection_listener.WaitForConnections();
+
+  // Have to shut down the test server before |connection_listener| falls out of
+  // scope.
+  EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete());
+
+  // Tearing down the URLRequestContext should not cause an AssertNoURLRequests
+  // failure.
+}
+
+#ifdef ENABLE_NET_MOJO
+TEST_F(URLRequestContextBuilderV8Test, MojoProxyResolver) {
+  EXPECT_TRUE(test_server_.Start());
+  TestMojoProxyResolverFactory::GetInstance()->set_resolver_created(false);
+
+  builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>(
+      ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL(kPacPath))));
+  builder_.set_mojo_proxy_resolver_factory(
+      TestMojoProxyResolverFactory::GetInstance());
+
+  std::unique_ptr<URLRequestContext> context(builder_.Build());
+  TestDelegate delegate;
+  std::unique_ptr<URLRequest> request(context->CreateRequest(
+      GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
+  request->SetExtraRequestHeaderByName("Foo", "Bar", false);
+  request->Start();
+  base::RunLoop().Run();
+  EXPECT_EQ("Bar", delegate.data_received());
+
+  // Make sure that the Mojo factory was used.
+  EXPECT_TRUE(TestMojoProxyResolverFactory::GetInstance()->resolver_created());
+}
+#endif  // ENABLE_NET_MOJO
+
+}  // namespace
+
+}  // namespace net
diff --git a/services/identity/OWNERS b/services/identity/OWNERS
index 2654e53..3532cb2 100644
--- a/services/identity/OWNERS
+++ b/services/identity/OWNERS
@@ -1,2 +1,4 @@
 blundell@chromium.org
 msarda@chromium.org
+
+# COMPONENT: Services>SignIn
diff --git a/services/ui/service.cc b/services/ui/service.cc
index f44fe04..59b670f 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -100,9 +100,9 @@
 #endif
 }
 
-void Service::InitializeResources(service_manager::Connector* connector) {
+bool Service::InitializeResources(service_manager::Connector* connector) {
   if (ui::ResourceBundle::HasSharedInstance())
-    return;
+    return true;
 
   std::set<std::string> resource_paths;
   resource_paths.insert(kResourceFileStrings);
@@ -112,7 +112,10 @@
   catalog::ResourceLoader loader;
   filesystem::mojom::DirectoryPtr directory;
   connector->BindInterface(catalog::mojom::kServiceName, &directory);
-  CHECK(loader.OpenFiles(std::move(directory), resource_paths));
+  if (!loader.OpenFiles(std::move(directory), resource_paths)) {
+    LOG(ERROR) << "Service failed to open resource files.";
+    return false;
+  }
 
   ui::RegisterPathProvider();
 
@@ -125,6 +128,7 @@
                          ui::SCALE_FACTOR_100P);
   rb.AddDataPackFromFile(loader.TakeFile(kResourceFile200),
                          ui::SCALE_FACTOR_200P);
+  return true;
 }
 
 Service::UserState* Service::GetUserState(
@@ -156,7 +160,11 @@
   if (test_config_)
     ui::test::EnableTestConfigForPlatformWindows();
 
-  InitializeResources(context()->connector());
+  // If resources are unavailable do not complete start-up.
+  if (!InitializeResources(context()->connector())) {
+    context()->QuitNow();
+    return;
+  }
 
 #if defined(USE_OZONE)
   // The ozone platform can provide its own event source. So initialize the
diff --git a/services/ui/service.h b/services/ui/service.h
index 0bf1f15d..6bf2463 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -87,7 +87,9 @@
 
   using UserIdToUserState = std::map<ws::UserId, std::unique_ptr<UserState>>;
 
-  void InitializeResources(service_manager::Connector* connector);
+  // Attempts to initialize the resource bundle. Returns true if successful,
+  // otherwise false if resources cannot be loaded.
+  bool InitializeResources(service_manager::Connector* connector);
 
   // Returns the user specific state for the user id of |remote_identity|.
   // Service owns the return value.
diff --git a/services/video_capture/BUILD.gn b/services/video_capture/BUILD.gn
index c834b7aa..be8833cb 100644
--- a/services/video_capture/BUILD.gn
+++ b/services/video_capture/BUILD.gn
@@ -51,10 +51,6 @@
     "//services/video_capture/public/interfaces",
     "//services/video_capture/public/interfaces:constants",
   ]
-
-  data_deps = [
-    ":manifest",
-  ]
 }
 
 source_set("tests") {
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.cc b/services/video_capture/device_factory_media_to_mojo_adapter.cc
index b7241270..60b2b370 100644
--- a/services/video_capture/device_factory_media_to_mojo_adapter.cc
+++ b/services/video_capture/device_factory_media_to_mojo_adapter.cc
@@ -35,17 +35,10 @@
     translated_device_info.descriptor = device_info.descriptor;
     for (const auto& format : device_info.supported_formats) {
       media::VideoCaptureFormat translated_format;
-      switch (format.pixel_format) {
-        case media::PIXEL_FORMAT_I420:
-        case media::PIXEL_FORMAT_MJPEG:
-          translated_format.pixel_format = media::PIXEL_FORMAT_I420;
-          break;
-        case media::PIXEL_FORMAT_Y16:
-          translated_format.pixel_format = media::PIXEL_FORMAT_Y16;
-        default:
-          // Any other format cannot be consumed by VideoCaptureDeviceClient.
-          continue;
-      }
+      translated_format.pixel_format =
+          (format.pixel_format == media::PIXEL_FORMAT_Y16)
+              ? media::PIXEL_FORMAT_Y16
+              : media::PIXEL_FORMAT_I420;
       translated_format.frame_size = format.frame_size;
       translated_format.frame_rate = format.frame_rate;
       translated_format.pixel_storage = media::PIXEL_STORAGE_CPU;
diff --git a/services/video_capture/public/cpp/BUILD.gn b/services/video_capture/public/cpp/BUILD.gn
index 4362d25..59094d47 100644
--- a/services/video_capture/public/cpp/BUILD.gn
+++ b/services/video_capture/public/cpp/BUILD.gn
@@ -4,6 +4,8 @@
 
 source_set("cpp") {
   sources = [
+    "constants.cc",
+    "constants.h",
     "device_to_feedback_observer_adapter.cc",
     "device_to_feedback_observer_adapter.h",
     "receiver_media_to_mojo_adapter.cc",
diff --git a/services/video_capture/public/cpp/constants.cc b/services/video_capture/public/cpp/constants.cc
new file mode 100644
index 0000000..37a25ed
--- /dev/null
+++ b/services/video_capture/public/cpp/constants.cc
@@ -0,0 +1,12 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/video_capture/public/cpp/constants.h"
+
+namespace video_capture {
+
+const base::Feature kMojoVideoCapture{"MojoVideoCapture",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace video_capture
diff --git a/services/video_capture/public/cpp/constants.h b/services/video_capture/public/cpp/constants.h
new file mode 100644
index 0000000..9a970a5
--- /dev/null
+++ b/services/video_capture/public/cpp/constants.h
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_CONSTANTS_H_
+#define SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_CONSTANTS_H_
+
+#include "base/feature_list.h"
+
+namespace video_capture {
+
+extern const base::Feature kMojoVideoCapture;
+
+}  // namespace video_capture
+
+#endif  // SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_CONSTANTS_H_
diff --git a/services/video_capture/service_manifest.json b/services/video_capture/service_manifest.json
index 4e5bffc37..62d76da 100644
--- a/services/video_capture/service_manifest.json
+++ b/services/video_capture/service_manifest.json
@@ -4,7 +4,7 @@
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
-        "production": [ "*" ],
+        "capture": [ "video_capture::mojom::DeviceFactoryProvider" ],
         "tests": [ "*" ]
       },
       "requires": {
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 3b368499..abe0cfa 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -240,6 +240,18 @@
         "test": "latency_unittests"
       },
       {
+        "args": [
+          "--ozone-platform=headless",
+          "--override-use-software-gl-for-tests",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/mash.browser_tests.filter"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 900
+        },
+        "test": "mash_browser_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter
index 0fb95080..c260db5 100644
--- a/testing/buildbot/filters/mash.browser_tests.filter
+++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -1,4 +1,3 @@
-BrowserTest.*
 # Failing test
 -BrowserTest.FullscreenBookmarkBar
 
@@ -15,25 +14,7 @@
 -ExtensionsLoadTestWithLoginScreenApps.CommandLineExtensionsDontLoad
 
 # Trying to whitelist
-AppWindowApiTest.AlphaEnabledHasPermissions
-AppWindowApiTest.AlphaEnabledInStable
-AppWindowApiTest.AlphaEnabledNoPermissions
-AppWindowApiTest.AlphaEnabledWrongFrameType
-AppWindowApiTest.AlwaysOnTopNoPermissions
-AppWindowApiTest.AlwaysOnTopWithOldPermissions
-AppWindowApiTest.AlwaysOnTopWithPermissions
-AppWindowApiTest.Get
-AppWindowApiTest.ImeWindowHasPermissions
-AppWindowApiTest.ImeWindowNoPermissions
-AppWindowApiTest.ImeWindowNotFullscreen
-AppWindowApiTest.SetShapeHasPerm
-AppWindowApiTest.SetShapeNoPerm
-AppWindowApiTest.VisibleOnAllWorkspacesInStable
-BluetoothInternalsTest.Startup_BluetoothInternals
-BootstrapTest.CleanUpFailedUser
-BootstrapTest.PRE_CleanUpFailedUser
 BrowserDialogTest.Invoke
-BrowsingDataRemoverTransportSecurityStateBrowserTest.ClearTransportSecurityState
 CastSessionBrowserTest.CreateAndDestroy
 ChromeContentRendererClientSearchBoxTest.RewriteThumbnailURL
 ChromeRenderFrameObserverTest.SkipCapturingSubFrames
@@ -42,25 +23,10 @@
 ChromeRenderViewTest.ImagesBlockedByDefault
 ChromeRenderViewTest.JSBlockSentAfterPageLoad
 ChromeRenderViewTest.PluginsTemporarilyAllowed
-ChromeServiceWorkerManifestFetchTest.OtherOrigin
-ChromeServiceWorkerManifestFetchTest.OtherOriginUseCredentials
-ChromeServiceWorkerManifestFetchTest.SameOrigin
-ChromeServiceWorkerManifestFetchTest.SameOriginUseCredentials
-ChromeServiceWorkerTest.CanCloseIncognitoWindowWithServiceWorkerController
-ChromeServiceWorkerTest.CanShutDownWithRegisteredServiceWorker
-ChromeServiceWorkerTest.FailRegisterServiceWorkerWhenJSDisabled
-ChromeServiceWorkerTest.FallbackMainResourceRequestWhenJSDisabled
-ConstrainedWebDialogBrowserTest.ReleaseWebContents
-ContentVerifierPolicyTest.PRE_PolicyCorruptedOnStartup
-ContentVerifierPolicyTest.PolicyCorruptedOnStartup
 CreateNewFolder/FileManagerBrowserTest.Test/0
 CreateNewFolder/FileManagerBrowserTest.Test/1
 CreateNewFolder/FileManagerBrowserTest.Test/2
 CreateNewFolder/FileManagerBrowserTest.Test/3
-DefaultTaskDialog/FileManagerBrowserTest.Test/0
-DefaultTaskDialog/FileManagerBrowserTest.Test/1
-DefaultTaskDialog/FileManagerBrowserTest.Test/2
-Delete/FileManagerBrowserTest.Test/1
 DeviceStatusCollectorNetworkInterfacesTest.NetworkInterfaces
 DeviceStatusCollectorNetworkInterfacesTest.ReportIfPublicSession
 DeviceStatusCollectorTest.ActivityCrossingMidnight
@@ -89,44 +55,8 @@
 DeviceStatusCollectorTest.TestVolumeInfo
 DeviceStatusCollectorTest.Times
 DeviceStatusCollectorTest.VersionInfo
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/0
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/1
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/10
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/11
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/12
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/13
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/14
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/15
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/16
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/17
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/18
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/19
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/2
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/20
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/21
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/22
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/24
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/3
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/4
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/5
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/6
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/7
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/8
-DirectoryTreeContextMenu/FileManagerBrowserTest.Test/9
 DownloadInterruptReasonEnumsSynced.DownloadInterruptReasonEnumsSynced
-DriveSpecific/FileManagerBrowserTest.Test/0
-DriveSpecific/FileManagerBrowserTest.Test/1
-DriveSpecific/FileManagerBrowserTest.Test/2
-DriveSpecific/FileManagerBrowserTest.Test/3
-DriveSpecific/FileManagerBrowserTest.Test/4
-DriveSpecific/FileManagerBrowserTest.Test/5
-DriveSpecific/FileManagerBrowserTest.Test/6
-ExecuteDefaultTaskOnDownloads/FileManagerBrowserTest.Test/0
-ExecuteDefaultTaskOnDownloads/FileManagerBrowserTest.Test/1
-ExecuteDefaultTaskOnDrive/FileManagerBrowserTest.Test/0
 ExtensionDetermineDownloadFilenameInternal.ExtensionDetermineDownloadFilenameInternal
-FolderShortcuts/FileManagerBrowserTest.Test/0
-FolderShortcuts/FileManagerBrowserTest.Test/1
 FormAutocompleteTest.AjaxSucceeded_FilledFormIsInvisible
 FormAutocompleteTest.AjaxSucceeded_FilledFormStillVisible
 FormAutocompleteTest.AjaxSucceeded_FormlessElements
@@ -158,18 +88,6 @@
 FormClassifierTest.kChangeFormWithTreePasswordFieldsHTML
 InstantProcessNavigationTest.ForkForNavigationsFromInstantProcess
 InstantProcessNavigationTest.ForkForNavigationsToSearchURLs
-MultiProfileFileManagerBrowserTest.BasicDownloads
-MultiProfileFileManagerBrowserTest.BasicDrive
-MultiProfileFileManagerBrowserTest.PRE_BasicDownloads
-OpenAudioFiles/FileManagerBrowserTest.Test/1
-OpenAudioFiles/FileManagerBrowserTest.Test/2
-OpenAudioFiles/FileManagerBrowserTest.Test/3
-OpenAudioFiles/FileManagerBrowserTest.Test/4
-OpenAudioFiles/FileManagerBrowserTest.Test/5
-OpenAudioFiles/FileManagerBrowserTest.Test/6
-OpenFileDialog/FileManagerBrowserTest.Test/0
-OpenFileDialog/FileManagerBrowserTest.Test/2
-OpenFileDialog/FileManagerBrowserTest.Test/5
 PageClickTrackerTest.PageClickTrackerClickDisabledInputDoesNotResetClickCounter
 PageClickTrackerTest.PageClickTrackerDisabledInputClickedNoEvent
 PageClickTrackerTest.PageClickTrackerInputClicked
@@ -219,13 +137,5 @@
 PolicyCertVerifierTest.VerifyTrustedCert
 PolicyCertVerifierTest.VerifyUntrustedCert
 PolicyCertVerifierTest.VerifyUsingAdditionalTrustAnchor
-Providers/FileManagerBrowserTest.Test/0
-Providers/FileManagerBrowserTest.Test/1
-Providers/FileManagerBrowserTest.Test/2
-Providers/FileManagerBrowserTest.Test/3
-RestoreGeometry/FileManagerBrowserTest.Test/0
-RestoreGeometry/FileManagerBrowserTest.Test/1
 ScriptContextTest.GetEffectiveDocumentURL
-ShowGridView/FileManagerBrowserTest.Test/0
-ShowGridView/FileManagerBrowserTest.Test/1
 SiteEngagementUiBrowserTest.Basic
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cssom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/cssom/interfaces-expected.txt
index 4c43e9b..05df14d5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/cssom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/cssom/interfaces-expected.txt
@@ -1,12 +1,12 @@
 This is a testharness.js-based test.
-Found 187 tests; 156 PASS, 31 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 187 tests; 159 PASS, 28 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Document interface: attribute styleSheets 
 FAIL Document must be primary interface of document assert_equals: document's prototype is not Document.prototype expected object "[object Document]" but got object "[object HTMLDocument]"
 FAIL Stringification of document assert_equals: class string of document expected "[object Document]" but got "[object HTMLDocument]"
 PASS Document interface: document must inherit property "styleSheets" with the proper type (0) 
-FAIL Document must be primary interface of new Document() assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Stringification of new Document() assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "styleSheets" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+PASS Document must be primary interface of new Document() 
+PASS Stringification of new Document() 
+PASS Document interface: new Document() must inherit property "styleSheets" with the proper type (0) 
 PASS ProcessingInstruction interface: attribute sheet 
 PASS HTMLElement interface: attribute style 
 PASS SVGElement interface: attribute style 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/adopted-callback-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/adopted-callback-expected.txt
deleted file mode 100644
index f201c5f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/adopted-callback-expected.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-This is a testharness.js-based test.
-Found 57 tests; 49 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS Inserting a custom element into the owner document must not enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to the document of the template elements must enqueue and invoke adoptedCallback 
-FAIL Inserting a custom element into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Moving a custom element from the owner document into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting an ancestor of custom element into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Moving an ancestor of custom element from the owner document into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting a custom element into a shadow tree in a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting the shadow host of a custom element into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Moving the shadow host of a custom element from the owner document into a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting a custom element into a detached shadow tree that belongs to a new document must enqueue and invoke adoptedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-PASS Inserting a custom element into a cloned document must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into a cloned document must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in a cloned document must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into a cloned document must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to a cloned document must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to a document created by createHTMLDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to an HTML document created by createDocument must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to the document of an iframe must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Moving a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Inserting an ancestor of custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Moving an ancestor of custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a shadow tree in an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Inserting the shadow host of a custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Moving the shadow host of a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to an HTML document fetched by XHR must enqueue and invoke adoptedCallback 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/connected-callbacks-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/connected-callbacks-expected.txt
deleted file mode 100644
index 6a4c52a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/connected-callbacks-expected.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-This is a testharness.js-based test.
-PASS Inserting a custom element into the document must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into the document must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in the document must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into the document must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to the document must not enqueue and invoke connectedCallback 
-PASS Inserting a custom element into the document of the template elements must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into the document of the template elements must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in the document of the template elements must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into the document of the template elements must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to the document of the template elements must not enqueue and invoke connectedCallback 
-FAIL Inserting a custom element into a new document must enqueue and invoke connectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting an ancestor of custom element into a new document must enqueue and invoke connectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting a custom element into a shadow tree in a new document must enqueue and invoke connectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting the shadow host of a custom element into a new document must enqueue and invoke connectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Inserting a custom element into a detached shadow tree that belongs to a new document must not enqueue and invoke connectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-PASS Inserting a custom element into a cloned document must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into a cloned document must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in a cloned document must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into a cloned document must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to a cloned document must not enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in a document created by createHTMLDocument must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke connectedCallback 
-PASS Inserting a custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in an HTML document created by createDocument must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to an HTML document created by createDocument must not enqueue and invoke connectedCallback 
-PASS Inserting a custom element into the document of an iframe must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into the document of an iframe must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in the document of an iframe must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into the document of an iframe must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to the document of an iframe must not enqueue and invoke connectedCallback 
-PASS Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback 
-PASS Inserting an ancestor of custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a shadow tree in an HTML document fetched by XHR must enqueue and invoke connectedCallback 
-PASS Inserting the shadow host of a custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback 
-PASS Inserting a custom element into a detached shadow tree that belongs to an HTML document fetched by XHR must not enqueue and invoke connectedCallback 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/disconnected-callbacks-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/disconnected-callbacks-expected.txt
deleted file mode 100644
index 9994c59..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/disconnected-callbacks-expected.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-This is a testharness.js-based test.
-PASS Removing a custom element from the document must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from the document must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in the document must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from athe document must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to the document must not enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from the document of the template elements must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from the document of the template elements must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in the document of the template elements must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from athe document of the template elements must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to the document of the template elements must not enqueue and invoke disconnectedCallback 
-FAIL Removing a custom element from a new document must enqueue and invoke disconnectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Removing an ancestor of custom element from a new document must enqueue and invoke disconnectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Removing a custom element from a shadow tree in a new document must enqueue and invoke disconnectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Removing the shadow host of a custom element from aa new document must enqueue and invoke disconnectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Removing a custom element from a detached shadow tree that belongs to a new document must not enqueue and invoke disconnectedCallback promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-PASS Removing a custom element from a cloned document must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from a cloned document must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in a cloned document must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from aa cloned document must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to a cloned document must not enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in a document created by createHTMLDocument must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from aa document created by createHTMLDocument must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in an HTML document created by createDocument must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from aan HTML document created by createDocument must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to an HTML document created by createDocument must not enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from the document of an iframe must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from the document of an iframe must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in the document of an iframe must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from athe document of an iframe must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to the document of an iframe must not enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback 
-PASS Removing an ancestor of custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a shadow tree in an HTML document fetched by XHR must enqueue and invoke disconnectedCallback 
-PASS Removing the shadow host of a custom element from aan HTML document fetched by XHR must enqueue and invoke disconnectedCallback 
-PASS Removing a custom element from a detached shadow tree that belongs to an HTML document fetched by XHR must not enqueue and invoke disconnectedCallback 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt
index b7b5bf9..142a37f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/parser/parser-uses-registry-of-owner-document-expected.txt
@@ -5,7 +5,7 @@
 PASS HTML parser must not instantiate a custom element defined inside an frame in frame element's owner document 
 PASS HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument() 
 FAIL HTML parser must use the registry of window.document in a document created by document.implementation.createXHTMLDocument() assert_true: expected true got false
-FAIL HTML parser must use the registry of window.document in a document created by new Document Illegal constructor
+PASS HTML parser must use the registry of window.document in a document created by new Document 
 PASS HTML parser must use the registry of window.document in a document created by XMLHttpRequest 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/upgrading-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/custom-elements/upgrading-expected.txt
deleted file mode 100644
index 4fedcfe..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/custom-elements/upgrading-expected.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-This is a testharness.js-based test.
-PASS Creating an element in the document of the template elements must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
-PASS Creating an element in the document of the template elements and inserting into the document must not enqueue a custom element upgrade reaction 
-PASS Creating an element in the document of the template elements and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
-FAIL Creating an element in a new document must not enqueue a custom element upgrade reaction because the document does not have a browsing context promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Creating an element in a new document and inserting into the document must not enqueue a custom element upgrade reaction promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-FAIL Creating an element in a new document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction promise_test: Unhandled rejection with value: object "TypeError: Illegal constructor"
-PASS Creating an element in a cloned document must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
-PASS Creating an element in a cloned document and inserting into the document must not enqueue a custom element upgrade reaction 
-PASS Creating an element in a cloned document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
-PASS Creating an element in a document created by createHTMLDocument must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
-PASS Creating an element in a document created by createHTMLDocument and inserting into the document must not enqueue a custom element upgrade reaction 
-PASS Creating an element in a document created by createHTMLDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
-PASS Creating an element in an HTML document created by createDocument must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
-PASS Creating an element in an HTML document created by createDocument and inserting into the document must not enqueue a custom element upgrade reaction 
-PASS Creating an element in an HTML document created by createDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
-PASS Creating an element in an HTML document fetched by XHR must not enqueue a custom element upgrade reaction because the document does not have a browsing context 
-PASS Creating an element in an HTML document fetched by XHR and inserting into the document must not enqueue a custom element upgrade reaction 
-PASS Creating an element in an HTML document fetched by XHR and adopting back to a document with browsing context must enqueue a custom element upgrade reaction 
-PASS Creating an element in the document of an iframe must not enqueue a custom element upgrade reaction if there is no matching definition 
-PASS Creating an element in the document of an iframe must enqueue a custom element upgrade reaction if there is a matching definition 
-PASS "define" in the document of an iframe must not enqueue a custom element upgrade reaction on a disconnected unresolved custom element 
-PASS Inserting an unresolved custom element into the document of an iframe must enqueue a custom element upgrade reaction 
-PASS "define" in the document of an iframe must enqueue a custom element upgrade reaction on a connected unresolved custom element 
-PASS Adopting (and leaving disconnceted) an unresolved custom element into the document of an iframe must not enqueue a custom element upgrade reaction 
-PASS Adopting and inserting an unresolved custom element into the document of an iframe must enqueue a custom element upgrade reaction 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-false-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-false-expected.txt
index cf63220..dbfb754 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-false-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-false-expected.txt
@@ -2,7 +2,7 @@
 PASS In window.document with click event 
 PASS In window.document with load event 
 FAIL In window.document.cloneNode(true) assert_array_equals: targets lengths differ, expected 8 got 0
-FAIL In new Document() Illegal constructor
+PASS In new Document() 
 PASS In DOMImplementation.createHTMLDocument() 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-true-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-true-expected.txt
index dbee77a..da032a1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-true-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/Event-dispatch-bubbles-true-expected.txt
@@ -2,7 +2,7 @@
 PASS In window.document with click event 
 PASS In window.document with load event 
 FAIL In window.document.cloneNode(true) assert_array_equals: targets lengths differ, expected 14 got 0
-FAIL In new Document() Illegal constructor
+PASS In new Document() 
 PASS In DOMImplementation.createHTMLDocument() 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
index 7b4a17dc..ce44fe68 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1570 tests; 1440 PASS, 130 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1570 tests; 1565 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver 
 PASS Event interface: existence and properties of interface object 
 PASS Event interface object length 
@@ -260,131 +260,131 @@
 PASS Document interface: operation append([object Object],[object Object]) 
 PASS Document interface: operation querySelector(DOMString) 
 PASS Document interface: operation querySelectorAll(DOMString) 
-FAIL Document interface: new Document() must inherit property "implementation" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "URL" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "documentURI" with the proper type (2) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "origin" with the proper type (3) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "compatMode" with the proper type (4) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "characterSet" with the proper type (5) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "charset" with the proper type (6) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "inputEncoding" with the proper type (7) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "contentType" with the proper type (8) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "doctype" with the proper type (9) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "documentElement" with the proper type (10) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "getElementsByTagName" with the proper type (11) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling getElementsByTagName(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "getElementsByTagNameNS" with the proper type (12) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling getElementsByTagNameNS(DOMString,DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "getElementsByClassName" with the proper type (13) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling getElementsByClassName(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createElement" with the proper type (14) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createElement(DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createElementNS" with the proper type (15) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createElementNS(DOMString,DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createDocumentFragment" with the proper type (16) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createTextNode" with the proper type (17) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createTextNode(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createCDATASection" with the proper type (18) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createCDATASection(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createComment" with the proper type (19) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createComment(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createProcessingInstruction" with the proper type (20) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createProcessingInstruction(DOMString,DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "importNode" with the proper type (21) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling importNode(Node,boolean) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "adoptNode" with the proper type (22) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling adoptNode(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createAttribute" with the proper type (23) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createAttribute(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createAttributeNS" with the proper type (24) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createAttributeNS(DOMString,DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createEvent" with the proper type (25) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createEvent(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createRange" with the proper type (26) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createNodeIterator" with the proper type (27) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createNodeIterator(Node,unsigned long,NodeFilter) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "createTreeWalker" with the proper type (28) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling createTreeWalker(Node,unsigned long,NodeFilter) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "getElementById" with the proper type (29) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling getElementById(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "children" with the proper type (30) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "firstElementChild" with the proper type (31) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "lastElementChild" with the proper type (32) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "childElementCount" with the proper type (33) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "prepend" with the proper type (34) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling prepend([object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "append" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling append([object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "querySelector" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling querySelector(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document() must inherit property "querySelectorAll" with the proper type (37) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: calling querySelectorAll(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ELEMENT_NODE" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ATTRIBUTE_NODE" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "TEXT_NODE" with the proper type (2) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "CDATA_SECTION_NODE" with the proper type (3) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ENTITY_NODE" with the proper type (5) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "COMMENT_NODE" with the proper type (7) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_NODE" with the proper type (8) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "NOTATION_NODE" with the proper type (11) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nodeType" with the proper type (12) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nodeName" with the proper type (13) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "baseURI" with the proper type (14) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isConnected" with the proper type (15) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "ownerDocument" with the proper type (16) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "getRootNode" with the proper type (17) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "parentNode" with the proper type (18) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "parentElement" with the proper type (19) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "hasChildNodes" with the proper type (20) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "childNodes" with the proper type (21) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "firstChild" with the proper type (22) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lastChild" with the proper type (23) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "previousSibling" with the proper type (24) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nextSibling" with the proper type (25) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "nodeValue" with the proper type (26) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "textContent" with the proper type (27) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "normalize" with the proper type (28) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "cloneNode" with the proper type (29) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling cloneNode(boolean) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isEqualNode" with the proper type (30) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling isEqualNode(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isSameNode" with the proper type (31) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling isSameNode(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "compareDocumentPosition" with the proper type (38) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling compareDocumentPosition(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "contains" with the proper type (39) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling contains(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lookupPrefix" with the proper type (40) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling lookupPrefix(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "lookupNamespaceURI" with the proper type (41) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling lookupNamespaceURI(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "isDefaultNamespace" with the proper type (42) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling isDefaultNamespace(DOMString) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "insertBefore" with the proper type (43) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling insertBefore(Node,Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "appendChild" with the proper type (44) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling appendChild(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "replaceChild" with the proper type (45) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling replaceChild(Node,Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: new Document() must inherit property "removeChild" with the proper type (46) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Node interface: calling removeChild(Node) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: new Document() must inherit property "addEventListener" with the proper type (0) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: new Document() must inherit property "removeEventListener" with the proper type (1) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: new Document() must inherit property "dispatchEvent" with the proper type (2) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL EventTarget interface: calling dispatchEvent(Event) on new Document() with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+PASS Document interface: new Document() must inherit property "implementation" with the proper type (0) 
+PASS Document interface: new Document() must inherit property "URL" with the proper type (1) 
+PASS Document interface: new Document() must inherit property "documentURI" with the proper type (2) 
+PASS Document interface: new Document() must inherit property "origin" with the proper type (3) 
+PASS Document interface: new Document() must inherit property "compatMode" with the proper type (4) 
+PASS Document interface: new Document() must inherit property "characterSet" with the proper type (5) 
+PASS Document interface: new Document() must inherit property "charset" with the proper type (6) 
+PASS Document interface: new Document() must inherit property "inputEncoding" with the proper type (7) 
+PASS Document interface: new Document() must inherit property "contentType" with the proper type (8) 
+PASS Document interface: new Document() must inherit property "doctype" with the proper type (9) 
+PASS Document interface: new Document() must inherit property "documentElement" with the proper type (10) 
+PASS Document interface: new Document() must inherit property "getElementsByTagName" with the proper type (11) 
+PASS Document interface: calling getElementsByTagName(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "getElementsByTagNameNS" with the proper type (12) 
+PASS Document interface: calling getElementsByTagNameNS(DOMString,DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "getElementsByClassName" with the proper type (13) 
+PASS Document interface: calling getElementsByClassName(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createElement" with the proper type (14) 
+PASS Document interface: calling createElement(DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createElementNS" with the proper type (15) 
+PASS Document interface: calling createElementNS(DOMString,DOMString,ElementCreationOptions) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createDocumentFragment" with the proper type (16) 
+PASS Document interface: new Document() must inherit property "createTextNode" with the proper type (17) 
+PASS Document interface: calling createTextNode(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createCDATASection" with the proper type (18) 
+PASS Document interface: calling createCDATASection(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createComment" with the proper type (19) 
+PASS Document interface: calling createComment(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createProcessingInstruction" with the proper type (20) 
+PASS Document interface: calling createProcessingInstruction(DOMString,DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "importNode" with the proper type (21) 
+PASS Document interface: calling importNode(Node,boolean) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "adoptNode" with the proper type (22) 
+PASS Document interface: calling adoptNode(Node) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createAttribute" with the proper type (23) 
+PASS Document interface: calling createAttribute(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createAttributeNS" with the proper type (24) 
+PASS Document interface: calling createAttributeNS(DOMString,DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createEvent" with the proper type (25) 
+PASS Document interface: calling createEvent(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createRange" with the proper type (26) 
+PASS Document interface: new Document() must inherit property "createNodeIterator" with the proper type (27) 
+PASS Document interface: calling createNodeIterator(Node,unsigned long,NodeFilter) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "createTreeWalker" with the proper type (28) 
+PASS Document interface: calling createTreeWalker(Node,unsigned long,NodeFilter) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "getElementById" with the proper type (29) 
+PASS Document interface: calling getElementById(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "children" with the proper type (30) 
+PASS Document interface: new Document() must inherit property "firstElementChild" with the proper type (31) 
+PASS Document interface: new Document() must inherit property "lastElementChild" with the proper type (32) 
+PASS Document interface: new Document() must inherit property "childElementCount" with the proper type (33) 
+PASS Document interface: new Document() must inherit property "prepend" with the proper type (34) 
+PASS Document interface: calling prepend([object Object],[object Object]) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "append" with the proper type (35) 
+PASS Document interface: calling append([object Object],[object Object]) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "querySelector" with the proper type (36) 
+PASS Document interface: calling querySelector(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Document interface: new Document() must inherit property "querySelectorAll" with the proper type (37) 
+PASS Document interface: calling querySelectorAll(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "ELEMENT_NODE" with the proper type (0) 
+PASS Node interface: new Document() must inherit property "ATTRIBUTE_NODE" with the proper type (1) 
+PASS Node interface: new Document() must inherit property "TEXT_NODE" with the proper type (2) 
+PASS Node interface: new Document() must inherit property "CDATA_SECTION_NODE" with the proper type (3) 
+PASS Node interface: new Document() must inherit property "ENTITY_REFERENCE_NODE" with the proper type (4) 
+PASS Node interface: new Document() must inherit property "ENTITY_NODE" with the proper type (5) 
+PASS Node interface: new Document() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type (6) 
+PASS Node interface: new Document() must inherit property "COMMENT_NODE" with the proper type (7) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_NODE" with the proper type (8) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_TYPE_NODE" with the proper type (9) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type (10) 
+PASS Node interface: new Document() must inherit property "NOTATION_NODE" with the proper type (11) 
+PASS Node interface: new Document() must inherit property "nodeType" with the proper type (12) 
+PASS Node interface: new Document() must inherit property "nodeName" with the proper type (13) 
+PASS Node interface: new Document() must inherit property "baseURI" with the proper type (14) 
+PASS Node interface: new Document() must inherit property "isConnected" with the proper type (15) 
+PASS Node interface: new Document() must inherit property "ownerDocument" with the proper type (16) 
+PASS Node interface: new Document() must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "parentNode" with the proper type (18) 
+PASS Node interface: new Document() must inherit property "parentElement" with the proper type (19) 
+PASS Node interface: new Document() must inherit property "hasChildNodes" with the proper type (20) 
+PASS Node interface: new Document() must inherit property "childNodes" with the proper type (21) 
+PASS Node interface: new Document() must inherit property "firstChild" with the proper type (22) 
+PASS Node interface: new Document() must inherit property "lastChild" with the proper type (23) 
+PASS Node interface: new Document() must inherit property "previousSibling" with the proper type (24) 
+PASS Node interface: new Document() must inherit property "nextSibling" with the proper type (25) 
+PASS Node interface: new Document() must inherit property "nodeValue" with the proper type (26) 
+PASS Node interface: new Document() must inherit property "textContent" with the proper type (27) 
+PASS Node interface: new Document() must inherit property "normalize" with the proper type (28) 
+PASS Node interface: new Document() must inherit property "cloneNode" with the proper type (29) 
+PASS Node interface: calling cloneNode(boolean) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "isEqualNode" with the proper type (30) 
+PASS Node interface: calling isEqualNode(Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "isSameNode" with the proper type (31) 
+PASS Node interface: calling isSameNode(Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type (32) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type (33) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type (34) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type (35) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type (36) 
+PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type (37) 
+PASS Node interface: new Document() must inherit property "compareDocumentPosition" with the proper type (38) 
+PASS Node interface: calling compareDocumentPosition(Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "contains" with the proper type (39) 
+PASS Node interface: calling contains(Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "lookupPrefix" with the proper type (40) 
+PASS Node interface: calling lookupPrefix(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "lookupNamespaceURI" with the proper type (41) 
+PASS Node interface: calling lookupNamespaceURI(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "isDefaultNamespace" with the proper type (42) 
+PASS Node interface: calling isDefaultNamespace(DOMString) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "insertBefore" with the proper type (43) 
+PASS Node interface: calling insertBefore(Node,Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "appendChild" with the proper type (44) 
+PASS Node interface: calling appendChild(Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "replaceChild" with the proper type (45) 
+PASS Node interface: calling replaceChild(Node,Node) on new Document() with too few arguments must throw TypeError 
+PASS Node interface: new Document() must inherit property "removeChild" with the proper type (46) 
+PASS Node interface: calling removeChild(Node) on new Document() with too few arguments must throw TypeError 
+PASS EventTarget interface: new Document() must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError 
+PASS EventTarget interface: new Document() must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on new Document() with too few arguments must throw TypeError 
+PASS EventTarget interface: new Document() must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on new Document() with too few arguments must throw TypeError 
 PASS XMLDocument interface: existence and properties of interface object 
 PASS XMLDocument interface object length 
 PASS XMLDocument interface object name 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-expected.txt
index bfd1f56..8318e20 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-expected.txt
@@ -1,8 +1,8 @@
 This is a testharness.js-based test.
-FAIL new Document(): interfaces Illegal constructor
-FAIL new Document(): children Illegal constructor
-FAIL new Document(): metadata Illegal constructor
-FAIL new Document(): characterSet aliases Illegal constructor
-FAIL new Document(): URL parsing Illegal constructor
+PASS new Document(): interfaces 
+PASS new Document(): children 
+PASS new Document(): metadata 
+PASS new Document(): characterSet aliases 
+FAIL new Document(): URL parsing assert_equals: expected "http://example.org/?%C3%A4" but got "http://example.org/?ä"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-svg.svg b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-svg.svg
new file mode 100644
index 0000000..28aaf16
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-svg.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<!-- Using windows-1252 to ensure that new Document() doesn't inherit utf-8
+     from the parent document. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"
+  width="100%" height="100%" viewBox="0 0 800 600">
+<title>Document constructor</title>
+<html:script src="/resources/testharness.js"></html:script>
+<html:script src="/resources/testharnessreport.js"></html:script>
+<html:script><![CDATA[
+test(function() {
+  var doc = new Document();
+  assert_true(doc instanceof Node, "Should be a Node");
+  assert_true(doc instanceof Document, "Should be a Document");
+  assert_false(doc instanceof XMLDocument, "Should not be an XMLDocument");
+  assert_equals(Object.getPrototypeOf(doc), Document.prototype,
+                "Document should be the primary interface");
+}, "new Document(): interfaces")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.firstChild, null, "firstChild");
+  assert_equals(doc.lastChild, null, "lastChild");
+  assert_equals(doc.doctype, null, "doctype");
+  assert_equals(doc.documentElement, null, "documentElement");
+  assert_array_equals(doc.childNodes, [], "childNodes");
+}, "new Document(): children")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.URL, "about:blank");
+  assert_equals(doc.documentURI, "about:blank");
+  assert_equals(doc.compatMode, "CSS1Compat");
+  assert_equals(doc.characterSet, "UTF-8");
+  assert_equals(doc.contentType, "application/xml");
+  assert_equals(doc.origin, document.origin);
+  assert_equals(doc.createElement("DIV").localName, "DIV");
+}, "new Document(): metadata")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.characterSet, "UTF-8", "characterSet");
+  assert_equals(doc.charset, "UTF-8", "charset");
+  assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");
+}, "new Document(): characterSet aliases")
+]]></html:script>
+</svg>
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-xml.xml b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-xml.xml
new file mode 100644
index 0000000..9aada51
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor-xml.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<!-- Using windows-1252 to ensure that new Document() doesn't inherit utf-8
+     from the parent document. -->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Document constructor</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-document" />
+</head>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script><![CDATA[
+test(function() {
+  var doc = new Document();
+  assert_true(doc instanceof Node, "Should be a Node");
+  assert_true(doc instanceof Document, "Should be a Document");
+  assert_false(doc instanceof XMLDocument, "Should not be an XMLDocument");
+  assert_equals(Object.getPrototypeOf(doc), Document.prototype,
+                "Document should be the primary interface");
+}, "new Document(): interfaces")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.firstChild, null, "firstChild");
+  assert_equals(doc.lastChild, null, "lastChild");
+  assert_equals(doc.doctype, null, "doctype");
+  assert_equals(doc.documentElement, null, "documentElement");
+  assert_array_equals(doc.childNodes, [], "childNodes");
+}, "new Document(): children")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.URL, "about:blank");
+  assert_equals(doc.documentURI, "about:blank");
+  assert_equals(doc.compatMode, "CSS1Compat");
+  assert_equals(doc.characterSet, "UTF-8");
+  assert_equals(doc.contentType, "application/xml");
+  assert_equals(doc.origin, document.origin);
+  assert_equals(doc.createElement("DIV").localName, "DIV");
+}, "new Document(): metadata")
+
+test(function() {
+  var doc = new Document();
+  assert_equals(doc.characterSet, "UTF-8", "characterSet");
+  assert_equals(doc.charset, "UTF-8", "charset");
+  assert_equals(doc.inputEncoding, "UTF-8", "inputEncoding");
+}, "new Document(): characterSet aliases")
+]]></script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor.html
index 11549da..3ebc780e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-constructor.html
@@ -33,6 +33,7 @@
   assert_equals(doc.compatMode, "CSS1Compat");
   assert_equals(doc.characterSet, "UTF-8");
   assert_equals(doc.contentType, "application/xml");
+  assert_equals(doc.origin, document.origin);
   assert_equals(doc.createElement("DIV").localName, "DIV");
 }, "new Document(): metadata")
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-doctype-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-doctype-expected.txt
deleted file mode 100644
index fcffef53..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-doctype-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Window document with doctype 
-FAIL new Document() Illegal constructor
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-childNodes-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-childNodes-expected.txt
deleted file mode 100644
index 10389f3..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-childNodes-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS Caching of Node.childNodes 
-PASS Node.childNodes on an Element. 
-PASS Node.childNodes on a DocumentFragment. 
-FAIL Node.childNodes on a Document. Illegal constructor
-PASS Iterator behavior of Node.childNodes 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-record.html b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-record.html
index 6e2ec8d..173daf0a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-record.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/headers/headers-record.html
@@ -306,6 +306,94 @@
   assert_equals(h.get("c"), "2");
 }, "Correct operation ordering with repeated keys");
 
-// Need to add symbol tests, but those are pending
-// https://github.com/heycam/webidl/issues/294 being resolved.
+test(function() {
+  this.add_cleanup(clearLog);
+  var record = {
+    a: "b",
+    [Symbol.toStringTag]: {
+      // Make sure the ToString conversion of the value happens
+      // after the ToString conversion of the key.
+      toString: function () { addLogEntry("toString", [this]); return "nope"; }
+    },
+    c: "d" };
+  var proxy = new Proxy(record, loggingHandler);
+  assert_throws(new TypeError(),
+                function() { var h = new Headers(proxy); });
+
+  assert_equals(log.length, 7);
+  // The first thing is the [[Get]] of Symbol.iterator to figure out whether
+  // we're a sequence, during overload resolution.
+  assert_array_equals(log[0], ["get", record, Symbol.iterator, proxy]);
+  // Then we have the [[OwnPropertyKeys]] from
+  // https://heycam.github.io/webidl/#es-to-record step 4.
+  assert_array_equals(log[1], ["ownKeys", record]);
+  // Then the [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[2], ["getOwnPropertyDescriptor", record, "a"]);
+  // Then the [[Get]] from step 5.2.
+  assert_array_equals(log[3], ["get", record, "a", proxy]);
+  // Then the second [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[4], ["getOwnPropertyDescriptor", record, "c"]);
+  // Then the second [[Get]] from step 5.2.
+  assert_array_equals(log[5], ["get", record, "c", proxy]);
+  // Then the third [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[6], ["getOwnPropertyDescriptor", record,
+                               Symbol.toStringTag]);
+  // Then we throw an exception converting the Symbol to a string, before we do
+  // the third [[Get]].
+}, "Basic operation with Symbol keys");
+
+test(function() {
+  this.add_cleanup(clearLog);
+  var record = {
+    a: {
+      toString: function() { addLogEntry("toString", [this]); return "b"; }
+    },
+    [Symbol.toStringTag]: {
+      toString: function () { addLogEntry("toString", [this]); return "nope"; }
+    },
+    c: {
+      toString: function() { addLogEntry("toString", [this]); return "d"; }
+    }
+  };
+  // Now make that Symbol-named property not enumerable.
+  Object.defineProperty(record, Symbol.toStringTag, { enumerable: false });
+  assert_array_equals(Reflect.ownKeys(record),
+                      ["a", "c", Symbol.toStringTag]);
+
+  var proxy = new Proxy(record, loggingHandler);
+  var h = new Headers(proxy);
+
+  assert_equals(log.length, 9);
+  // The first thing is the [[Get]] of Symbol.iterator to figure out whether
+  // we're a sequence, during overload resolution.
+  assert_array_equals(log[0], ["get", record, Symbol.iterator, proxy]);
+  // Then we have the [[OwnPropertyKeys]] from
+  // https://heycam.github.io/webidl/#es-to-record step 4.
+  assert_array_equals(log[1], ["ownKeys", record]);
+  // Then the [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[2], ["getOwnPropertyDescriptor", record, "a"]);
+  // Then the [[Get]] from step 5.2.
+  assert_array_equals(log[3], ["get", record, "a", proxy]);
+  // Then the ToString on the value.
+  assert_array_equals(log[4], ["toString", record.a]);
+  // Then the second [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[5], ["getOwnPropertyDescriptor", record, "c"]);
+  // Then the second [[Get]] from step 5.2.
+  assert_array_equals(log[6], ["get", record, "c", proxy]);
+  // Then the ToString on the value.
+  assert_array_equals(log[7], ["toString", record.c]);
+  // Then the third [[GetOwnProperty]] from step 5.1.
+  assert_array_equals(log[8], ["getOwnPropertyDescriptor", record,
+                               Symbol.toStringTag]);
+  // No [[Get]] because not enumerable.
+
+  // Check the results.
+  assert_equals([...h].length, 2);
+  assert_array_equals([...h.keys()], ["a", "c"]);
+  assert_true(h.has("a"));
+  assert_equals(h.get("a"), "b");
+  assert_true(h.has("c"));
+  assert_equals(h.get("c"), "d");
+}, "Operation with non-enumerable Symbol keys");
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt
index 082e6fa..2787f89 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt
@@ -6,14 +6,14 @@
 PASS Document interface: attribute onfullscreenchange 
 PASS Document interface: attribute onfullscreenerror 
 FAIL Document interface: attribute fullscreenElement assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
-FAIL Document must be primary interface of new Document assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Stringification of new Document assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "fullscreenEnabled" with the proper type (29) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "fullscreen" with the proper type (30) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "exitFullscreen" with the proper type (31) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "onfullscreenchange" with the proper type (32) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "onfullscreenerror" with the proper type (33) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
-FAIL Document interface: new Document must inherit property "fullscreenElement" with the proper type (35) assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor"
+PASS Document must be primary interface of new Document 
+PASS Stringification of new Document 
+PASS Document interface: new Document must inherit property "fullscreenEnabled" with the proper type (29) 
+FAIL Document interface: new Document must inherit property "fullscreen" with the proper type (30) assert_inherits: property "fullscreen" not found in prototype chain
+PASS Document interface: new Document must inherit property "exitFullscreen" with the proper type (31) 
+PASS Document interface: new Document must inherit property "onfullscreenchange" with the proper type (32) 
+PASS Document interface: new Document must inherit property "onfullscreenerror" with the proper type (33) 
+PASS Document interface: new Document must inherit property "fullscreenElement" with the proper type (35) 
 FAIL ShadowRoot interface: attribute fullscreenElement assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
 FAIL Element interface: operation requestFullscreen() assert_unreached: Throws "TypeError: Illegal invocation" instead of rejecting promise Reached unreachable code
 PASS Element must be primary interface of document.createElementNS(null, "test") 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt
index 6282ea6..740f2dc8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain-expected.txt
@@ -1,6 +1,6 @@
 This is a testharness.js-based test.
 PASS sanity checks 
 PASS current document 
-FAIL new document Illegal constructor
+FAIL new document assert_equals: new document has empty domain expected "" but got "web-platform.test"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/Document-defaultView-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/Document-defaultView-expected.txt
deleted file mode 100644
index af71375d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/Document-defaultView-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-PASS Document in a browsing context 
-FAIL Document created with the Document constructor Illegal constructor
-PASS Document created with createDocument 
-PASS Document created with createHTMLDocument 
-PASS Document created with XML DOMParser 
-PASS Document created with HTML DOMParser 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt
index 6f5609653..8e9e8e7 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt
@@ -6,7 +6,6 @@
 PASS TryAllocate('Attr') is 'exception'
 PASS TryAllocate('CharacterData') is 'exception'
 PASS TryAllocate('CDATASection') is 'exception'
-PASS TryAllocate('Document') is 'exception'
 PASS TryAllocate('DocumentType') is 'exception'
 PASS TryAllocate('Element') is 'exception'
 PASS TryAllocate('EventTarget') is 'exception'
@@ -121,6 +120,9 @@
 PASS TryAllocate('DOMParser') is '[object DOMParser]'
 PASS TryAllocate('DOMParser') is '[object DOMParser]'
 PASS TryAllocate('DOMParser') is '[object DOMParser]'
+PASS TryAllocate('Document') is '[object Document]'
+PASS TryAllocate('Document') is '[object Document]'
+PASS TryAllocate('Document') is '[object Document]'
 PASS TryAllocate('DocumentFragment') is '[object DocumentFragment]'
 PASS TryAllocate('DocumentFragment') is '[object DocumentFragment]'
 PASS TryAllocate('DocumentFragment') is '[object DocumentFragment]'
diff --git a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors.html b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors.html
index 4d7c572..9a63addb 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors.html
@@ -16,7 +16,6 @@
     'Attr',
     'CharacterData',
     'CDATASection',
-    'Document',
     'DocumentType',
     'Element',
     'EventTarget',
@@ -124,6 +123,7 @@
     'Comment',
     'DataTransfer',
     'DOMParser',
+    'Document',
     'DocumentFragment',
     'Range',
     'Text',
diff --git a/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImpl.h b/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImpl.h
index 5276efa..f693688 100644
--- a/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImpl.h
+++ b/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImpl.h
@@ -430,13 +430,10 @@
     // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks
     // web-platform-tests' headers-record.html and deviates from the spec
     // algorithm.
-    // Symbols are being skipped due to
-    // https://github.com/heycam/webidl/issues/294.
     if (!v8_object
              ->GetOwnPropertyNames(context,
                                    static_cast<v8::PropertyFilter>(
-                                       v8::PropertyFilter::ALL_PROPERTIES |
-                                       v8::PropertyFilter::SKIP_SYMBOLS))
+                                       v8::PropertyFilter::ALL_PROPERTIES))
              .ToLocal(&keys)) {
       exception_state.RethrowV8Exception(block.Exception());
       return ImplType();
@@ -464,11 +461,14 @@
         return ImplType();
       }
 
+      // V8's GetOwnPropertyNames() does not convert numeric property indices
+      // to strings, so we have to do it ourselves.
+      if (!key->IsName())
+        key = key->ToString(context).ToLocalChecked();
+
       // "4.1. Let desc be ? O.[[GetOwnProperty]](key)."
       v8::Local<v8::Value> desc;
-      if (!v8_object
-               ->GetOwnPropertyDescriptor(
-                   context, key->ToString(context).ToLocalChecked())
+      if (!v8_object->GetOwnPropertyDescriptor(context, key.As<v8::Name>())
                .ToLocal(&desc)) {
         exception_state.RethrowV8Exception(block.Exception());
         return ImplType();
diff --git a/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImplTest.cpp b/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImplTest.cpp
index 71a82a2f..8203b29 100644
--- a/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImplTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/NativeValueTraitsImplTest.cpp
@@ -200,27 +200,15 @@
     EXPECT_TRUE(V8CallBoolean(v8_object->Set(
         scope.GetContext(), ToV8(&scope, "foo"), ToV8(&scope, 42))));
 
-    NonThrowableExceptionState exception_state;
+    // The presence of symbols should throw a TypeError when the conversion to
+    // the record's key type is attempted.
+    DummyExceptionStateForTesting exception_state;
     const auto& record =
         NativeValueTraits<IDLRecord<IDLString, IDLShort>>::NativeValue(
             scope.GetIsolate(), v8_object, exception_state);
-    EXPECT_EQ(1U, record.size());
-    EXPECT_EQ(std::make_pair(String("foo"), int16_t(42)), record[0]);
-  }
-  {
-    v8::Local<v8::Object> v8_object = v8::Object::New(scope.GetIsolate());
-    EXPECT_TRUE(V8CallBoolean(v8_object->Set(
-        scope.GetContext(), v8::Symbol::GetToStringTag(scope.GetIsolate()),
-        ToV8(&scope, 34))));
-    EXPECT_TRUE(V8CallBoolean(v8_object->Set(
-        scope.GetContext(), ToV8(&scope, "foo"), ToV8(&scope, 42))));
-
-    NonThrowableExceptionState exception_state;
-    const auto& record =
-        NativeValueTraits<IDLRecord<IDLString, IDLShort>>::NativeValue(
-            scope.GetIsolate(), v8_object, exception_state);
-    EXPECT_EQ(1U, record.size());
-    EXPECT_EQ(std::make_pair(String("foo"), int16_t(42)), record[0]);
+    EXPECT_TRUE(record.IsEmpty());
+    EXPECT_TRUE(exception_state.HadException());
+    EXPECT_TRUE(exception_state.Message().IsEmpty());
   }
   {
     v8::Local<v8::Object> v8_parent_object =
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index 45cd4f15..3677190d 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -491,6 +491,14 @@
   DEFINE_INLINE_VIRTUAL_TRACE() { ContextLifecycleObserver::Trace(visitor); }
 };
 
+Document* Document::Create(const Document& document) {
+  Document* new_document = new Document(
+      DocumentInit::FromContext(const_cast<Document*>(&document), BlankURL()));
+  new_document->SetSecurityOrigin(document.GetSecurityOrigin());
+  new_document->SetContextFeatures(document.GetContextFeatures());
+  return new_document;
+}
+
 Document::Document(const DocumentInit& initializer,
                    DocumentClassFlags document_classes)
     : ContainerNode(0, kCreateDocument),
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 0f79aedd8..ad3b948 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -261,6 +261,11 @@
   static Document* Create(const DocumentInit& initializer = DocumentInit()) {
     return new Document(initializer);
   }
+  // Factory for web-exposed Document constructor. The argument document must be
+  // a document instance representing window.document, and it works as the
+  // source of ExecutionContext and security origin of the new document.
+  // https://dom.spec.whatwg.org/#dom-document-document
+  static Document* Create(const Document&);
   ~Document() override;
 
   MediaQueryMatcher& GetMediaQueryMatcher();
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl
index ec933ed0..48f4f0c 100644
--- a/third_party/WebKit/Source/core/dom/Document.idl
+++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -34,8 +34,10 @@
 
 // https://dom.spec.whatwg.org/#interface-document
 
-// FIXME: Document should have a constructor. crbug.com/238234
-interface Document : Node {
+[
+    Constructor(),
+    ConstructorCallWith=Document,
+] interface Document : Node {
     [SameObject] readonly attribute DOMImplementation implementation;
     [ImplementedAs=urlForBinding] readonly attribute DOMString URL;
     // FIXME: documentURI should not be nullable.
diff --git a/third_party/WebKit/Source/platform/wtf/Assertions.h b/third_party/WebKit/Source/platform/wtf/Assertions.h
index a39a133e..33e2b7a 100644
--- a/third_party/WebKit/Source/platform/wtf/Assertions.h
+++ b/third_party/WebKit/Source/platform/wtf/Assertions.h
@@ -120,27 +120,10 @@
 #define CRASH() IMMEDIATE_CRASH()
 #endif
 
-// ASSERT
-//  These macros are compiled out of release builds.
-//  Expressions inside them are evaluated in debug builds only.
-//  This is deprecated. We should use:
-//    - DCHECK() for ASSERT()
-#if OS(WIN)
-// FIXME: Change to use something other than ASSERT to avoid this conflict with
-// the underlying platform.
-#undef ASSERT
-#endif
-
 #define DCHECK_AT(assertion, file, line)                            \
   LAZY_STREAM(logging::LogMessage(file, line, #assertion).stream(), \
               DCHECK_IS_ON() ? !(assertion) : false)
 
-#if DCHECK_IS_ON()
-#define ASSERT(assertion) DCHECK(assertion)
-#else
-#define ASSERT(assertion) ((void)0)
-#endif
-
 // Users must test "#if ENABLE(SECURITY_ASSERT)", which helps ensure
 // that code testing this macro has included this header.
 #if defined(ADDRESS_SANITIZER) || DCHECK_IS_ON()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
index 0ade6bf..bc5929d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations.py
@@ -27,6 +27,7 @@
 import logging
 import webbrowser
 
+from webkitpy.layout_tests.models.test_expectations import CHROMIUM_BUG_PREFIX
 from webkitpy.layout_tests.models.test_expectations import TestExpectations
 from webkitpy.tool.commands.flaky_tests import FlakyTests
 
@@ -51,18 +52,16 @@
         _log.warning("Didn't find generic expectations file at: " + expectations_file)
         return 1
 
-    remove_flakes_o_matic = RemoveFlakesOMatic(host,
-                                               port,
-                                               bot_test_expectations_factory,
-                                               webbrowser)
+    remove_flakes_o_matic = RemoveFlakesOMatic(
+        host, port, bot_test_expectations_factory, webbrowser)
 
     test_expectations = remove_flakes_o_matic.get_updated_test_expectations()
 
     if args.show_results:
         remove_flakes_o_matic.show_removed_results()
 
-    remove_flakes_o_matic.write_test_expectations(test_expectations,
-                                                  expectations_file)
+    remove_flakes_o_matic.write_test_expectations(test_expectations, expectations_file)
+    remove_flakes_o_matic.print_suggested_commit_description()
     return 0
 
 
@@ -319,15 +318,13 @@
         return test_expectations
 
     def show_removed_results(self):
-        """Opens removed lines in the results dashboard.
+        """Opens a browser showing the removed lines in the results dashboard.
 
-        Opens the results dashboard in the browser, showing all the tests for lines that the script
-        removed from the TestExpectations file and allowing the user to manually confirm the
-        results.
+        Opens the results dashboard in the browser, showing all the tests for
+        lines removed from the TestExpectations file, allowing the user to
+        manually confirm the results.
         """
-        removed_test_names = ','.join(x.name for x in self._expectations_to_remove())
-        url = FlakyTests.FLAKINESS_DASHBOARD_URL % removed_test_names
-
+        url = self._flakiness_dashboard_url()
         _log.info('Opening results dashboard: ' + url)
         self._browser.open(url)
 
@@ -342,3 +339,26 @@
         self._host.filesystem.write_text_file(
             test_expectations_file,
             TestExpectations.list_to_string(test_expectations, reconstitute_only_these=[]))
+
+    def print_suggested_commit_description(self):
+        """Prints the body of a suggested CL description after removing some lines."""
+        dashboard_url = self._flakiness_dashboard_url()
+        bugs = ','.join(self._bug_numbers())
+        message = ('Remove flaky TestExpectations for tests which appear non-flaky recently.\n\n'
+                   'This change was made by the update-test-expectations script.\n\n'
+                   'Recent test results history:\n%s\n\n'
+                   'BUG=%s') % (dashboard_url, bugs)
+        _log.info('Suggested commit description:\n' + message)
+
+    def _flakiness_dashboard_url(self):
+        removed_test_names = ','.join(x.name for x in self._expectations_to_remove())
+        return FlakyTests.FLAKINESS_DASHBOARD_URL % removed_test_names
+
+    def _bug_numbers(self):
+        """Returns the list of all bug numbers affected by this change."""
+        numbers = []
+        for line in self._expectations_to_remove():
+            for bug in line.bugs:
+                if bug.startswith(CHROMIUM_BUG_PREFIX):
+                    numbers.append(bug[len(CHROMIUM_BUG_PREFIX):])
+        return sorted(numbers)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
index 13817716..3e5e9b7f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
@@ -1061,3 +1061,44 @@
         self.assertEqual(
             FlakyTests.FLAKINESS_DASHBOARD_URL % 'test/a.html,test/b.html',
             self._mock_web_browser.opened_url)
+
+    def test_suggested_commit_description(self):
+        """Tests display of the suggested commit message.
+        """
+        test_expectations_before = (
+            """# Remove this since it's passing all runs.
+            crbug.com/2222 test/a.html [ Failure Pass ]
+            # Remove this since, although there's a failure, it's not a timeout.
+            crbug.com/1111 test/b.html [ Pass Timeout ]
+            # Keep since we have both crashes and passes.
+            crbug.com/3333 test/c.html [ Crash Pass ]""")
+
+        self._define_builders({
+            'WebKit Linux': {
+                'port_name': 'linux-trusty',
+                'specifiers': ['Trusty', 'Release']
+            },
+        })
+        self._port.all_build_types = ('release',)
+        self._port.all_systems = (('trusty', 'x86_64'),)
+
+        self._parse_expectations(test_expectations_before)
+        self._expectation_factory.all_results_by_builder = {
+            'WebKit Linux': {
+                'test/a.html': ['PASS', 'PASS', 'PASS'],
+                'test/b.html': ['PASS', 'IMAGE', 'PASS'],
+                'test/c.html': ['PASS', 'CRASH', 'PASS'],
+            }
+        }
+        self._flake_remover.print_suggested_commit_description()
+        self.assertLog([
+            'INFO: Deleting line "crbug.com/2222 test/a.html [ Failure Pass ]"\n',
+            'INFO: Deleting line "crbug.com/1111 test/b.html [ Pass Timeout ]"\n',
+            'INFO: Suggested commit description:\n'
+            'Remove flaky TestExpectations for tests which appear non-flaky recently.\n\n'
+            'This change was made by the update-test-expectations script.\n\n'
+            'Recent test results history:\n'
+            'https://test-results.appspot.com/dashboards/flakiness_dashboard.html'
+            '#testType=webkit_layout_tests&tests=test/a.html,test/b.html\n\n'
+            'BUG=1111,2222\n'
+        ])
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index edaeb30e..0bf0e05 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -249,7 +249,8 @@
       self.extra_gn_args_str = (' exclude_unwind_tables=true '
           'ffmpeg_branding="Chrome" proprietary_codecs=true')
     if self.IsLinux():
-      self.extra_gn_args_str += ' allow_posix_link_time_opt=false'
+      self.extra_gn_args_str += (
+          ' allow_posix_link_time_opt=false generate_linker_map=true')
     self.target = self.target if self.IsAndroid() else 'chrome'
 
   def _GenGnCmd(self):
diff --git a/tools/gdb/gdb_chrome.py b/tools/gdb/gdb_chrome.py
index f3073e3..67e333f 100644
--- a/tools/gdb/gdb_chrome.py
+++ b/tools/gdb/gdb_chrome.py
@@ -107,26 +107,6 @@
 pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter)
 
 
-class SizePrinter(Printer):
-    def to_string(self):
-        return '%sx%s' % (self.val['width_'], self.val['height_'])
-pp_set.add_printer('gfx::Size', '^gfx::(Size|SizeF|SizeBase<.*>)$', SizePrinter)
-
-
-class PointPrinter(Printer):
-    def to_string(self):
-        return '%s,%s' % (self.val['x_'], self.val['y_'])
-pp_set.add_printer('gfx::Point', '^gfx::(Point|PointF|PointBase<.*>)$',
-                   PointPrinter)
-
-
-class RectPrinter(Printer):
-    def to_string(self):
-        return '%s %s' % (self.val['origin_'], self.val['size_'])
-pp_set.add_printer('gfx::Rect', '^gfx::(Rect|RectF|RectBase<.*>)$',
-                   RectPrinter)
-
-
 class SmartPtrPrinter(Printer):
     def to_string(self):
         return '%s%s' % (self.typename, typed_ptr(self.ptr()))
@@ -246,7 +226,7 @@
 pp_set.add_printer('base::ManualConstructor', '^base::ManualConstructor<.*>$', ManualConstructorPrinter)
 
 
-class FlatMapPrinter(object):
+class FlatTreePrinter(object):
     def __init__(self, val):
         self.val = val
 
@@ -256,8 +236,11 @@
         # Python is much more complicated and this output is reasonable.
         # (Without this printer, a flat_map will output 7 lines of internal
         # template goop before the vector contents.)
-        return 'base::flat_map with ' + str(self.val['impl_']['body_'])
-pp_set.add_printer('base::flat_map', '^base::flat_map<.*>$', FlatMapPrinter)
+        return 'base::flat_tree with ' + str(self.val['impl_']['body_'])
+pp_set.add_printer('base::flat_map', '^base::flat_map<.*>$', FlatTreePrinter)
+pp_set.add_printer('base::flat_set', '^base::flat_set<.*>$', FlatTreePrinter)
+pp_set.add_printer('base::flat_tree', '^base::internal::flat_tree<.*>$',
+                   FlatTreePrinter)
 
 
 class ValuePrinter(object):
@@ -290,7 +273,10 @@
             valuestr = self.val['list_']
 
         return "base::Value of type %s = %s" % (typestr, str(valuestr))
-pp_set.add_printer('base::Value', '^base::(List|Dictionary|)Value$', ValuePrinter)
+pp_set.add_printer('base::Value', '^base::Value$', ValuePrinter)
+pp_set.add_printer('base::ListValue', '^base::ListValue$', ValuePrinter)
+pp_set.add_printer('base::DictionaryValue', '^base::DictionaryValue$',
+                   ValuePrinter)
 
 
 class IpcMessagePrinter(Printer):
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 58a44813..f55e2e4 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -13036,8 +13036,7 @@
   </summary>
 </histogram>
 
-<histogram name="DnsProbe.Probe.NcnOffline.Result"
-    enum="DnsProbe.ObsoleteProbeResult">
+<histogram name="DnsProbe.Probe.NcnOffline.Result">
   <obsolete>
     Removed 7/2013.
   </obsolete>
@@ -13057,8 +13056,7 @@
   </summary>
 </histogram>
 
-<histogram name="DnsProbe.Probe.NcnOnline.Result"
-    enum="DnsProbe.ObsoleteProbeResult">
+<histogram name="DnsProbe.Probe.NcnOnline.Result">
   <obsolete>
     Removed 7/2013.
   </obsolete>
@@ -13068,7 +13066,7 @@
   </summary>
 </histogram>
 
-<histogram name="DnsProbe.Probe.Result" enum="DnsProbe.ObsoleteProbeResult">
+<histogram name="DnsProbe.Probe.Result">
   <obsolete>
     Renamed 7/2013 to DnsProbe.ProbeResult.  (Also switched to the full
     DnsProbe.ProbeStatus enum.)
@@ -46403,9 +46401,9 @@
 
 <histogram name="Omnibox.ProgressBarBreakPointUpdateCount"
     units="break point updates">
-  <obselete>
+  <obsolete>
     Obselete 05/16/2017. Data is unused (crbug.com/719801).
-  </obselete>
+  </obsolete>
   <owner>kkimlabs@chromium.org</owner>
   <summary>
     The number of progress bar break point updates from page load started to
@@ -46414,9 +46412,9 @@
 </histogram>
 
 <histogram name="Omnibox.ProgressBarUpdateCount" units="frame updates">
-  <obselete>
+  <obsolete>
     Obselete 05/16/2017. Data is unused (crbug.com/719801).
-  </obselete>
+  </obsolete>
   <owner>kkimlabs@chromium.org</owner>
   <summary>
     The number of progress bar frame updates from page load started to page load
@@ -72083,16 +72081,12 @@
 
 <histogram base="true" name="Storage.BytesRead" units="bytes">
   <owner>michaeln@chromium.org</owner>
-  <summary>
-    The number of bytes read. Recorded on each read.
-  </summary>
+  <summary>The number of bytes read. Recorded on each read.</summary>
 </histogram>
 
 <histogram base="true" name="Storage.BytesWritten" units="bytes">
   <owner>michaeln@chromium.org</owner>
-  <summary>
-    The number of bytes written. Recorded on each write.
-  </summary>
+  <summary>The number of bytes written. Recorded on each write.</summary>
 </histogram>
 
 <histogram name="Storage.ImportantSites.CBDChosenReason"
@@ -82167,8 +82161,8 @@
   <owner>philipel@chromium.org</owner>
   <summary>
     A successful probing attempt for a given bitrate, triggered by an update to
-    the max configured bitrate. NOTE! This is not the resulting bitrate from
-    a probing attempt, see WebRTC.BWE.MidCallProbing.ProbedKbps.
+    the max configured bitrate. NOTE! This is not the resulting bitrate from a
+    probing attempt, see WebRTC.BWE.MidCallProbing.ProbedKbps.
   </summary>
 </histogram>
 
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py
index 6b9841d8..9646110 100644
--- a/tools/perf/benchmarks/system_health_smoke_test.py
+++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -63,6 +63,9 @@
 
   # crbug.com/699966
   'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.multitab:misc:typical24', # pylint: disable=line-too-long
+
+  # crbug.com/725386
+  'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.browse:social:twitter', # pylint: disable=line-too-long
 })