diff --git a/AUTHORS b/AUTHORS
index 397d7c96..4618223b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -722,6 +722,7 @@
 U. Artie Eoff <ullysses.a.eoff@intel.com>
 Umar Hansa <umar.hansa@gmail.com>
 Upendra Gowda <upendrag.gowda@gmail.com>
+Uzair Jaleel <uzair.jaleel@samsung.com>
 Vaibhav Agrawal <vaibhav1.a@samsung.com>
 Valentin Ilie <valentin.ilie@intel.com>
 Vamshikrishna Yellenki <vamshi@motorola.com>
diff --git a/DEPS b/DEPS
index d23886c7..5d0be82 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': 'a6ae1f7cda072ff814a838e2d9013a017552cc35',
+  'skia_revision': 'dc3c336c84dbbf43c68337ebb1b640d5c948e2aa',
   # 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': '06d36330e481d098c19fe047809d45955837ee46',
+  'v8_revision': 'f7036b132f6bcce9312b52a9ba386ae487280713',
   # 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.
@@ -60,7 +60,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '2ddef8858e5015140f374d5c06d1a68b7c78af10',
+  'swiftshader_revision': '38182314999cc26c6510fbb5d6372fda8847c1b8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -100,7 +100,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
-  'libfuzzer_revision': 'eebc6eb55995a29173f269baf071046fcd2e0f4b',
+  'libfuzzer_revision': 'a746f0ef810637b40784e808bad49aa2ef1bde8b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-node-modules
   # and whatever else without interference from each other.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index f6f6a1c..2df1e018 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -413,8 +413,6 @@
     "common/system/tray/tray_popup_header_button.cc",
     "common/system/tray/tray_popup_header_button.h",
     "common/system/tray/tray_popup_ink_drop_style.h",
-    "common/system/tray/tray_popup_item_container.cc",
-    "common/system/tray/tray_popup_item_container.h",
     "common/system/tray/tray_popup_item_style.cc",
     "common/system/tray/tray_popup_item_style.h",
     "common/system/tray/tray_popup_utils.cc",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index c132a7b..fa81be1 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -84,13 +84,12 @@
   DISALLOW_COPY_AND_ASSIGN(TestTarget);
 };
 
-class ReleaseAccelerator : public ui::Accelerator {
- public:
-  ReleaseAccelerator(ui::KeyboardCode keycode, int modifiers)
-      : ui::Accelerator(keycode, modifiers) {
-    set_type(ui::ET_KEY_RELEASED);
-  }
-};
+ui::Accelerator CreateReleaseAccelerator(ui::KeyboardCode key_code,
+                                         int modifiers) {
+  ui::Accelerator accelerator(key_code, modifiers);
+  accelerator.set_key_state(ui::Accelerator::KeyState::RELEASED);
+  return accelerator;
+}
 
 class DummyBrightnessControlDelegate : public BrightnessControlDelegate {
  public:
@@ -216,12 +215,12 @@
   static AcceleratorController* GetController();
 
   static bool ProcessInController(const ui::Accelerator& accelerator) {
-    if (accelerator.type() == ui::ET_KEY_RELEASED) {
+    if (accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
       // If the |accelerator| should trigger on release, then we store the
       // pressed version of it first in history then the released one to
       // simulate what happens in reality.
       ui::Accelerator pressed_accelerator = accelerator;
-      pressed_accelerator.set_type(ui::ET_KEY_PRESSED);
+      pressed_accelerator.set_key_state(ui::Accelerator::KeyState::PRESSED);
       GetController()->accelerator_history()->StoreCurrentAccelerator(
           pressed_accelerator);
     }
@@ -286,7 +285,7 @@
 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
   ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
   ui::Accelerator release(press);
-  release.set_type(ui::ET_KEY_RELEASED);
+  release.set_key_state(ui::Accelerator::KeyState::RELEASED);
   ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
   ASSERT_TRUE(ewh);
   StubForTest(ewh);
@@ -308,7 +307,7 @@
 TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) {
   ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
   ui::Accelerator release(press);
-  release.set_type(ui::ET_KEY_RELEASED);
+  release.set_key_state(ui::Accelerator::KeyState::RELEASED);
   ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
   ASSERT_TRUE(ewh);
   StubForTest(ewh);
@@ -747,11 +746,9 @@
 
 TEST_F(AcceleratorControllerTest, AutoRepeat) {
   ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_CONTROL_DOWN);
-  accelerator_a.set_type(ui::ET_KEY_PRESSED);
   TestTarget target_a;
   GetController()->Register({accelerator_a}, &target_a);
   ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN);
-  accelerator_b.set_type(ui::ET_KEY_PRESSED);
   TestTarget target_b;
   GetController()->Register({accelerator_b}, &target_b);
 
@@ -1032,8 +1029,8 @@
   EXPECT_EQ(ui::VKEY_LWIN, GetCurrentAccelerator().key_code());
   EXPECT_EQ(0u, test_app_list_presenter.toggle_count());
 
-  EXPECT_TRUE(
-      ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
+  EXPECT_TRUE(ProcessInController(
+      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
   RunAllPendingInMessageLoop();
   EXPECT_EQ(1u, test_app_list_presenter.toggle_count());
   EXPECT_EQ(ui::VKEY_LWIN, GetPreviousAccelerator().key_code());
@@ -1042,8 +1039,8 @@
   delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
   EXPECT_FALSE(
       ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
-  EXPECT_FALSE(
-      ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
+  EXPECT_FALSE(ProcessInController(
+      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
   delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
   RunAllPendingInMessageLoop();
   EXPECT_EQ(1u, test_app_list_presenter.toggle_count());
@@ -1051,8 +1048,8 @@
   // Turning off spoken feedback should allow the AppList to toggle again.
   EXPECT_FALSE(
       ProcessInController(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
-  EXPECT_TRUE(
-      ProcessInController(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
+  EXPECT_TRUE(ProcessInController(
+      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
   RunAllPendingInMessageLoop();
   EXPECT_EQ(2u, test_app_list_presenter.toggle_count());
 
@@ -1062,7 +1059,7 @@
   RunAllPendingInMessageLoop();
   EXPECT_EQ(3u, test_app_list_presenter.toggle_count());
   EXPECT_FALSE(ProcessInController(
-      ReleaseAccelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
+      CreateReleaseAccelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
   RunAllPendingInMessageLoop();
   EXPECT_EQ(3u, test_app_list_presenter.toggle_count());
 }
@@ -1070,9 +1067,8 @@
 TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
   // Test IME shortcuts.
   ui::Accelerator control_space_down(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
-  control_space_down.set_type(ui::ET_KEY_PRESSED);
   ui::Accelerator control_space_up(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
-  control_space_up.set_type(ui::ET_KEY_RELEASED);
+  control_space_up.set_key_state(ui::Accelerator::KeyState::RELEASED);
   const ui::Accelerator convert(ui::VKEY_CONVERT, ui::EF_NONE);
   const ui::Accelerator non_convert(ui::VKEY_NONCONVERT, ui::EF_NONE);
   const ui::Accelerator wide_half_1(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE);
@@ -1203,8 +1199,8 @@
   EXPECT_FALSE(ProcessInController(press_alt_then_search));
   // When you release Search before Alt, the key_code is still VKEY_LWIN and
   // Alt is still the modifier.
-  const ReleaseAccelerator release_search_before_alt(ui::VKEY_LWIN,
-                                                     ui::EF_ALT_DOWN);
+  const ui::Accelerator release_search_before_alt(
+      CreateReleaseAccelerator(ui::VKEY_LWIN, ui::EF_ALT_DOWN));
   EXPECT_TRUE(ProcessInController(release_search_before_alt));
   EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
   input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
@@ -1219,8 +1215,8 @@
 
   // 3. Press Alt, Press Search, Release Alt, Release Search.
   EXPECT_FALSE(ProcessInController(press_alt_then_search));
-  const ReleaseAccelerator release_alt_before_search(ui::VKEY_MENU,
-                                                     ui::EF_COMMAND_DOWN);
+  const ui::Accelerator release_alt_before_search(
+      CreateReleaseAccelerator(ui::VKEY_MENU, ui::EF_COMMAND_DOWN));
   EXPECT_TRUE(ProcessInController(release_alt_before_search));
   EXPECT_TRUE(input_method_manager->GetImeKeyboard()->CapsLockIsEnabled());
   input_method_manager->GetImeKeyboard()->SetCapsLockEnabled(false);
@@ -1487,8 +1483,9 @@
 
   ui::Accelerator CreateAccelerator(const AcceleratorData& data) const {
     ui::Accelerator result(data.keycode, data.modifiers);
-    result.set_type(data.trigger_on_press ? ui::ET_KEY_PRESSED
-                                          : ui::ET_KEY_RELEASED);
+    result.set_key_state(data.trigger_on_press
+                             ? ui::Accelerator::KeyState::PRESSED
+                             : ui::Accelerator::KeyState::RELEASED);
     return result;
   }
 
diff --git a/ash/common/accelerators/accelerator_controller.cc b/ash/common/accelerators/accelerator_controller.cc
index e4af731e..50fbb48 100644
--- a/ash/common/accelerators/accelerator_controller.cc
+++ b/ash/common/accelerators/accelerator_controller.cc
@@ -157,8 +157,9 @@
                                   int modifiers,
                                   bool trigger_on_press) {
   ui::Accelerator accelerator(keycode, modifiers);
-  accelerator.set_type(trigger_on_press ? ui::ET_KEY_PRESSED
-                                        : ui::ET_KEY_RELEASED);
+  accelerator.set_key_state(trigger_on_press
+                                ? ui::Accelerator::KeyState::PRESSED
+                                : ui::Accelerator::KeyState::RELEASED);
   return accelerator;
 }
 
@@ -283,7 +284,7 @@
 void HandlePreviousIme(ImeControlDelegate* ime_control_delegate,
                        const ui::Accelerator& accelerator) {
   base::RecordAction(UserMetricsAction("Accel_Previous_Ime"));
-  if (accelerator.type() == ui::ET_KEY_PRESSED)
+  if (accelerator.key_state() == ui::Accelerator::KeyState::PRESSED)
     ime_control_delegate->HandlePreviousIme();
   // Else: consume the Ctrl+Space ET_KEY_RELEASED event but do not do anything.
 }
@@ -369,7 +370,8 @@
     // If something else was pressed between the Search key (LWIN)
     // being pressed and released, then ignore the release of the
     // Search key.
-    if (previous_accelerator.type() != ui::ET_KEY_PRESSED ||
+    if (previous_accelerator.key_state() !=
+            ui::Accelerator::KeyState::PRESSED ||
         previous_accelerator.key_code() != ui::VKEY_LWIN) {
       return false;
     }
@@ -466,7 +468,7 @@
 
 bool CanHandleDisableCapsLock(const ui::Accelerator& previous_accelerator) {
   ui::KeyboardCode previous_key_code = previous_accelerator.key_code();
-  if (previous_accelerator.type() == ui::ET_KEY_RELEASED ||
+  if (previous_accelerator.key_state() == ui::Accelerator::KeyState::RELEASED ||
       (previous_key_code != ui::VKEY_LSHIFT &&
        previous_key_code != ui::VKEY_SHIFT &&
        previous_key_code != ui::VKEY_RSHIFT)) {
@@ -554,11 +556,12 @@
   // This shortcust is set to be trigger on release. Either the current
   // accelerator is a Search release or Alt release.
   if (accelerator.key_code() == ui::VKEY_LWIN &&
-      accelerator.type() == ui::ET_KEY_RELEASED) {
+      accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
     // The previous must be either an Alt press or Search press:
     // 1. Press Alt, Press Search, Release Search, Release Alt.
     // 2. Press Search, Press Alt, Release Search, Release Alt.
-    if (previous_accelerator.type() == ui::ET_KEY_PRESSED &&
+    if (previous_accelerator.key_state() ==
+            ui::Accelerator::KeyState::PRESSED &&
         (previous_accelerator.key_code() == ui::VKEY_LWIN ||
          previous_accelerator.key_code() == ui::VKEY_MENU)) {
       return ime && ime->GetImeKeyboard();
@@ -567,11 +570,12 @@
 
   // Alt release.
   if (accelerator.key_code() == ui::VKEY_MENU &&
-      accelerator.type() == ui::ET_KEY_RELEASED) {
+      accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) {
     // The previous must be either an Alt press or Search press:
     // 3. Press Alt, Press Search, Release Alt, Release Search.
     // 4. Press Search, Press Alt, Release Alt, Release Search.
-    if (previous_accelerator.type() == ui::ET_KEY_PRESSED &&
+    if (previous_accelerator.key_state() ==
+            ui::Accelerator::KeyState::PRESSED &&
         (previous_accelerator.key_code() == ui::VKEY_LWIN ||
          previous_accelerator.key_code() == ui::VKEY_MENU)) {
       return ime && ime->GetImeKeyboard();
diff --git a/ash/common/system/chromeos/audio/volume_view.cc b/ash/common/system/chromeos/audio/volume_view.cc
index 47cfabe..edd95b1 100644
--- a/ash/common/system/chromeos/audio/volume_view.cc
+++ b/ash/common/system/chromeos/audio/volume_view.cc
@@ -11,7 +11,6 @@
 #include "ash/common/system/tray/actionable_view.h"
 #include "ash/common/system/tray/system_tray_item.h"
 #include "ash/common/system/tray/tray_constants.h"
-#include "ash/common/system/tray/tray_popup_item_container.h"
 #include "ash/common/system/tray/tray_popup_utils.h"
 #include "ash/common/system/tray/tri_view.h"
 #include "ash/common/wm_shell.h"
diff --git a/ash/common/system/tray/system_tray_bubble.cc b/ash/common/system/tray/system_tray_bubble.cc
index 75e6b04a..97b78894 100644
--- a/ash/common/system/tray/system_tray_bubble.cc
+++ b/ash/common/system/tray/system_tray_bubble.cc
@@ -7,13 +7,11 @@
 #include <utility>
 #include <vector>
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/system/tray/system_tray.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
 #include "ash/common/system/tray/system_tray_item.h"
 #include "ash/common/system/tray/tray_bubble_wrapper.h"
 #include "ash/common/system/tray/tray_constants.h"
-#include "ash/common/system/tray/tray_popup_item_container.h"
 #include "ash/common/wm_shell.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -295,12 +293,10 @@
 }
 
 void SystemTrayBubble::UpdateBottomPadding() {
-  if (bubble_type_ == BUBBLE_TYPE_DEFAULT &&
-      MaterialDesignController::IsSystemTrayMenuMaterial()) {
+  if (bubble_type_ == BUBBLE_TYPE_DEFAULT)
     bubble_view_->SetBottomPadding(kDefaultViewBottomPadding);
-  } else {
+  else
     bubble_view_->SetBottomPadding(0);
-  }
 }
 
 void SystemTrayBubble::CreateItemViews(LoginStatus login_status) {
@@ -313,9 +309,7 @@
     login_status = LoginStatus::LOCKED;
   }
 
-  std::vector<TrayPopupItemContainer*> item_containers;
   views::View* focus_view = nullptr;
-  const bool is_default_bubble = bubble_type_ == BUBBLE_TYPE_DEFAULT;
   for (size_t i = 0; i < items_.size(); ++i) {
     views::View* item_view = nullptr;
     switch (bubble_type_) {
@@ -329,27 +323,8 @@
         break;
     }
     if (item_view) {
-      TrayPopupItemContainer* tray_popup_item_container =
-          new TrayPopupItemContainer(
-              item_view,
-              is_default_bubble &&
-                  !MaterialDesignController::IsSystemTrayMenuMaterial());
-      bubble_view_->AddChildView(tray_popup_item_container);
-      item_containers.push_back(tray_popup_item_container);
-      tray_item_view_map_[items_[i]->uma_type()] = tray_popup_item_container;
-    }
-  }
-
-  if (!MaterialDesignController::IsSystemTrayMenuMaterial()) {
-    // For default view, draw bottom border for each item, except the last
-    // 2 items, which are the bottom header row and the one just above it.
-    if (is_default_bubble) {
-      const int last_item_with_border =
-          static_cast<int>(item_containers.size()) - 2;
-      for (int i = 0; i < last_item_with_border; ++i) {
-        item_containers.at(i)->SetBorder(
-            views::CreateSolidSidedBorder(0, 0, 1, 0, kBorderLightColor));
-      }
+      bubble_view_->AddChildView(item_view);
+      tray_item_view_map_[items_[i]->uma_type()] = item_view;
     }
   }
 
diff --git a/ash/common/system/tray/system_tray_unittest.cc b/ash/common/system/tray/system_tray_unittest.cc
index 90b68324..42407b4b 100644
--- a/ash/common/system/tray/system_tray_unittest.cc
+++ b/ash/common/system/tray/system_tray_unittest.cc
@@ -14,7 +14,6 @@
 #include "ash/common/system/tray/system_tray_bubble.h"
 #include "ash/common/system/tray/system_tray_item.h"
 #include "ash/common/system/tray/tray_constants.h"
-#include "ash/common/system/tray/tray_popup_item_container.h"
 #include "ash/common/system/web_notification/web_notification_tray.h"
 #include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
diff --git a/ash/common/system/tray/tray_popup_item_container.cc b/ash/common/system/tray/tray_popup_item_container.cc
deleted file mode 100644
index 3a3d0d5..0000000
--- a/ash/common/system/tray/tray_popup_item_container.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/common/system/tray/tray_popup_item_container.h"
-
-#include "ash/common/system/tray/tray_constants.h"
-#include "ui/gfx/canvas.h"
-#include "ui/views/layout/box_layout.h"
-
-namespace ash {
-
-TrayPopupItemContainer::TrayPopupItemContainer(views::View* view,
-                                               bool change_background)
-    : active_(false), change_background_(change_background) {
-  set_notify_enter_exit_on_child(true);
-  views::BoxLayout* layout =
-      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
-  layout->SetDefaultFlex(1);
-  SetLayoutManager(layout);
-  if (view->layer()) {
-    SetPaintToLayer();
-    layer()->SetFillsBoundsOpaquely(view->layer()->fills_bounds_opaquely());
-  }
-  AddChildView(view);
-  SetVisible(view->visible());
-}
-
-TrayPopupItemContainer::~TrayPopupItemContainer() {}
-
-void TrayPopupItemContainer::SetActive(bool active) {
-  if (!change_background_ || active_ == active)
-    return;
-  active_ = active;
-  SchedulePaint();
-}
-
-void TrayPopupItemContainer::ChildVisibilityChanged(View* child) {
-  if (visible() == child->visible())
-    return;
-  SetVisible(child->visible());
-  PreferredSizeChanged();
-}
-
-void TrayPopupItemContainer::ChildPreferredSizeChanged(View* child) {
-  PreferredSizeChanged();
-}
-
-void TrayPopupItemContainer::OnMouseEntered(const ui::MouseEvent& event) {
-  SetActive(true);
-}
-
-void TrayPopupItemContainer::OnMouseExited(const ui::MouseEvent& event) {
-  SetActive(false);
-}
-
-void TrayPopupItemContainer::OnGestureEvent(ui::GestureEvent* event) {
-  if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
-    SetActive(true);
-  } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL ||
-             event->type() == ui::ET_GESTURE_TAP) {
-    SetActive(false);
-  }
-}
-
-void TrayPopupItemContainer::OnPaintBackground(gfx::Canvas* canvas) {
-  if (child_count() == 0)
-    return;
-
-  views::View* view = child_at(0);
-  if (!view->background()) {
-    canvas->FillRect(gfx::Rect(size()),
-                     (active_) ? kHoverBackgroundColor : kBackgroundColor);
-  }
-}
-
-}  // namespace ash
diff --git a/ash/common/system/tray/tray_popup_item_container.h b/ash/common/system/tray/tray_popup_item_container.h
deleted file mode 100644
index 2fdddb7f..0000000
--- a/ash/common/system/tray/tray_popup_item_container.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_COMMON_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_
-#define ASH_COMMON_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_
-
-#include "base/macros.h"
-#include "ui/views/view.h"
-
-namespace ash {
-
-// A view which can optionally change the background color when a mouse is
-// hovering or a user is interacting via touch.
-class TrayPopupItemContainer : public views::View {
- public:
-  TrayPopupItemContainer(views::View* view, bool change_background);
-
-  ~TrayPopupItemContainer() override;
-
-  bool active() { return active_; }
-
- private:
-  // Sets whether the active background is to be used, and triggers a paint.
-  void SetActive(bool active);
-
-  // views::View:
-  void ChildVisibilityChanged(views::View* child) override;
-  void ChildPreferredSizeChanged(views::View* child) override;
-  void OnMouseEntered(const ui::MouseEvent& event) override;
-  void OnMouseExited(const ui::MouseEvent& event) override;
-  void OnGestureEvent(ui::GestureEvent* event) override;
-  void OnPaintBackground(gfx::Canvas* canvas) override;
-
-  // True if either a mouse is hovering over this view, or if a user has touched
-  // down.
-  bool active_;
-
-  // True if mouse hover and touch feedback can alter the background color of
-  // the container.
-  bool change_background_;
-
-  DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer);
-};
-
-}  // namespace ash
-
-#endif  // ASH_COMMON_SYSTEM_TRAY_TRAY_POPUP_ITEM_CONTAINER_H_
diff --git a/ash/common/system/web_notification/web_notification_tray.cc b/ash/common/system/web_notification/web_notification_tray.cc
index 440d8cb..28f6586 100644
--- a/ash/common/system/web_notification/web_notification_tray.cc
+++ b/ash/common/system/web_notification/web_notification_tray.cc
@@ -4,7 +4,6 @@
 
 #include "ash/common/system/web_notification/web_notification_tray.h"
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/shelf/shelf_constants.h"
 #include "ash/common/shelf/wm_shelf.h"
@@ -64,7 +63,6 @@
 constexpr int kMaximumSmallIconCount = 3;
 
 constexpr gfx::Size kTrayItemInnerIconSize(16, 16);
-constexpr gfx::Size kTrayItemInnerBellIconSizeNonMd(18, 18);
 constexpr gfx::Size kTrayItemOuterSize(26, 26);
 constexpr int kTrayMainAxisInset = 3;
 constexpr int kTrayCrossAxisInset = 0;
@@ -75,14 +73,6 @@
 
 // Flag to disable animation. Only for testing.
 bool disable_animations_for_test = false;
-}
-
-namespace {
-
-const SkColor kWebNotificationColorNoUnread =
-    SkColorSetARGB(128, 255, 255, 255);
-const SkColor kWebNotificationColorWithUnread = SK_ColorWHITE;
-const int kNoUnreadIconSize = 18;
 
 }  // namespace
 
@@ -232,13 +222,12 @@
 class WebNotificationImage : public WebNotificationItem {
  public:
   WebNotificationImage(const gfx::ImageSkia& image,
-                       const gfx::Size& size,
                        gfx::AnimationContainer* container,
                        WebNotificationTray* tray)
       : WebNotificationItem(container, tray) {
     view_ = new views::ImageView();
     view_->SetImage(image);
-    view_->SetImageSize(size);
+    view_->SetImageSize(kTrayItemInnerIconSize);
     AddChildView(view_);
   }
 
@@ -272,7 +261,6 @@
     }
 
     view_->SetText(str);
-    view_->SetEnabledColor(kWebNotificationColorWithUnread);
     SchedulePaint();
   }
 
@@ -295,21 +283,11 @@
   DCHECK(status_area_window_);
   DCHECK(system_tray_);
 
-  if (MaterialDesignController::IsShelfMaterial()) {
-    SetInkDropMode(InkDropMode::ON);
-    gfx::ImageSkia bell_image =
-        CreateVectorIcon(kShelfNotificationsIcon, kShelfIconColor);
-    const gfx::Size bell_icon_size = kTrayItemInnerIconSize;
-    bell_icon_.reset(new WebNotificationImage(
-        bell_image, bell_icon_size, animation_container_.get(), this));
-  } else {
-    gfx::ImageSkia bell_image =
-        CreateVectorIcon(ui::kNotificationsIcon, kNoUnreadIconSize,
-                         kWebNotificationColorNoUnread);
-    const gfx::Size bell_icon_size = kTrayItemInnerBellIconSizeNonMd;
-    bell_icon_.reset(new WebNotificationImage(
-        bell_image, bell_icon_size, animation_container_.get(), this));
-  }
+  SetInkDropMode(InkDropMode::ON);
+  gfx::ImageSkia bell_image =
+      CreateVectorIcon(kShelfNotificationsIcon, kShelfIconColor);
+  bell_icon_.reset(
+      new WebNotificationImage(bell_image, animation_container_.get(), this));
   tray_container()->AddChildView(bell_icon_.get());
 
   counter_.reset(new WebNotificationLabel(animation_container_.get(), this));
@@ -583,9 +561,8 @@
     if (visible_small_icons_.count(notification->id()) != 0)
       continue;
 
-    auto* item =
-        new WebNotificationImage(image.AsImageSkia(), kTrayItemInnerIconSize,
-                                 animation_container_.get(), this);
+    auto* item = new WebNotificationImage(image.AsImageSkia(),
+                                          animation_container_.get(), this);
     visible_small_icons_.insert(std::make_pair(notification->id(), item));
 
     tray_container()->AddChildViewAt(item, 0);
diff --git a/ash/mus/accelerators/accelerator_controller_registrar.cc b/ash/mus/accelerators/accelerator_controller_registrar.cc
index bac5387..bf4acc7 100644
--- a/ash/mus/accelerators/accelerator_controller_registrar.cc
+++ b/ash/mus/accelerators/accelerator_controller_registrar.cc
@@ -142,10 +142,8 @@
       accelerator.modifiers());
   pre_event_matcher->accelerator_phase =
       ui::mojom::AcceleratorPhase::PRE_TARGET;
-  DCHECK(accelerator.type() == ui::ET_KEY_PRESSED ||
-         accelerator.type() == ui::ET_KEY_RELEASED);
   pre_event_matcher->type_matcher->type =
-      accelerator.type() == ui::ET_KEY_PRESSED
+      accelerator.key_state() == ui::Accelerator::KeyState::PRESSED
           ? ui::mojom::EventType::KEY_PRESSED
           : ui::mojom::EventType::KEY_RELEASED;
 
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc
index 40e9b95..444dc70 100644
--- a/base/debug/activity_tracker.cc
+++ b/base/debug/activity_tracker.cc
@@ -23,6 +23,7 @@
 #include "base/process/process_handle.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
 
 namespace base {
@@ -30,18 +31,13 @@
 
 namespace {
 
-// A number that identifies the memory as having been initialized. It's
-// arbitrary but happens to be the first 4 bytes of SHA1(ThreadActivityTracker).
-// A version number is added on so that major structure changes won't try to
-// read an older version (since the cookie won't match).
-const uint32_t kHeaderCookie = 0xC0029B24UL + 2;  // v2
-
 // The minimum depth a stack should support.
 const int kMinStackDepth = 2;
 
 // The amount of memory set aside for holding arbitrary user data (key/value
 // pairs) globally or associated with ActivityData entries.
 const size_t kUserDataSize = 1 << 10;     // 1 KiB
+const size_t kProcessDataSize = 4 << 10;  // 4 KiB
 const size_t kGlobalDataSize = 16 << 10;  // 16 KiB
 const size_t kMaxUserDataNameLength =
     static_cast<size_t>(std::numeric_limits<uint8_t>::max());
@@ -49,6 +45,13 @@
 // A constant used to indicate that module information is changing.
 const uint32_t kModuleInformationChanging = 0x80000000;
 
+// The key used to record process information.
+const char kProcessPhaseDataKey[] = "process-phase";
+
+// An atomically incrementing number, used to check for recreations of objects
+// in the same memory space.
+StaticAtomicSequenceNumber g_next_id;
+
 union ThreadRef {
   int64_t as_id;
 #if defined(OS_WIN)
@@ -64,6 +67,33 @@
 #endif
 };
 
+// Get the next non-zero identifier. It is only unique within a process.
+uint32_t GetNextDataId() {
+  uint32_t id;
+  while ((id = g_next_id.GetNext()) == 0)
+    ;
+  return id;
+}
+
+// Finds and reuses a specific allocation or creates a new one.
+PersistentMemoryAllocator::Reference AllocateFrom(
+    PersistentMemoryAllocator* allocator,
+    uint32_t from_type,
+    size_t size,
+    uint32_t to_type) {
+  PersistentMemoryAllocator::Iterator iter(allocator);
+  PersistentMemoryAllocator::Reference ref;
+  while ((ref = iter.GetNextOfType(from_type)) != 0) {
+    DCHECK_LE(size, allocator->GetAllocSize(ref));
+    // This can fail if a another thread has just taken it. It is assumed that
+    // the memory is cleared during the "free" operation.
+    if (allocator->ChangeType(ref, to_type, from_type, /*clear=*/false))
+      return ref;
+  }
+
+  return allocator->Allocate(size, to_type);
+}
+
 // Determines the previous aligned index.
 size_t RoundDownToAlignment(size_t index, size_t alignment) {
   return index & (0 - alignment);
@@ -76,6 +106,36 @@
 
 }  // namespace
 
+OwningProcess::OwningProcess() {}
+OwningProcess::~OwningProcess() {}
+
+void OwningProcess::Release_Initialize() {
+  uint32_t old_id = data_id.load(std::memory_order_acquire);
+  DCHECK_EQ(0U, old_id);
+  process_id = GetCurrentProcId();
+  create_stamp = Time::Now().ToInternalValue();
+  data_id.store(GetNextDataId(), std::memory_order_release);
+}
+
+void OwningProcess::SetOwningProcessIdForTesting(ProcessId pid, int64_t stamp) {
+  DCHECK_NE(0U, data_id);
+  process_id = pid;
+  create_stamp = stamp;
+}
+
+// static
+bool OwningProcess::GetOwningProcessId(const void* memory,
+                                       ProcessId* out_id,
+                                       int64_t* out_stamp) {
+  const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory);
+  uint32_t id = info->data_id.load(std::memory_order_acquire);
+  if (id == 0)
+    return false;
+
+  *out_id = static_cast<ProcessId>(info->process_id);
+  *out_stamp = info->create_stamp;
+  return id == info->data_id.load(std::memory_order_seq_cst);
+}
 
 // It doesn't matter what is contained in this (though it will be all zeros)
 // as only the address of it is important.
@@ -246,32 +306,31 @@
   return ref_value_;
 }
 
+// These are required because std::atomic is (currently) not a POD type and
+// thus clang requires explicit out-of-line constructors and destructors even
+// when they do nothing.
 ActivityUserData::ValueInfo::ValueInfo() {}
 ActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default;
 ActivityUserData::ValueInfo::~ValueInfo() {}
-
-StaticAtomicSequenceNumber ActivityUserData::next_id_;
+ActivityUserData::MemoryHeader::MemoryHeader() {}
+ActivityUserData::MemoryHeader::~MemoryHeader() {}
+ActivityUserData::FieldHeader::FieldHeader() {}
+ActivityUserData::FieldHeader::~FieldHeader() {}
 
 ActivityUserData::ActivityUserData(void* memory, size_t size)
     : memory_(reinterpret_cast<char*>(memory)),
       available_(RoundDownToAlignment(size, kMemoryAlignment)),
-      id_(reinterpret_cast<std::atomic<uint32_t>*>(memory)) {
+      header_(reinterpret_cast<MemoryHeader*>(memory)) {
   // It's possible that no user data is being stored.
   if (!memory_)
     return;
 
-  DCHECK_LT(kMemoryAlignment, available_);
-  if (id_->load(std::memory_order_relaxed) == 0) {
-    // Generate a new ID and store it in the first 32-bit word of memory_.
-    // |id_| must be non-zero for non-sink instances.
-    uint32_t id;
-    while ((id = next_id_.GetNext()) == 0)
-      ;
-    id_->store(id, std::memory_order_relaxed);
-    DCHECK_NE(0U, id_->load(std::memory_order_relaxed));
-  }
-  memory_ += kMemoryAlignment;
-  available_ -= kMemoryAlignment;
+  static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header");
+  DCHECK_LT(sizeof(MemoryHeader), available_);
+  if (header_->owner.data_id.load(std::memory_order_acquire) == 0)
+    header_->owner.Release_Initialize();
+  memory_ += sizeof(MemoryHeader);
+  available_ -= sizeof(MemoryHeader);
 
   // If there is already data present, load that. This allows the same class
   // to be used for analysis through snapshots.
@@ -280,148 +339,6 @@
 
 ActivityUserData::~ActivityUserData() {}
 
-void ActivityUserData::Set(StringPiece name,
-                           ValueType type,
-                           const void* memory,
-                           size_t size) {
-  DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
-  size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1),
-                  size);
-
-  // It's possible that no user data is being stored.
-  if (!memory_)
-    return;
-
-  // The storage of a name is limited so use that limit during lookup.
-  if (name.length() > kMaxUserDataNameLength)
-    name.set(name.data(), kMaxUserDataNameLength);
-
-  ValueInfo* info;
-  auto existing = values_.find(name);
-  if (existing != values_.end()) {
-    info = &existing->second;
-  } else {
-    // The name size is limited to what can be held in a single byte but
-    // because there are not alignment constraints on strings, it's set tight
-    // against the header. Its extent (the reserved space, even if it's not
-    // all used) is calculated so that, when pressed against the header, the
-    // following field will be aligned properly.
-    size_t name_size = name.length();
-    size_t name_extent =
-        RoundUpToAlignment(sizeof(Header) + name_size, kMemoryAlignment) -
-        sizeof(Header);
-    size_t value_extent = RoundUpToAlignment(size, kMemoryAlignment);
-
-    // The "base size" is the size of the header and (padded) string key. Stop
-    // now if there's not room enough for even this.
-    size_t base_size = sizeof(Header) + name_extent;
-    if (base_size > available_)
-      return;
-
-    // The "full size" is the size for storing the entire value.
-    size_t full_size = std::min(base_size + value_extent, available_);
-
-    // If the value is actually a single byte, see if it can be stuffed at the
-    // end of the name extent rather than wasting kMemoryAlignment bytes.
-    if (size == 1 && name_extent > name_size) {
-      full_size = base_size;
-      --name_extent;
-      --base_size;
-    }
-
-    // Truncate the stored size to the amount of available memory. Stop now if
-    // there's not any room for even part of the value.
-    if (size != 0) {
-      size = std::min(full_size - base_size, size);
-      if (size == 0)
-        return;
-    }
-
-    // Allocate a chunk of memory.
-    Header* header = reinterpret_cast<Header*>(memory_);
-    memory_ += full_size;
-    available_ -= full_size;
-
-    // Datafill the header and name records. Memory must be zeroed. The |type|
-    // is written last, atomically, to release all the other values.
-    DCHECK_EQ(END_OF_VALUES, header->type.load(std::memory_order_relaxed));
-    DCHECK_EQ(0, header->value_size.load(std::memory_order_relaxed));
-    header->name_size = static_cast<uint8_t>(name_size);
-    header->record_size = full_size;
-    char* name_memory = reinterpret_cast<char*>(header) + sizeof(Header);
-    void* value_memory =
-        reinterpret_cast<char*>(header) + sizeof(Header) + name_extent;
-    memcpy(name_memory, name.data(), name_size);
-    header->type.store(type, std::memory_order_release);
-
-    // Create an entry in |values_| so that this field can be found and changed
-    // later on without having to allocate new entries.
-    StringPiece persistent_name(name_memory, name_size);
-    auto inserted =
-        values_.insert(std::make_pair(persistent_name, ValueInfo()));
-    DCHECK(inserted.second);  // True if inserted, false if existed.
-    info = &inserted.first->second;
-    info->name = persistent_name;
-    info->memory = value_memory;
-    info->size_ptr = &header->value_size;
-    info->extent = full_size - sizeof(Header) - name_extent;
-    info->type = type;
-  }
-
-  // Copy the value data to storage. The |size| is written last, atomically, to
-  // release the copied data. Until then, a parallel reader will just ignore
-  // records with a zero size.
-  DCHECK_EQ(type, info->type);
-  size = std::min(size, info->extent);
-  info->size_ptr->store(0, std::memory_order_seq_cst);
-  memcpy(info->memory, memory, size);
-  info->size_ptr->store(size, std::memory_order_release);
-}
-
-void ActivityUserData::SetReference(StringPiece name,
-                                    ValueType type,
-                                    const void* memory,
-                                    size_t size) {
-  ReferenceRecord rec;
-  rec.address = reinterpret_cast<uintptr_t>(memory);
-  rec.size = size;
-  Set(name, type, &rec, sizeof(rec));
-}
-
-void ActivityUserData::ImportExistingData() const {
-  while (available_ > sizeof(Header)) {
-    Header* header = reinterpret_cast<Header*>(memory_);
-    ValueType type =
-        static_cast<ValueType>(header->type.load(std::memory_order_acquire));
-    if (type == END_OF_VALUES)
-      return;
-    if (header->record_size > available_)
-      return;
-
-    size_t value_offset = RoundUpToAlignment(sizeof(Header) + header->name_size,
-                                             kMemoryAlignment);
-    if (header->record_size == value_offset &&
-        header->value_size.load(std::memory_order_relaxed) == 1) {
-      value_offset -= 1;
-    }
-    if (value_offset + header->value_size > header->record_size)
-      return;
-
-    ValueInfo info;
-    info.name = StringPiece(memory_ + sizeof(Header), header->name_size);
-    info.type = type;
-    info.memory = memory_ + value_offset;
-    info.size_ptr = &header->value_size;
-    info.extent = header->record_size - value_offset;
-
-    StringPiece key(info.name);
-    values_.insert(std::make_pair(key, std::move(info)));
-
-    memory_ += header->record_size;
-    available_ -= header->record_size;
-  }
-}
-
 bool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const {
   DCHECK(output_snapshot);
   DCHECK(output_snapshot->empty());
@@ -470,10 +387,167 @@
   return true;
 }
 
-const void* ActivityUserData::GetBaseAddress() {
-  // The |memory_| pointer advances as elements are written but the |id_|
+const void* ActivityUserData::GetBaseAddress() const {
+  // The |memory_| pointer advances as elements are written but the |header_|
   // value is always at the start of the block so just return that.
-  return id_;
+  return header_;
+}
+
+void ActivityUserData::SetOwningProcessIdForTesting(ProcessId pid,
+                                                    int64_t stamp) {
+  if (!header_)
+    return;
+  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
+}
+
+// static
+bool ActivityUserData::GetOwningProcessId(const void* memory,
+                                          ProcessId* out_id,
+                                          int64_t* out_stamp) {
+  const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory);
+  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
+}
+
+void ActivityUserData::Set(StringPiece name,
+                           ValueType type,
+                           const void* memory,
+                           size_t size) {
+  DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length());
+  size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1),
+                  size);
+
+  // It's possible that no user data is being stored.
+  if (!memory_)
+    return;
+
+  // The storage of a name is limited so use that limit during lookup.
+  if (name.length() > kMaxUserDataNameLength)
+    name.set(name.data(), kMaxUserDataNameLength);
+
+  ValueInfo* info;
+  auto existing = values_.find(name);
+  if (existing != values_.end()) {
+    info = &existing->second;
+  } else {
+    // The name size is limited to what can be held in a single byte but
+    // because there are not alignment constraints on strings, it's set tight
+    // against the header. Its extent (the reserved space, even if it's not
+    // all used) is calculated so that, when pressed against the header, the
+    // following field will be aligned properly.
+    size_t name_size = name.length();
+    size_t name_extent =
+        RoundUpToAlignment(sizeof(FieldHeader) + name_size, kMemoryAlignment) -
+        sizeof(FieldHeader);
+    size_t value_extent = RoundUpToAlignment(size, kMemoryAlignment);
+
+    // The "base size" is the size of the header and (padded) string key. Stop
+    // now if there's not room enough for even this.
+    size_t base_size = sizeof(FieldHeader) + name_extent;
+    if (base_size > available_)
+      return;
+
+    // The "full size" is the size for storing the entire value.
+    size_t full_size = std::min(base_size + value_extent, available_);
+
+    // If the value is actually a single byte, see if it can be stuffed at the
+    // end of the name extent rather than wasting kMemoryAlignment bytes.
+    if (size == 1 && name_extent > name_size) {
+      full_size = base_size;
+      --name_extent;
+      --base_size;
+    }
+
+    // Truncate the stored size to the amount of available memory. Stop now if
+    // there's not any room for even part of the value.
+    if (size != 0) {
+      size = std::min(full_size - base_size, size);
+      if (size == 0)
+        return;
+    }
+
+    // Allocate a chunk of memory.
+    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
+    memory_ += full_size;
+    available_ -= full_size;
+
+    // Datafill the header and name records. Memory must be zeroed. The |type|
+    // is written last, atomically, to release all the other values.
+    DCHECK_EQ(END_OF_VALUES, header->type.load(std::memory_order_relaxed));
+    DCHECK_EQ(0, header->value_size.load(std::memory_order_relaxed));
+    header->name_size = static_cast<uint8_t>(name_size);
+    header->record_size = full_size;
+    char* name_memory = reinterpret_cast<char*>(header) + sizeof(FieldHeader);
+    void* value_memory =
+        reinterpret_cast<char*>(header) + sizeof(FieldHeader) + name_extent;
+    memcpy(name_memory, name.data(), name_size);
+    header->type.store(type, std::memory_order_release);
+
+    // Create an entry in |values_| so that this field can be found and changed
+    // later on without having to allocate new entries.
+    StringPiece persistent_name(name_memory, name_size);
+    auto inserted =
+        values_.insert(std::make_pair(persistent_name, ValueInfo()));
+    DCHECK(inserted.second);  // True if inserted, false if existed.
+    info = &inserted.first->second;
+    info->name = persistent_name;
+    info->memory = value_memory;
+    info->size_ptr = &header->value_size;
+    info->extent = full_size - sizeof(FieldHeader) - name_extent;
+    info->type = type;
+  }
+
+  // Copy the value data to storage. The |size| is written last, atomically, to
+  // release the copied data. Until then, a parallel reader will just ignore
+  // records with a zero size.
+  DCHECK_EQ(type, info->type);
+  size = std::min(size, info->extent);
+  info->size_ptr->store(0, std::memory_order_seq_cst);
+  memcpy(info->memory, memory, size);
+  info->size_ptr->store(size, std::memory_order_release);
+}
+
+void ActivityUserData::SetReference(StringPiece name,
+                                    ValueType type,
+                                    const void* memory,
+                                    size_t size) {
+  ReferenceRecord rec;
+  rec.address = reinterpret_cast<uintptr_t>(memory);
+  rec.size = size;
+  Set(name, type, &rec, sizeof(rec));
+}
+
+void ActivityUserData::ImportExistingData() const {
+  while (available_ > sizeof(FieldHeader)) {
+    FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_);
+    ValueType type =
+        static_cast<ValueType>(header->type.load(std::memory_order_acquire));
+    if (type == END_OF_VALUES)
+      return;
+    if (header->record_size > available_)
+      return;
+
+    size_t value_offset = RoundUpToAlignment(
+        sizeof(FieldHeader) + header->name_size, kMemoryAlignment);
+    if (header->record_size == value_offset &&
+        header->value_size.load(std::memory_order_relaxed) == 1) {
+      value_offset -= 1;
+    }
+    if (value_offset + header->value_size > header->record_size)
+      return;
+
+    ValueInfo info;
+    info.name = StringPiece(memory_ + sizeof(FieldHeader), header->name_size);
+    info.type = type;
+    info.memory = memory_ + value_offset;
+    info.size_ptr = &header->value_size;
+    info.extent = header->record_size - value_offset;
+
+    StringPiece key(info.name);
+    values_.insert(std::make_pair(key, std::move(info)));
+
+    memory_ += header->record_size;
+    available_ -= header->record_size;
+  }
 }
 
 // This information is kept for every thread that is tracked. It is filled
@@ -485,27 +559,15 @@
       GlobalActivityTracker::kTypeIdActivityTracker;
 
   // Expected size for 32/64-bit check.
-  static constexpr size_t kExpectedInstanceSize = 80;
+  static constexpr size_t kExpectedInstanceSize =
+      OwningProcess::kExpectedInstanceSize + 72;
 
-  // This unique number indicates a valid initialization of the memory.
-  std::atomic<uint32_t> cookie;
+  // This information uniquely identifies a process.
+  OwningProcess owner;
 
-  // The number of Activity slots (spaces that can hold an Activity) that
-  // immediately follow this structure in memory.
-  uint32_t stack_slots;
-
-  // The process-id and thread-id (thread_ref.as_id) to which this data belongs.
-  // These identifiers are not guaranteed to mean anything but are unique, in
-  // combination, among all active trackers. It would be nice to always have
-  // the process_id be a 64-bit value but the necessity of having it atomic
-  // (for the memory barriers it provides) limits it to the natural word size
-  // of the machine.
-#ifdef ARCH_CPU_64_BITS
-  std::atomic<int64_t> process_id;
-#else
-  std::atomic<int32_t> process_id;
-  int32_t process_id_padding;
-#endif
+  // The thread-id (thread_ref.as_id) to which this data belongs. This number
+  // is not guaranteed to mean anything but combined with the process-id from
+  // OwningProcess is unique among all active trackers.
   ThreadRef thread_ref;
 
   // The start-time and start-ticks when the data was created. Each activity
@@ -514,6 +576,13 @@
   int64_t start_time;
   int64_t start_ticks;
 
+  // The number of Activity slots (spaces that can hold an Activity) that
+  // immediately follow this structure in memory.
+  uint32_t stack_slots;
+
+  // Some padding to keep everything 64-bit aligned.
+  uint32_t padding;
+
   // The current depth of the stack. This may be greater than the number of
   // slots. If the depth exceeds the number of slots, the newest entries
   // won't be recorded.
@@ -596,9 +665,10 @@
                 "ActivityData.data is not 64-bit aligned");
 
   // Provided memory should either be completely initialized or all zeros.
-  if (header_->cookie.load(std::memory_order_relaxed) == 0) {
+  if (header_->owner.data_id.load(std::memory_order_relaxed) == 0) {
     // This is a new file. Double-check other fields and then initialize.
-    DCHECK_EQ(0, header_->process_id.load(std::memory_order_relaxed));
+    DCHECK_EQ(0, header_->owner.process_id);
+    DCHECK_EQ(0, header_->owner.create_stamp);
     DCHECK_EQ(0, header_->thread_ref.as_id);
     DCHECK_EQ(0, header_->start_time);
     DCHECK_EQ(0, header_->start_ticks);
@@ -616,7 +686,6 @@
     header_->thread_ref.as_handle =
         PlatformThread::CurrentHandle().platform_handle();
 #endif
-    header_->process_id.store(GetCurrentProcId(), std::memory_order_relaxed);
 
     header_->start_time = base::Time::Now().ToInternalValue();
     header_->start_ticks = base::TimeTicks::Now().ToInternalValue();
@@ -626,7 +695,7 @@
 
     // This is done last so as to guarantee that everything above is "released"
     // by the time this value gets written.
-    header_->cookie.store(kHeaderCookie, std::memory_order_release);
+    header_->owner.Release_Initialize();
 
     valid_ = true;
     DCHECK(IsValid());
@@ -771,11 +840,9 @@
 }
 
 bool ThreadActivityTracker::IsValid() const {
-  if (header_->cookie.load(std::memory_order_acquire) != kHeaderCookie ||
-      header_->process_id.load(std::memory_order_relaxed) == 0 ||
-      header_->thread_ref.as_id == 0 ||
-      header_->start_time == 0 ||
-      header_->start_ticks == 0 ||
+  if (header_->owner.data_id.load(std::memory_order_acquire) == 0 ||
+      header_->owner.process_id == 0 || header_->thread_ref.as_id == 0 ||
+      header_->start_time == 0 || header_->start_ticks == 0 ||
       header_->stack_slots != stack_slots_ ||
       header_->thread_name[sizeof(header_->thread_name) - 1] != '\0') {
     return false;
@@ -806,12 +873,12 @@
   output_snapshot->activity_stack.reserve(stack_slots_);
 
   for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
-    // Remember the process and thread IDs to ensure they aren't replaced
-    // during the snapshot operation. Use "acquire" to ensure that all the
-    // non-atomic fields of the structure are valid (at least at the current
-    // moment in time).
-    const int64_t starting_process_id =
-        header_->process_id.load(std::memory_order_acquire);
+    // Remember the data IDs to ensure nothing is replaced during the snapshot
+    // operation. Use "acquire" so that all the non-atomic fields of the
+    // structure are valid (at least at the current moment in time).
+    const uint32_t starting_id =
+        header_->owner.data_id.load(std::memory_order_acquire);
+    const int64_t starting_process_id = header_->owner.process_id;
     const int64_t starting_thread_id = header_->thread_ref.as_id;
 
     // Write a non-zero value to |stack_unchanged| so it's possible to detect
@@ -841,19 +908,11 @@
 
     // TODO(bcwhite): Snapshot other things here.
 
-    // Get the general thread information. Loading of "process_id" is guaranteed
-    // to be last so that it's possible to detect below if any content has
-    // changed while reading it. It's technically possible for a thread to end,
-    // have its data cleared, a new thread get created with the same IDs, and
-    // it perform an action which starts tracking all in the time since the
-    // ID reads above but the chance is so unlikely that it's not worth the
-    // effort and complexity of protecting against it (perhaps with an
-    // "unchanged" field like is done for the stack).
+    // Get the general thread information.
     output_snapshot->thread_name =
         std::string(header_->thread_name, sizeof(header_->thread_name) - 1);
     output_snapshot->thread_id = header_->thread_ref.as_id;
-    output_snapshot->process_id =
-        header_->process_id.load(std::memory_order_seq_cst);
+    output_snapshot->process_id = header_->owner.process_id;
 
     // All characters of the thread-name buffer were copied so as to not break
     // if the trailing NUL were missing. Now limit the length if the actual
@@ -861,9 +920,10 @@
     output_snapshot->thread_name.resize(
         strlen(output_snapshot->thread_name.c_str()));
 
-    // If the process or thread ID has changed then the tracker has exited and
-    // the memory reused by a new one. Try again.
-    if (output_snapshot->process_id != starting_process_id ||
+    // If the data ID has changed then the tracker has exited and the memory
+    // reused by a new one. Try again.
+    if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id ||
+        output_snapshot->process_id != starting_process_id ||
         output_snapshot->thread_id != starting_thread_id) {
       continue;
     }
@@ -892,6 +952,23 @@
   return false;
 }
 
+const void* ThreadActivityTracker::GetBaseAddress() {
+  return header_;
+}
+
+void ThreadActivityTracker::SetOwningProcessIdForTesting(ProcessId pid,
+                                                         int64_t stamp) {
+  header_->owner.SetOwningProcessIdForTesting(pid, stamp);
+}
+
+// static
+bool ThreadActivityTracker::GetOwningProcessId(const void* memory,
+                                               ProcessId* out_id,
+                                               int64_t* out_stamp) {
+  const Header* header = reinterpret_cast<const Header*>(memory);
+  return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp);
+}
+
 // static
 size_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) {
   return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header);
@@ -979,6 +1056,9 @@
   pickle_size = pickler.size();
   changes.store(0, std::memory_order_relaxed);
 
+  // Initialize the owner info.
+  owner.Release_Initialize();
+
   // Now set those fields that can change.
   return UpdateFrom(info);
 }
@@ -1053,15 +1133,16 @@
   return *user_data_;
 }
 
-GlobalActivityTracker::GlobalUserData::GlobalUserData(void* memory, size_t size)
+GlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory,
+                                                              size_t size)
     : ActivityUserData(memory, size) {}
 
-GlobalActivityTracker::GlobalUserData::~GlobalUserData() {}
+GlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() {}
 
-void GlobalActivityTracker::GlobalUserData::Set(StringPiece name,
-                                                ValueType type,
-                                                const void* memory,
-                                                size_t size) {
+void GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name,
+                                                    ValueType type,
+                                                    const void* memory,
+                                                    size_t size) {
   AutoLock lock(data_lock_);
   ActivityUserData::Set(name, type, memory, size);
 }
@@ -1186,6 +1267,174 @@
     delete tracker;
 }
 
+void GlobalActivityTracker::SetBackgroundTaskRunner(
+    const scoped_refptr<TaskRunner>& runner) {
+  AutoLock lock(global_tracker_lock_);
+  background_task_runner_ = runner;
+}
+
+void GlobalActivityTracker::SetProcessExitCallback(
+    ProcessExitCallback callback) {
+  AutoLock lock(global_tracker_lock_);
+  process_exit_callback_ = callback;
+}
+
+void GlobalActivityTracker::RecordProcessLaunch(
+    ProcessId process_id,
+    const FilePath::StringType& cmd) {
+  DCHECK_NE(GetCurrentProcId(), process_id);
+
+  base::AutoLock lock(global_tracker_lock_);
+  if (base::ContainsKey(known_processes_, process_id)) {
+    // TODO(bcwhite): Measure this in UMA.
+    NOTREACHED() << "Process #" << process_id
+                 << " was previously recorded as \"launched\""
+                 << " with no corresponding exit.";
+    known_processes_.erase(process_id);
+  }
+
+#if defined(OS_WIN)
+  known_processes_.insert(std::make_pair(process_id, UTF16ToUTF8(cmd)));
+#else
+  known_processes_.insert(std::make_pair(process_id, cmd));
+#endif
+}
+
+void GlobalActivityTracker::RecordProcessLaunch(
+    ProcessId process_id,
+    const FilePath::StringType& exe,
+    const FilePath::StringType& args) {
+  if (exe.find(FILE_PATH_LITERAL(" "))) {
+    RecordProcessLaunch(process_id,
+                        FilePath::StringType(FILE_PATH_LITERAL("\"")) + exe +
+                            FILE_PATH_LITERAL("\" ") + args);
+  } else {
+    RecordProcessLaunch(process_id, exe + FILE_PATH_LITERAL(' ') + args);
+  }
+}
+
+void GlobalActivityTracker::RecordProcessExit(ProcessId process_id,
+                                              int exit_code) {
+  DCHECK_NE(GetCurrentProcId(), process_id);
+
+  scoped_refptr<TaskRunner> task_runner;
+  std::string command_line;
+  {
+    base::AutoLock lock(global_tracker_lock_);
+    task_runner = background_task_runner_;
+    auto found = known_processes_.find(process_id);
+    if (found != known_processes_.end()) {
+      command_line = std::move(found->second);
+      known_processes_.erase(found);
+    } else {
+      DLOG(ERROR) << "Recording exit of unknown process #" << process_id;
+    }
+  }
+
+  // Use the current time to differentiate the process that just exited
+  // from any that might be created in the future with the same ID.
+  int64_t now_stamp = Time::Now().ToInternalValue();
+
+  // The persistent allocator is thread-safe so run the iteration and
+  // adjustments on a worker thread if one was provided.
+  if (task_runner && !task_runner->RunsTasksOnCurrentThread()) {
+    task_runner->PostTask(
+        FROM_HERE,
+        Bind(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this),
+             process_id, now_stamp, exit_code, Passed(&command_line)));
+    return;
+  }
+
+  CleanupAfterProcess(process_id, now_stamp, exit_code,
+                      std::move(command_line));
+}
+
+void GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) {
+  process_data().SetInt(kProcessPhaseDataKey, phase);
+}
+
+void GlobalActivityTracker::CleanupAfterProcess(ProcessId process_id,
+                                                int64_t exit_stamp,
+                                                int exit_code,
+                                                std::string&& command_line) {
+  // The process may not have exited cleanly so its necessary to go through
+  // all the data structures it may have allocated in the persistent memory
+  // segment and mark them as "released". This will allow them to be reused
+  // later on.
+
+  PersistentMemoryAllocator::Iterator iter(allocator_.get());
+  PersistentMemoryAllocator::Reference ref;
+
+  ProcessExitCallback process_exit_callback;
+  {
+    AutoLock lock(global_tracker_lock_);
+    process_exit_callback = process_exit_callback_;
+  }
+  if (process_exit_callback) {
+    // Find the processes user-data record so the process phase can be passed
+    // to the callback.
+    ActivityUserData::Snapshot process_data_snapshot;
+    while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) {
+      const void* memory = allocator_->GetAsArray<char>(
+          ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny);
+      ProcessId found_id;
+      int64_t create_stamp;
+      if (ActivityUserData::GetOwningProcessId(memory, &found_id,
+                                               &create_stamp)) {
+        if (found_id == process_id && create_stamp < exit_stamp) {
+          const ActivityUserData process_data(const_cast<void*>(memory),
+                                              allocator_->GetAllocSize(ref));
+          process_data.CreateSnapshot(&process_data_snapshot);
+          break;  // No need to look for any others.
+        }
+      }
+    }
+    iter.Reset();  // So it starts anew when used below.
+
+    // Record the process's phase at exit so callback doesn't need to go
+    // searching based on a private key value.
+    ProcessPhase exit_phase = PROCESS_PHASE_UNKNOWN;
+    auto phase = process_data_snapshot.find(kProcessPhaseDataKey);
+    if (phase != process_data_snapshot.end())
+      exit_phase = static_cast<ProcessPhase>(phase->second.GetInt());
+
+    // Perform the callback.
+    process_exit_callback.Run(process_id, exit_stamp, exit_code, exit_phase,
+                              std::move(command_line),
+                              std::move(process_data_snapshot));
+  }
+
+  // Find all allocations associated with the exited process and free them.
+  uint32_t type;
+  while ((ref = iter.GetNext(&type)) != 0) {
+    switch (type) {
+      case kTypeIdActivityTracker:
+      case kTypeIdUserDataRecord:
+      case kTypeIdProcessDataRecord:
+      case ModuleInfoRecord::kPersistentTypeId: {
+        const void* memory = allocator_->GetAsArray<char>(
+            ref, type, PersistentMemoryAllocator::kSizeAny);
+        ProcessId found_id;
+        int64_t create_stamp;
+
+        // By convention, the OwningProcess structure is always the first
+        // field of the structure so there's no need to handle all the
+        // cases separately.
+        if (OwningProcess::GetOwningProcessId(memory, &found_id,
+                                              &create_stamp)) {
+          // Only change the type to be "free" if the process ID matches and
+          // the creation time is before the exit time (so PID re-use doesn't
+          // cause the erasure of something that is in-use). Memory is cleared
+          // here, rather than when it's needed, so as to limit the impact at
+          // that critical time.
+          if (found_id == process_id && create_stamp < exit_stamp)
+            allocator_->ChangeType(ref, ~type, type, /*clear=*/true);
+        }
+      } break;
+    }
+  }
+}
+
 void GlobalActivityTracker::RecordLogMessage(StringPiece message) {
   // Allocate at least one extra byte so the string is NUL terminated. All
   // memory returned by the allocator is guaranteed to be zeroed.
@@ -1249,12 +1498,20 @@
                            kTypeIdUserDataRecordFree,
                            kUserDataSize,
                            kCachedUserDataMemories,
-                           /*make_iterable=*/false),
+                           /*make_iterable=*/true),
+      process_data_(allocator_->GetAsArray<char>(
+                        AllocateFrom(allocator_.get(),
+                                     kTypeIdProcessDataRecordFree,
+                                     kProcessDataSize,
+                                     kTypeIdProcessDataRecord),
+                        kTypeIdProcessDataRecord,
+                        kProcessDataSize),
+                    kProcessDataSize),
       global_data_(
           allocator_->GetAsArray<char>(
               allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord),
               kTypeIdGlobalDataRecord,
-              PersistentMemoryAllocator::kSizeAny),
+              kGlobalDataSize),
           kGlobalDataSize) {
   // Ensure the passed memory is valid and empty (iterator finds nothing).
   uint32_t type;
@@ -1264,10 +1521,15 @@
   DCHECK(!g_tracker_);
   subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this));
 
-  // The global records must be iterable in order to be found by an analyzer.
+  // The data records must be iterable in order to be found by an analyzer.
+  allocator_->MakeIterable(allocator_->GetAsReference(
+      process_data_.GetBaseAddress(), kTypeIdProcessDataRecord));
   allocator_->MakeIterable(allocator_->GetAsReference(
       global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord));
 
+  // Note that this process has launched.
+  SetProcessPhase(PROCESS_LAUNCHED);
+
   // Fetch and record all activated field trials.
   FieldTrial::ActiveGroups active_groups;
   FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h
index 719a318..922528f 100644
--- a/base/debug/activity_tracker.h
+++ b/base/debug/activity_tracker.h
@@ -23,12 +23,15 @@
 
 #include "base/atomicops.h"
 #include "base/base_export.h"
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/gtest_prod_util.h"
 #include "base/location.h"
 #include "base/metrics/persistent_memory_allocator.h"
+#include "base/process/process_handle.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_runner.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_checker.h"
 #include "base/threading/thread_local_storage.h"
@@ -41,7 +44,6 @@
 class Lock;
 class PlatformThreadHandle;
 class Process;
-class StaticAtomicSequenceNumber;
 class WaitableEvent;
 
 namespace debug {
@@ -56,6 +58,39 @@
   kActivityCallStackSize = 10,
 };
 
+// A class for keeping all information needed to verify that a structure is
+// associated with a given process.
+struct OwningProcess {
+  OwningProcess();
+  ~OwningProcess();
+
+  // Initializes structure with the current process id and the current time.
+  // These can uniquely identify a process. A unique non-zero data_id will be
+  // set making it possible to tell using atomic reads if the data has changed.
+  void Release_Initialize();
+
+  // Explicitly sets the process ID.
+  void SetOwningProcessIdForTesting(ProcessId pid, int64_t stamp);
+
+  // Gets the associated process ID, in native form, and the creation timestamp
+  // from memory without loading the entire structure for analysis. This will
+  // return false if no valid process ID is available.
+  static bool GetOwningProcessId(const void* memory,
+                                 ProcessId* out_id,
+                                 int64_t* out_stamp);
+
+  // SHA1(base::debug::OwningProcess): Increment this if structure changes!
+  static constexpr uint32_t kPersistentTypeId = 0xB1179672 + 1;
+
+  // Expected size for 32/64-bit check by PersistentMemoryAllocator.
+  static constexpr size_t kExpectedInstanceSize = 24;
+
+  std::atomic<uint32_t> data_id;
+  uint32_t padding;
+  int64_t process_id;
+  int64_t create_stamp;
+};
+
 // The data associated with an activity is dependent upon the activity type.
 // This union defines all of the various fields. All fields must be explicitly
 // sized types to ensure no interoperability problems between 32-bit and
@@ -293,7 +328,9 @@
 // This class manages arbitrary user data that can be associated with activities
 // done by a thread by supporting key/value pairs of any type. This can provide
 // additional information during debugging. It is also used to store arbitrary
-// global data. All updates must be done from the same thread.
+// global data. All updates must be done from the same thread though other
+// threads can read it concurrently if they create new objects using the same
+// memory.
 class BASE_EXPORT ActivityUserData {
  public:
   // List of known value type. REFERENCE types must immediately follow the non-
@@ -355,7 +392,7 @@
   // contents have been overwritten by another thread. The return value is
   // always non-zero unless it's actually just a data "sink".
   uint32_t id() const {
-    return memory_ ? id_->load(std::memory_order_relaxed) : 0;
+    return header_ ? header_->owner.data_id.load(std::memory_order_relaxed) : 0;
   }
 
   // Writes a |value| (as part of a key/value pair) that will be included with
@@ -409,7 +446,17 @@
   bool CreateSnapshot(Snapshot* output_snapshot) const;
 
   // Gets the base memory address used for storing data.
-  const void* GetBaseAddress();
+  const void* GetBaseAddress() const;
+
+  // Explicitly sets the process ID.
+  void SetOwningProcessIdForTesting(ProcessId pid, int64_t stamp);
+
+  // Gets the associated process ID, in native form, and the creation timestamp
+  // from tracker memory without loading the entire structure for analysis. This
+  // will return false if no valid process ID is available.
+  static bool GetOwningProcessId(const void* memory,
+                                 ProcessId* out_id,
+                                 int64_t* out_stamp);
 
  protected:
   virtual void Set(StringPiece name,
@@ -422,20 +469,31 @@
 
   enum : size_t { kMemoryAlignment = sizeof(uint64_t) };
 
-  // A structure used to reference data held outside of persistent memory.
-  struct ReferenceRecord {
-    uint64_t address;
-    uint64_t size;
+  // A structure that defines the structure header in memory.
+  struct MemoryHeader {
+    MemoryHeader();
+    ~MemoryHeader();
+
+    OwningProcess owner;  // Information about the creating process.
   };
 
   // Header to a key/value record held in persistent memory.
-  struct Header {
+  struct FieldHeader {
+    FieldHeader();
+    ~FieldHeader();
+
     std::atomic<uint8_t> type;         // Encoded ValueType
     uint8_t name_size;                 // Length of "name" key.
     std::atomic<uint16_t> value_size;  // Actual size of of the stored value.
     uint16_t record_size;              // Total storage of name, value, header.
   };
 
+  // A structure used to reference data held outside of persistent memory.
+  struct ReferenceRecord {
+    uint64_t address;
+    uint64_t size;
+  };
+
   // This record is used to hold known value is a map so that they can be
   // found and overwritten later.
   struct ValueInfo {
@@ -470,12 +528,8 @@
   mutable char* memory_;
   mutable size_t available_;
 
-  // A pointer to the unique ID for this instance.
-  std::atomic<uint32_t>* const id_;
-
-  // This ID is used to create unique indentifiers for user data so that it's
-  // possible to tell if the information has been overwritten.
-  static StaticAtomicSequenceNumber next_id_;
+  // A pointer to the memory header for this instance.
+  MemoryHeader* const header_;
 
   DISALLOW_COPY_AND_ASSIGN(ActivityUserData);
 };
@@ -618,6 +672,19 @@
   // implementation does not support concurrent snapshot operations.
   bool CreateSnapshot(Snapshot* output_snapshot) const;
 
+  // Gets the base memory address used for storing data.
+  const void* GetBaseAddress();
+
+  // Explicitly sets the process ID.
+  void SetOwningProcessIdForTesting(ProcessId pid, int64_t stamp);
+
+  // Gets the associated process ID, in native form, and the creation timestamp
+  // from tracker memory without loading the entire structure for analysis. This
+  // will return false if no valid process ID is available.
+  static bool GetOwningProcessId(const void* memory,
+                                 ProcessId* out_id,
+                                 int64_t* out_stamp);
+
   // Calculates the memory size required for a given stack depth, including
   // the internal header structure for the stack.
   static size_t SizeForStackDepth(int stack_depth);
@@ -649,15 +716,45 @@
   // will be safely ignored. These are public so that an external process
   // can recognize records of this type within an allocator.
   enum : uint32_t {
-    kTypeIdActivityTracker = 0x5D7381AF + 3,   // SHA1(ActivityTracker) v3
-    kTypeIdUserDataRecord = 0x615EDDD7 + 2,    // SHA1(UserDataRecord) v2
+    kTypeIdActivityTracker = 0x5D7381AF + 4,   // SHA1(ActivityTracker) v4
+    kTypeIdUserDataRecord = 0x615EDDD7 + 3,    // SHA1(UserDataRecord) v3
     kTypeIdGlobalLogMessage = 0x4CF434F9 + 1,  // SHA1(GlobalLogMessage) v1
-    kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 1000,
+    kTypeIdProcessDataRecord = kTypeIdUserDataRecord + 0x100,
+    kTypeIdGlobalDataRecord = kTypeIdUserDataRecord + 0x200,
 
     kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker,
     kTypeIdUserDataRecordFree = ~kTypeIdUserDataRecord,
+    kTypeIdProcessDataRecordFree = ~kTypeIdProcessDataRecord,
   };
 
+  // An enumeration of common process life stages. All entries are given an
+  // explicit number so they are known and remain constant; this allows for
+  // cross-version analysis either locally or on a server.
+  enum ProcessPhase : int {
+    // The phases are generic and may have meaning to the tracker.
+    PROCESS_PHASE_UNKNOWN = 0,
+    PROCESS_LAUNCHED = 1,
+    PROCESS_LAUNCH_FAILED = 2,
+    PROCESS_EXITED_CLEANLY = 10,
+    PROCESS_EXITED_WITH_CODE = 11,
+
+    // Add here whatever is useful for analysis.
+    PROCESS_SHUTDOWN_STARTED = 100,
+    PROCESS_MAIN_LOOP_STARTED = 101,
+  };
+
+  // A callback made when a process exits to allow immediate analysis of its
+  // data. Note that the system may reuse the |process_id| so when fetching
+  // records it's important to ensure that what is returned was created before
+  // the |exit_stamp|. Movement of |process_data| information is allowed.
+  using ProcessExitCallback =
+      Callback<void(int64_t process_id,
+                    int64_t exit_stamp,
+                    int exit_code,
+                    ProcessPhase exit_phase,
+                    std::string&& command_line,
+                    ActivityUserData::Snapshot&& process_data)>;
+
   // This structure contains information about a loaded module, as shown to
   // users of the tracker.
   struct BASE_EXPORT ModuleInfo {
@@ -789,6 +886,49 @@
   // Releases the activity-tracker for the current thread (for testing only).
   void ReleaseTrackerForCurrentThreadForTesting();
 
+  // Sets a task-runner that can be used for background work.
+  void SetBackgroundTaskRunner(const scoped_refptr<TaskRunner>& runner);
+
+  // Sets an optional callback to be called when a process exits.
+  void SetProcessExitCallback(ProcessExitCallback callback);
+
+  // Manages process lifetimes. These are called by the process that launched
+  // and reaped the subprocess, not the subprocess itself. If it is expensive
+  // to generate the parameters, Get() the global tracker and call these
+  // conditionally rather than using the static versions.
+  void RecordProcessLaunch(ProcessId process_id,
+                           const FilePath::StringType& cmd);
+  void RecordProcessLaunch(ProcessId process_id,
+                           const FilePath::StringType& exe,
+                           const FilePath::StringType& args);
+  void RecordProcessExit(ProcessId process_id, int exit_code);
+  static void RecordProcessLaunchIfEnabled(ProcessId process_id,
+                                           const FilePath::StringType& cmd) {
+    GlobalActivityTracker* tracker = Get();
+    if (tracker)
+      tracker->RecordProcessLaunch(process_id, cmd);
+  }
+  static void RecordProcessLaunchIfEnabled(ProcessId process_id,
+                                           const FilePath::StringType& exe,
+                                           const FilePath::StringType& args) {
+    GlobalActivityTracker* tracker = Get();
+    if (tracker)
+      tracker->RecordProcessLaunch(process_id, exe, args);
+  }
+  static void RecordProcessExitIfEnabled(ProcessId process_id, int exit_code) {
+    GlobalActivityTracker* tracker = Get();
+    if (tracker)
+      tracker->RecordProcessExit(process_id, exit_code);
+  }
+  // Sets the "phase" of the current process, useful for knowing what it was
+  // doing when it last reported.
+  void SetProcessPhase(ProcessPhase phase);
+  static void SetProcessPhaseIfEnabled(ProcessPhase phase) {
+    GlobalActivityTracker* tracker = Get();
+    if (tracker)
+      tracker->SetProcessPhase(phase);
+  }
+
   // Records a log message. The current implementation does NOT recycle these
   // only store critical messages such as FATAL ones.
   void RecordLogMessage(StringPiece message);
@@ -818,7 +958,12 @@
       tracker->RecordFieldTrial(trial_name, group_name);
   }
 
+  // Accesses the process data record for storing arbitrary key/value pairs.
+  // Updates to this are thread-safe.
+  ActivityUserData& process_data() { return process_data_; }
+
   // Accesses the global data record for storing arbitrary key/value pairs.
+  // Updates to this are thread-safe.
   ActivityUserData& global_data() { return global_data_; }
 
  private:
@@ -837,10 +982,10 @@
   // A wrapper around ActivityUserData that is thread-safe and thus can be used
   // in the global scope without the requirement of being called from only one
   // thread.
-  class GlobalUserData : public ActivityUserData {
+  class ThreadSafeUserData : public ActivityUserData {
    public:
-    GlobalUserData(void* memory, size_t size);
-    ~GlobalUserData() override;
+    ThreadSafeUserData(void* memory, size_t size);
+    ~ThreadSafeUserData() override;
 
    private:
     void Set(StringPiece name,
@@ -850,7 +995,7 @@
 
     Lock data_lock_;
 
-    DISALLOW_COPY_AND_ASSIGN(GlobalUserData);
+    DISALLOW_COPY_AND_ASSIGN(ThreadSafeUserData);
   };
 
   // State of a module as stored in persistent memory. This supports a single
@@ -862,7 +1007,8 @@
     static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1;
 
     // Expected size for 32/64-bit check by PersistentMemoryAllocator.
-    static constexpr size_t kExpectedInstanceSize = 56;
+    static constexpr size_t kExpectedInstanceSize =
+        OwningProcess::kExpectedInstanceSize + 56;
 
     // The atomic unfortunately makes this a "complex" class on some compilers
     // and thus requires an out-of-line constructor & destructor even though
@@ -870,6 +1016,7 @@
     ModuleInfoRecord();
     ~ModuleInfoRecord();
 
+    OwningProcess owner;            // The process that created this record.
     uint64_t address;               // The base address of the module.
     uint64_t load_time;             // Time of last load/unload.
     uint64_t size;                  // The size of the module in bytes.
@@ -933,6 +1080,12 @@
   // be tracked. |value| is a pointer to a ManagedActivityTracker.
   static void OnTLSDestroy(void* value);
 
+  // Does process-exit work. This can be run on any thread.
+  void CleanupAfterProcess(ProcessId process_id,
+                           int64_t exit_stamp,
+                           int exit_code,
+                           std::string&& command_line);
+
   // The persistent-memory allocator from which the memory for all trackers
   // is taken.
   std::unique_ptr<PersistentMemoryAllocator> allocator_;
@@ -955,9 +1108,9 @@
   ActivityTrackerMemoryAllocator user_data_allocator_;
   base::Lock user_data_allocator_lock_;
 
-  // An object for holding global arbitrary key value pairs. Values must always
-  // be written from the main UI thread.
-  GlobalUserData global_data_;
+  // An object for holding arbitrary key value pairs with thread-safe access.
+  ThreadSafeUserData process_data_;
+  ThreadSafeUserData global_data_;
 
   // A map of global module information, keyed by module path.
   std::map<const std::string, ModuleInfoRecord*> modules_;
@@ -966,6 +1119,21 @@
   // The active global activity tracker.
   static subtle::AtomicWord g_tracker_;
 
+  // A lock that is used to protect access to the following fields.
+  base::Lock global_tracker_lock_;
+
+  // The collection of processes being tracked and their command-lines.
+  std::map<int64_t, std::string> known_processes_;
+
+  // A task-runner that can be used for doing background processing.
+  scoped_refptr<TaskRunner> background_task_runner_;
+
+  // A callback performed when a subprocess exits, including its exit-code
+  // and the phase it was in when that occurred. This will be called via
+  // the |background_task_runner_| if one is set or whatever thread reaped
+  // the process otherwise.
+  ProcessExitCallback process_exit_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker);
 };
 
diff --git a/base/debug/activity_tracker_unittest.cc b/base/debug/activity_tracker_unittest.cc
index aced4fb3..e9934d1 100644
--- a/base/debug/activity_tracker_unittest.cc
+++ b/base/debug/activity_tracker_unittest.cc
@@ -84,45 +84,73 @@
     return GlobalActivityTracker::Get()->user_data_allocator_.cache_used();
   }
 
+  void HandleProcessExit(int64_t id,
+                         int64_t stamp,
+                         int code,
+                         GlobalActivityTracker::ProcessPhase phase,
+                         std::string&& command,
+                         ActivityUserData::Snapshot&& data) {
+    exit_id = id;
+    exit_stamp = stamp;
+    exit_code = code;
+    exit_phase = phase;
+    exit_command = std::move(command);
+    exit_data = std::move(data);
+  }
+
   static void DoNothing() {}
+
+  int64_t exit_id = 0;
+  int64_t exit_stamp;
+  int exit_code;
+  GlobalActivityTracker::ProcessPhase exit_phase;
+  std::string exit_command;
+  ActivityUserData::Snapshot exit_data;
 };
 
 TEST_F(ActivityTrackerTest, UserDataTest) {
   char buffer[256];
   memset(buffer, 0, sizeof(buffer));
   ActivityUserData data(buffer, sizeof(buffer));
-  const size_t space = sizeof(buffer) - 8;
+  size_t space = sizeof(buffer) - sizeof(ActivityUserData::MemoryHeader);
   ASSERT_EQ(space, data.available_);
 
   data.SetInt("foo", 1);
-  ASSERT_EQ(space - 24, data.available_);
+  space -= 24;
+  ASSERT_EQ(space, data.available_);
 
   data.SetUint("b", 1U);  // Small names fit beside header in a word.
-  ASSERT_EQ(space - 24 - 16, data.available_);
+  space -= 16;
+  ASSERT_EQ(space, data.available_);
 
   data.Set("c", buffer, 10);
-  ASSERT_EQ(space - 24 - 16 - 24, data.available_);
+  space -= 24;
+  ASSERT_EQ(space, data.available_);
 
   data.SetString("dear john", "it's been fun");
-  ASSERT_EQ(space - 24 - 16 - 24 - 32, data.available_);
+  space -= 32;
+  ASSERT_EQ(space, data.available_);
 
   data.Set("c", buffer, 20);
-  ASSERT_EQ(space - 24 - 16 - 24 - 32, data.available_);
+  ASSERT_EQ(space, data.available_);
 
   data.SetString("dear john", "but we're done together");
-  ASSERT_EQ(space - 24 - 16 - 24 - 32, data.available_);
+  ASSERT_EQ(space, data.available_);
 
   data.SetString("dear john", "bye");
-  ASSERT_EQ(space - 24 - 16 - 24 - 32, data.available_);
+  ASSERT_EQ(space, data.available_);
 
   data.SetChar("d", 'x');
-  ASSERT_EQ(space - 24 - 16 - 24 - 32 - 8, data.available_);
+  space -= 8;
+  ASSERT_EQ(space, data.available_);
 
   data.SetBool("ee", true);
-  ASSERT_EQ(space - 24 - 16 - 24 - 32 - 8 - 16, data.available_);
+  space -= 16;
+  ASSERT_EQ(space, data.available_);
 
   data.SetString("f", "");
-  ASSERT_EQ(space - 24 - 16 - 24 - 32 - 8 - 16 - 8, data.available_);
+  space -= 8;
+  ASSERT_EQ(space, data.available_);
 }
 
 TEST_F(ActivityTrackerTest, PushPopTest) {
@@ -250,6 +278,16 @@
 
 // GlobalActivityTracker tests below.
 
+TEST_F(ActivityTrackerTest, BasicTest) {
+  GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
+  GlobalActivityTracker* global = GlobalActivityTracker::Get();
+
+  // Ensure the data repositories have backing store, indicated by non-zero ID.
+  EXPECT_NE(0U, global->process_data().id());
+  EXPECT_NE(0U, global->global_data().id());
+  EXPECT_NE(global->process_data().id(), global->global_data().id());
+}
+
 class SimpleActivityThread : public SimpleThread {
  public:
   SimpleActivityThread(const std::string& name,
@@ -336,5 +374,107 @@
   EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
 }
 
+TEST_F(ActivityTrackerTest, ProcessDeathTest) {
+  // This doesn't actually create and destroy a process. Instead, it uses for-
+  // testing interfaces to simulate data created by other processes.
+  const ProcessId other_process_id = GetCurrentProcId() + 1;
+
+  GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3);
+  GlobalActivityTracker* global = GlobalActivityTracker::Get();
+  ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
+
+  // Get callbacks for process exit.
+  global->SetProcessExitCallback(
+      Bind(&ActivityTrackerTest::HandleProcessExit, Unretained(this)));
+
+  // Pretend than another process has started.
+  global->RecordProcessLaunch(other_process_id, FILE_PATH_LITERAL("foo --bar"));
+
+  // Do some activities.
+  PendingTask task(FROM_HERE, base::Bind(&DoNothing));
+  ScopedTaskRunActivity activity(task);
+  ActivityUserData& user_data = activity.user_data();
+  ASSERT_NE(0U, user_data.id());
+
+  // Get the memory-allocator references to that data.
+  PersistentMemoryAllocator::Reference proc_data_ref =
+      global->allocator()->GetAsReference(
+          global->process_data().GetBaseAddress(),
+          GlobalActivityTracker::kTypeIdProcessDataRecord);
+  ASSERT_TRUE(proc_data_ref);
+  PersistentMemoryAllocator::Reference tracker_ref =
+      global->allocator()->GetAsReference(
+          thread->GetBaseAddress(),
+          GlobalActivityTracker::kTypeIdActivityTracker);
+  ASSERT_TRUE(tracker_ref);
+  PersistentMemoryAllocator::Reference user_data_ref =
+      global->allocator()->GetAsReference(
+          user_data.GetBaseAddress(),
+          GlobalActivityTracker::kTypeIdUserDataRecord);
+  ASSERT_TRUE(user_data_ref);
+
+  // Make a copy of the thread-tracker state so it can be restored later.
+  const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
+  std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
+  memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
+
+  // Change the objects to appear to be owned by another process.
+  ProcessId owning_id;
+  int64_t stamp;
+  ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
+      global->process_data().GetBaseAddress(), &owning_id, &stamp));
+  EXPECT_NE(other_process_id, owning_id);
+  ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
+      thread->GetBaseAddress(), &owning_id, &stamp));
+  EXPECT_NE(other_process_id, owning_id);
+  ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
+                                                   &owning_id, &stamp));
+  EXPECT_NE(other_process_id, owning_id);
+  global->process_data().SetOwningProcessIdForTesting(other_process_id, stamp);
+  thread->SetOwningProcessIdForTesting(other_process_id, stamp);
+  user_data.SetOwningProcessIdForTesting(other_process_id, stamp);
+  ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
+      global->process_data().GetBaseAddress(), &owning_id, &stamp));
+  EXPECT_EQ(other_process_id, owning_id);
+  ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
+      thread->GetBaseAddress(), &owning_id, &stamp));
+  EXPECT_EQ(other_process_id, owning_id);
+  ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
+                                                   &owning_id, &stamp));
+  EXPECT_EQ(other_process_id, owning_id);
+
+  // Check that process exit will perform callback and free the allocations.
+  ASSERT_EQ(0, exit_id);
+  ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
+            global->allocator()->GetType(proc_data_ref));
+  ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
+            global->allocator()->GetType(tracker_ref));
+  ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
+            global->allocator()->GetType(user_data_ref));
+  global->RecordProcessExit(other_process_id, 0);
+  EXPECT_EQ(other_process_id, exit_id);
+  EXPECT_EQ("foo --bar", exit_command);
+  EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
+            global->allocator()->GetType(proc_data_ref));
+  EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
+            global->allocator()->GetType(tracker_ref));
+  EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
+            global->allocator()->GetType(user_data_ref));
+
+  // Restore memory contents and types so things don't crash when doing real
+  // process clean-up.
+  memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
+         tracker_size);
+  global->allocator()->ChangeType(
+      proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
+      GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
+  global->allocator()->ChangeType(
+      tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
+      GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
+  global->allocator()->ChangeType(
+      user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
+      GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
+}
+
 }  // namespace debug
 }  // namespace base
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc
index 939174e..a0e3871 100644
--- a/base/metrics/persistent_histogram_allocator.cc
+++ b/base/metrics/persistent_histogram_allocator.cc
@@ -905,6 +905,8 @@
 }
 
 void GlobalHistogramAllocator::DeletePersistentLocation() {
+  memory_allocator()->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED);
+
 #if defined(OS_NACL)
   NOTREACHED();
 #else
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc
index f70b3969..d381d87 100644
--- a/base/metrics/persistent_memory_allocator.cc
+++ b/base/metrics/persistent_memory_allocator.cc
@@ -18,6 +18,7 @@
 #include "base/memory/shared_memory.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/sparse_histogram.h"
+#include "base/threading/thread_restrictions.h"
 
 namespace {
 
@@ -32,7 +33,7 @@
 // The current version of the metadata. If updates are made that change
 // the metadata, the version number can be queried to operate in a backward-
 // compatible manner until the memory segment is completely re-initalized.
-const uint32_t kGlobalVersion = 1;
+const uint32_t kGlobalVersion = 2;
 
 // Constant values placed in the block headers to indicate its state.
 const uint32_t kBlockCookieFree = 0;
@@ -43,7 +44,7 @@
 // TODO(bcwhite): When acceptable, consider moving flags to std::atomic<char>
 // types rather than combined bitfield.
 
-// Flags stored in the flags_ field of the SharedMetaData structure below.
+// Flags stored in the flags_ field of the SharedMetadata structure below.
 enum : int {
   kFlagCorrupt = 1 << 0,
   kFlagFull    = 1 << 1
@@ -100,7 +101,9 @@
 };
 
 // The shared metadata exists once at the top of the memory segment to
-// describe the state of the allocator to all processes.
+// describe the state of the allocator to all processes. The size of this
+// structure must be a multiple of 64-bits to ensure compatibility between
+// architectures.
 struct PersistentMemoryAllocator::SharedMetadata {
   uint32_t cookie;     // Some value that indicates complete initialization.
   uint32_t size;       // Total size of memory segment.
@@ -108,10 +111,15 @@
   uint32_t version;    // Version code so upgrades don't break.
   uint64_t id;         // Arbitrary ID number given by creator.
   uint32_t name;       // Reference to stored name string.
+  uint32_t padding1;   // Pad-out read-only data to 64-bit alignment.
 
   // Above is read-only after first construction. Below may be changed and
   // so must be marked "volatile" to provide correct inter-process behavior.
 
+  // State of the memory, plus some padding to keep alignment.
+  volatile std::atomic<uint8_t> memory_state;  // MemoryState enum values.
+  uint8_t padding2[3];
+
   // Bitfield of information flags. Access to this should be done through
   // the CheckFlag() and SetFlag() methods defined above.
   volatile std::atomic<uint32_t> flags;
@@ -121,6 +129,7 @@
 
   // The "iterable" queue is an M&S Queue as described here, append-only:
   // https://www.research.ibm.com/people/m/michael/podc-1996.pdf
+  // |queue| needs to be 64-bit aligned and is itself a multiple of 64 bits.
   volatile std::atomic<uint32_t> tailptr;  // Last block of iteration queue.
   volatile BlockHeader queue;   // Empty block for linked-list head/tail.
 };
@@ -312,7 +321,7 @@
   // definitions and so cannot be moved to the global scope.
   static_assert(sizeof(PersistentMemoryAllocator::BlockHeader) == 16,
                 "struct is not portable across different natural word widths");
-  static_assert(sizeof(PersistentMemoryAllocator::SharedMetadata) == 56,
+  static_assert(sizeof(PersistentMemoryAllocator::SharedMetadata) == 64,
                 "struct is not portable across different natural word widths");
 
   static_assert(sizeof(BlockHeader) % kAllocAlignment == 0,
@@ -384,12 +393,13 @@
       if (name_cstr)
         memcpy(name_cstr, name.data(), name.length());
     }
+
+    shared_meta()->memory_state.store(MEMORY_INITIALIZED,
+                                      std::memory_order_release);
   } else {
-    if (shared_meta()->size == 0 ||
-        shared_meta()->version == 0 ||
+    if (shared_meta()->size == 0 || shared_meta()->version != kGlobalVersion ||
         shared_meta()->freeptr.load(std::memory_order_relaxed) == 0 ||
-        shared_meta()->tailptr == 0 ||
-        shared_meta()->queue.cookie == 0 ||
+        shared_meta()->tailptr == 0 || shared_meta()->queue.cookie == 0 ||
         shared_meta()->queue.next.load(std::memory_order_relaxed) == 0) {
       SetCorrupt();
     }
@@ -470,6 +480,19 @@
       HistogramBase::kUmaTargetedHistogramFlag);
 }
 
+void PersistentMemoryAllocator::Flush(bool sync) {
+  FlushPartial(used(), sync);
+}
+
+void PersistentMemoryAllocator::SetMemoryState(uint8_t memory_state) {
+  shared_meta()->memory_state.store(memory_state, std::memory_order_relaxed);
+  FlushPartial(sizeof(SharedMetadata), false);
+}
+
+uint8_t PersistentMemoryAllocator::GetMemoryState() const {
+  return shared_meta()->memory_state.load(std::memory_order_relaxed);
+}
+
 size_t PersistentMemoryAllocator::used() const {
   return std::min(shared_meta()->freeptr.load(std::memory_order_relaxed),
                   mem_size_);
@@ -816,8 +839,12 @@
 PersistentMemoryAllocator::GetBlock(Reference ref, uint32_t type_id,
                                     uint32_t size, bool queue_ok,
                                     bool free_ok) const {
+  // Handle special cases.
+  if (ref == kReferenceQueue && queue_ok)
+    return reinterpret_cast<const volatile BlockHeader*>(mem_base_ + ref);
+
   // Validation of parameters.
-  if (ref < (queue_ok ? kReferenceQueue : sizeof(SharedMetadata)))
+  if (ref < sizeof(SharedMetadata))
     return nullptr;
   if (ref % kAllocAlignment != 0)
     return nullptr;
@@ -827,17 +854,13 @@
 
   // Validation of referenced block-header.
   if (!free_ok) {
-    uint32_t freeptr = std::min(
-        shared_meta()->freeptr.load(std::memory_order_relaxed), mem_size_);
-    if (ref + size > freeptr)
-      return nullptr;
     const volatile BlockHeader* const block =
         reinterpret_cast<volatile BlockHeader*>(mem_base_ + ref);
+    if (block->cookie != kBlockCookieAllocated)
+      return nullptr;
     if (block->size < size)
       return nullptr;
-    if (ref + block->size > freeptr)
-      return nullptr;
-    if (ref != kReferenceQueue && block->cookie != kBlockCookieAllocated)
+    if (ref + block->size > mem_size_)
       return nullptr;
     if (type_id != 0 &&
         block->type_id.load(std::memory_order_relaxed) != type_id) {
@@ -849,6 +872,13 @@
   return reinterpret_cast<const volatile BlockHeader*>(mem_base_ + ref);
 }
 
+void PersistentMemoryAllocator::FlushPartial(size_t length, bool sync) {
+  // Generally there is nothing to do as every write is done through volatile
+  // memory with atomic instructions to guarantee consistency. This (virtual)
+  // method exists so that derivced classes can do special things, such as
+  // tell the OS to write changes to disk now rather than when convenient.
+}
+
 void PersistentMemoryAllocator::RecordError(int error) const {
   if (errors_histogram_)
     errors_histogram_->Add(error);
@@ -989,7 +1019,12 @@
           id,
           name,
           read_only),
-      mapped_file_(std::move(file)) {}
+      mapped_file_(std::move(file)) {
+  // Ensure the disk-copy of the data reflects the fully-initialized memory as
+  // there is no guarantee as to what order the pages might be auto-flushed by
+  // the OS in the future.
+  Flush(true);
+}
 
 FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() {}
 
@@ -999,6 +1034,33 @@
     bool read_only) {
   return IsMemoryAcceptable(file.data(), file.length(), 0, read_only);
 }
+
+void FilePersistentMemoryAllocator::FlushPartial(size_t length, bool sync) {
+  if (sync)
+    ThreadRestrictions::AssertIOAllowed();
+  if (IsReadonly())
+    return;
+
+#if defined(OS_WIN)
+  // Windows doesn't support a synchronous flush.
+  BOOL success = ::FlushViewOfFile(data(), length);
+  DPCHECK(success);
+#elif defined(OS_MACOSX)
+  // On OSX, "invalidate" removes all cached pages, forcing a re-read from
+  // disk. That's not applicable to "flush" so omit it.
+  int result =
+      ::msync(const_cast<void*>(data()), length, sync ? MS_SYNC : MS_ASYNC);
+  DCHECK_NE(EINVAL, result);
+#elif defined(OS_POSIX)
+  // On POSIX, "invalidate" forces _other_ processes to recognize what has
+  // been written to disk and so is applicable to "flush".
+  int result = ::msync(const_cast<void*>(data()), length,
+                       MS_INVALIDATE | (sync ? MS_SYNC : MS_ASYNC));
+  DCHECK_NE(EINVAL, result);
+#else
+#error Unsupported OS.
+#endif
+}
 #endif  // !defined(OS_NACL)
 
 }  // namespace base
diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h
index b38f284..94a7744b 100644
--- a/base/metrics/persistent_memory_allocator.h
+++ b/base/metrics/persistent_memory_allocator.h
@@ -96,6 +96,29 @@
  public:
   typedef uint32_t Reference;
 
+  // These states are used to indicate the overall condition of the memory
+  // segment irrespective of what is stored within it. Because the data is
+  // often persistent and thus needs to be readable by different versions of
+  // a program, these values are fixed and can never change.
+  enum MemoryState : uint8_t {
+    // Persistent memory starts all zeros and so shows "uninitialized".
+    MEMORY_UNINITIALIZED = 0,
+
+    // The header has been written and the memory is ready for use.
+    MEMORY_INITIALIZED = 1,
+
+    // The data should be considered deleted. This would be set when the
+    // allocator is being cleaned up. If file-backed, the file is likely
+    // to be deleted but since deletion can fail for a variety of reasons,
+    // having this extra status means a future reader can realize what
+    // should have happened.
+    MEMORY_DELETED = 2,
+
+    // Outside code can create states starting with this number; these too
+    // must also never change between code versions.
+    MEMORY_USER_DEFINED = 100,
+  };
+
   // Iterator for going through all iterable memory records in an allocator.
   // Like the allocator itself, iterators are lock-free and thread-secure.
   // That means that multiple threads can share an iterator and the same
@@ -280,7 +303,11 @@
   const char* Name() const;
 
   // Is this segment open only for read?
-  bool IsReadonly() { return readonly_; }
+  bool IsReadonly() const { return readonly_; }
+
+  // Manage the saved state of the memory.
+  void SetMemoryState(uint8_t memory_state);
+  uint8_t GetMemoryState() const;
 
   // Create internal histograms for tracking memory use and allocation sizes
   // for allocator of |name| (which can simply be the result of Name()). This
@@ -293,6 +320,17 @@
   //    UMA.PersistentAllocator.name.UsedPct
   void CreateTrackingHistograms(base::StringPiece name);
 
+  // Flushes the persistent memory to any backing store. This typically does
+  // nothing but is used by the FilePersistentMemoryAllocator to inform the
+  // OS that all the data should be sent to the disk immediately. This is
+  // useful in the rare case where something has just been stored that needs
+  // to survive a hard shutdown of the machine like from a power failure.
+  // The |sync| parameter indicates if this call should block until the flush
+  // is complete but is only advisory and may or may not have an effect
+  // depending on the capabilities of the OS. Synchronous flushes are allowed
+  // only from theads that are allowed to do I/O.
+  void Flush(bool sync);
+
   // Direct access to underlying memory segment. If the segment is shared
   // across threads or processes, reading data through these values does
   // not guarantee consistency. Use with care. Do not write.
@@ -580,6 +618,9 @@
                             uint64_t id, base::StringPiece name,
                             bool readonly);
 
+  // Implementation of Flush that accepts how much to flush.
+  virtual void FlushPartial(size_t length, bool sync);
+
   volatile char* const mem_base_;  // Memory base. (char so sizeof guaranteed 1)
   const MemoryType mem_type_;      // Type of memory allocation.
   const uint32_t mem_size_;        // Size of entire memory segment.
@@ -715,6 +756,10 @@
   // the rest.
   static bool IsFileAcceptable(const MemoryMappedFile& file, bool read_only);
 
+ protected:
+  // PersistentMemoryAllocator:
+  void FlushPartial(size_t length, bool sync) override;
+
  private:
   std::unique_ptr<MemoryMappedFile> mapped_file_;
 
diff --git a/base/metrics/persistent_memory_allocator_unittest.cc b/base/metrics/persistent_memory_allocator_unittest.cc
index d12e00f..c3027ec 100644
--- a/base/metrics/persistent_memory_allocator_unittest.cc
+++ b/base/metrics/persistent_memory_allocator_unittest.cc
@@ -100,6 +100,8 @@
   EXPECT_TRUE(allocator_->used_histogram_);
   EXPECT_EQ("UMA.PersistentAllocator." + base_name + ".UsedPct",
             allocator_->used_histogram_->histogram_name());
+  EXPECT_EQ(PersistentMemoryAllocator::MEMORY_INITIALIZED,
+            allocator_->GetMemoryState());
 
   // Get base memory info for later comparison.
   PersistentMemoryAllocator::MemoryInfo meminfo0;
@@ -254,6 +256,11 @@
   allocator_->Delete(obj2);
   PersistentMemoryAllocator::Iterator iter1z(allocator_.get());
   EXPECT_EQ(nullptr, iter1z.GetNextOfObject<TestObject2>());
+
+  // Ensure that the memory state can be set.
+  allocator_->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED);
+  EXPECT_EQ(PersistentMemoryAllocator::MEMORY_DELETED,
+            allocator_->GetMemoryState());
 }
 
 TEST_F(PersistentMemoryAllocatorTest, PageTest) {
@@ -691,8 +698,8 @@
   const size_t mmlength = mmfile->length();
   EXPECT_GE(meminfo1.total, mmlength);
 
-  FilePersistentMemoryAllocator file(std::move(mmfile), 0, 0, "", true);
-  EXPECT_TRUE(file.IsReadonly());
+  FilePersistentMemoryAllocator file(std::move(mmfile), 0, 0, "", false);
+  EXPECT_FALSE(file.IsReadonly());
   EXPECT_EQ(TEST_ID, file.Id());
   EXPECT_FALSE(file.IsFull());
   EXPECT_FALSE(file.IsCorrupt());
@@ -713,6 +720,11 @@
   EXPECT_GE(meminfo1.free, meminfo2.free);
   EXPECT_EQ(mmlength, meminfo2.total);
   EXPECT_EQ(0U, meminfo2.free);
+
+  // There's no way of knowing if Flush actually does anything but at least
+  // verify that it runs without CHECK violations.
+  file.Flush(false);
+  file.Flush(true);
 }
 
 TEST(FilePersistentMemoryAllocatorTest, ExtendTest) {
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index 1349b3e..bb51a69 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -17,6 +17,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/debug/activity_tracker.h"
 #include "base/debug/stack_trace.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
@@ -94,7 +95,12 @@
     NOTREACHED() << "Failed to start process";
     return false;
   }
+
   base::win::ScopedProcessInformation proc_info(temp_process_info);
+  base::debug::GlobalActivityTracker* tracker =
+      base::debug::GlobalActivityTracker::Get();
+  if (tracker)
+    tracker->RecordProcessLaunch(proc_info.process_id(), cl.as_string());
 
   // Close our writing end of pipe now. Otherwise later read would not be able
   // to detect end of child's output.
@@ -119,6 +125,8 @@
   int exit_code;
   base::TerminationStatus status = GetTerminationStatus(
       proc_info.process_handle(), &exit_code);
+  base::debug::GlobalActivityTracker::RecordProcessExitIfEnabled(
+      proc_info.process_id(), exit_code);
   return status != base::TERMINATION_STATUS_PROCESS_CRASHED &&
          status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION;
 }
@@ -317,6 +325,8 @@
   if (options.wait)
     WaitForSingleObject(process_info.process_handle(), INFINITE);
 
+  base::debug::GlobalActivityTracker::RecordProcessLaunchIfEnabled(
+      process_info.process_id(), cmdline);
   return Process(process_info.TakeProcessHandle());
 }
 
@@ -344,6 +354,8 @@
   if (options.wait)
     WaitForSingleObject(shex_info.hProcess, INFINITE);
 
+  base::debug::GlobalActivityTracker::RecordProcessLaunchIfEnabled(
+      GetProcessId(shex_info.hProcess), file, arguments);
   return Process(shex_info.hProcess);
 }
 
diff --git a/base/process/process_win.cc b/base/process/process_win.cc
index 62321265..9232c6d 100644
--- a/base/process/process_win.cc
+++ b/base/process/process_win.cc
@@ -139,6 +139,10 @@
   } else if (!result) {
     DPLOG(ERROR) << "Unable to terminate process";
   }
+  if (result) {
+    base::debug::GlobalActivityTracker::RecordProcessExitIfEnabled(Pid(),
+                                                                   exit_code);
+  }
   return result;
 }
 
@@ -162,6 +166,9 @@
 
   if (exit_code)
     *exit_code = temp_code;
+
+  base::debug::GlobalActivityTracker::RecordProcessExitIfEnabled(
+      Pid(), static_cast<int>(temp_code));
   return true;
 }
 
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
index 0d9d55db..6a2676f 100644
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
+++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -229,7 +229,7 @@
   size_t workers_unregistered_during_join =
       subtle::NoBarrier_Load(&workers_unregistered_during_join_);
   DCHECK_EQ(workers_unregistered_during_join, workers_.size())
-      << "There cannot be outstanding SingleThreadTaskRunners upon destruction"
+      << "There cannot be outstanding SingleThreadTaskRunners upon destruction "
          "of SchedulerSingleThreadTaskRunnerManager or the Task Scheduler";
 #endif
 }
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
index ea9cb66a..1311ea8 100644
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
+++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
@@ -280,6 +280,7 @@
  private:
   SchedulerSingleThreadTaskRunnerManager* const manager_to_join_;
   WaitableEvent run_started_event_;
+
   DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
 };
 
@@ -302,6 +303,8 @@
 }  // namespace
 
 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
+  // Exercises the codepath where the workers are unavailable for unregistration
+  // because of a Join call.
   WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
                              WaitableEvent::InitialState::NOT_SIGNALED);
   WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
@@ -328,6 +331,8 @@
 
 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest,
        ConcurrentJoinExtraSkippedTask) {
+  // Tests to make sure that tasks are properly cleaned up at Join, allowing
+  // SingleThreadTaskRunners to unregister themselves.
   WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
                              WaitableEvent::InitialState::NOT_SIGNALED);
   WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
diff --git a/build/OWNERS b/build/OWNERS
index c57052cb..89f07f1d 100644
--- a/build/OWNERS
+++ b/build/OWNERS
@@ -6,6 +6,7 @@
 thakis@chromium.org
 brucedawson@chromium.org
 
+per-file .gitignore=*
 per-file mac_toolchain.py=erikchen@chromium.org
 per-file mac_toolchain.py=justincohen@chromium.org
 per-file package_mac_toolchain.py=erikchen@chromium.org
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn
index fddca1b..ea55411 100644
--- a/build/config/android/BUILD.gn
+++ b/build/config/android/BUILD.gn
@@ -39,7 +39,6 @@
   }
 
   ldflags = [
-    "-Wl,--build-id=sha1",
     "-Wl,--no-undefined",
 
     # Don't allow visible symbols from libgcc or libc++ to be
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 1f89686..d60664b 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -277,6 +277,16 @@
       }
     }
 
+    if (is_official_build) {
+      # Explicitly pass --build-id to ld. Compilers used to always pass this
+      # implicitly but don't any more (in particular clang when built without
+      # ENABLE_LINKER_BUILD_ID=ON). The crash infrastructure does need a build
+      # id, so explicitly enable it in official builds. It's not needed in
+      # unofficial builds and computing it does slow down the link, so go with
+      # faster links in unofficial builds.
+      ldflags += [ "-Wl,--build-id=sha1" ]
+    }
+
     defines += [ "_FILE_OFFSET_BITS=64" ]
 
     if (!is_android) {
diff --git a/cc/playback/display_item_list.cc b/cc/playback/display_item_list.cc
index 1d54ae7..f9a827de 100644
--- a/cc/playback/display_item_list.cc
+++ b/cc/playback/display_item_list.cc
@@ -157,13 +157,9 @@
 
 }  // namespace
 
-DisplayItemList::Inputs::Inputs()
-    : items(LargestDisplayItemSize(),
-            LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {}
-
-DisplayItemList::Inputs::~Inputs() = default;
-
-DisplayItemList::DisplayItemList() = default;
+DisplayItemList::DisplayItemList()
+    : items_(LargestDisplayItemSize(),
+             LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {}
 
 DisplayItemList::~DisplayItemList() = default;
 
@@ -194,7 +190,7 @@
   std::vector<size_t> indices;
   rtree_.Search(canvas_playback_rect, &indices);
   for (size_t index : indices) {
-    RasterItem(inputs_.items[index], canvas, callback);
+    RasterItem(items_[index], canvas, callback);
 
     // We use a callback during solid color analysis on the compositor thread to
     // break out early. Since we're handling a sequence of pictures via rtree
@@ -206,21 +202,21 @@
 
 void DisplayItemList::GrowCurrentBeginItemVisualRect(
     const gfx::Rect& visual_rect) {
-  if (!inputs_.begin_item_indices.empty())
-    inputs_.visual_rects[inputs_.begin_item_indices.back()].Union(visual_rect);
+  if (!begin_item_indices_.empty())
+    visual_rects_[begin_item_indices_.back()].Union(visual_rect);
 }
 
 void DisplayItemList::Finalize() {
   TRACE_EVENT0("cc", "DisplayItemList::Finalize");
-  DCHECK(inputs_.items.size() == inputs_.visual_rects.size())
-      << "items.size() " << inputs_.items.size() << " visual_rects.size() "
-      << inputs_.visual_rects.size();
-  rtree_.Build(inputs_.visual_rects);
+  DCHECK(items_.size() == visual_rects_.size())
+      << "items.size() " << items_.size() << " visual_rects.size() "
+      << visual_rects_.size();
+  rtree_.Build(visual_rects_);
 
   if (!retain_visual_rects_)
     // This clears both the vector and the vector's capacity, since
     // visual_rects won't be used anymore.
-    std::vector<gfx::Rect>().swap(inputs_.visual_rects);
+    std::vector<gfx::Rect>().swap(visual_rects_);
 }
 
 bool DisplayItemList::IsSuitableForGpuRasterization() const {
@@ -228,7 +224,7 @@
   // none of the items might individually trigger a veto even though they
   // collectively have enough "bad" operations that a corresponding Picture
   // would get vetoed. See crbug.com/513016.
-  return inputs_.all_items_are_suitable_for_gpu_rasterization;
+  return all_items_are_suitable_for_gpu_rasterization_;
 }
 
 int DisplayItemList::ApproximateOpCount() const {
@@ -239,7 +235,7 @@
   size_t memory_usage = sizeof(*this);
 
   size_t external_memory_usage = 0;
-  for (const auto& item : inputs_.items) {
+  for (const auto& item : items_) {
     size_t bytes = 0;
     switch (item.type) {
       case DisplayItem::CLIP:
@@ -281,7 +277,7 @@
   }
 
   // Memory outside this class due to |items_|.
-  memory_usage += inputs_.items.GetCapacityInBytes() + external_memory_usage;
+  memory_usage += items_.GetCapacityInBytes() + external_memory_usage;
 
   // TODO(jbroman): Does anything else owned by this class substantially
   // contribute to memory usage?
@@ -313,10 +309,10 @@
   if (include_items) {
     state->BeginArray("items");
 
-    auto visual_rects_it = inputs_.visual_rects.begin();
-    for (const DisplayItem& base_item : inputs_.items) {
+    auto visual_rects_it = visual_rects_.begin();
+    for (const DisplayItem& base_item : items_) {
       gfx::Rect visual_rect;
-      if (visual_rects_it != inputs_.visual_rects.end()) {
+      if (visual_rects_it != visual_rects_.end()) {
         visual_rect = *visual_rects_it;
         ++visual_rects_it;
       }
@@ -490,7 +486,7 @@
   DiscardableImageMap::ScopedMetadataGenerator generator(
       &image_map_, gfx::Size(bounds.right(), bounds.bottom()));
   auto* canvas = generator.canvas();
-  for (const auto& item : inputs_.items)
+  for (const auto& item : items_)
     RasterItem(item, canvas, nullptr);
 }
 
diff --git a/cc/playback/display_item_list.h b/cc/playback/display_item_list.h
index 1b060825..1f78694 100644
--- a/cc/playback/display_item_list.h
+++ b/cc/playback/display_item_list.h
@@ -68,18 +68,18 @@
   const DisplayItemType& CreateAndAppendPairedBeginItemWithVisualRect(
       const gfx::Rect& visual_rect,
       Args&&... args) {
-    size_t item_index = inputs_.visual_rects.size();
-    inputs_.visual_rects.push_back(visual_rect);
-    inputs_.begin_item_indices.push_back(item_index);
+    size_t item_index = visual_rects_.size();
+    visual_rects_.push_back(visual_rect);
+    begin_item_indices_.push_back(item_index);
 
     return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
   }
 
   template <typename DisplayItemType, typename... Args>
   const DisplayItemType& CreateAndAppendPairedEndItem(Args&&... args) {
-    DCHECK(!inputs_.begin_item_indices.empty());
-    size_t last_begin_index = inputs_.begin_item_indices.back();
-    inputs_.begin_item_indices.pop_back();
+    DCHECK(!begin_item_indices_.empty());
+    size_t last_begin_index = begin_item_indices_.back();
+    begin_item_indices_.pop_back();
 
     // Note that we are doing two separate things below:
     //
@@ -103,11 +103,11 @@
     // overhead.
 
     // Ending bounds match the starting bounds.
-    inputs_.visual_rects.push_back(inputs_.visual_rects[last_begin_index]);
+    visual_rects_.push_back(visual_rects_[last_begin_index]);
 
     // The block that ended needs to be included in the bounds of the enclosing
     // block.
-    GrowCurrentBeginItemVisualRect(inputs_.visual_rects[last_begin_index]);
+    GrowCurrentBeginItemVisualRect(visual_rects_[last_begin_index]);
 
     return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
   }
@@ -116,7 +116,7 @@
   const DisplayItemType& CreateAndAppendDrawingItem(
       const gfx::Rect& visual_rect,
       Args&&... args) {
-    inputs_.visual_rects.push_back(visual_rect);
+    visual_rects_.push_back(visual_rect);
     GrowCurrentBeginItemVisualRect(visual_rect);
 
     return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
@@ -127,7 +127,7 @@
   void Finalize();
 
   void SetIsSuitableForGpuRasterization(bool is_suitable) {
-    inputs_.all_items_are_suitable_for_gpu_rasterization = is_suitable;
+    all_items_are_suitable_for_gpu_rasterization_ = is_suitable;
   }
   bool IsSuitableForGpuRasterization() const;
 
@@ -147,18 +147,16 @@
     retain_visual_rects_ = retain;
   }
 
-  size_t size() const { return inputs_.items.size(); }
+  size_t size() const { return items_.size(); }
 
-  gfx::Rect VisualRectForTesting(int index) {
-    return inputs_.visual_rects[index];
-  }
+  gfx::Rect VisualRectForTesting(int index) { return visual_rects_[index]; }
 
   ContiguousContainer<DisplayItem>::const_iterator begin() const {
-    return inputs_.items.begin();
+    return items_.begin();
   }
 
   ContiguousContainer<DisplayItem>::const_iterator end() const {
-    return inputs_.items.end();
+    return items_.end();
   }
 
  private:
@@ -170,43 +168,35 @@
   std::unique_ptr<base::trace_event::TracedValue> CreateTracedValue(
       bool include_items) const;
 
-  RTree rtree_;
-  // For testing purposes only. Whether to keep visual rects across calls to
-  // Finalize().
-  bool retain_visual_rects_ = false;
-
   // If we're currently within a paired display item block, unions the
   // given visual rect with the begin display item's visual rect.
   void GrowCurrentBeginItemVisualRect(const gfx::Rect& visual_rect);
 
   template <typename DisplayItemType, typename... Args>
   const DisplayItemType& AllocateAndConstruct(Args&&... args) {
-    auto* item = &inputs_.items.AllocateAndConstruct<DisplayItemType>(
+    auto* item = &items_.AllocateAndConstruct<DisplayItemType>(
         std::forward<Args>(args)...);
     approximate_op_count_ += item->ApproximateOpCount();
     return *item;
   }
 
-  int approximate_op_count_ = 0;
-
+  RTree rtree_;
   DiscardableImageMap image_map_;
+  ContiguousContainer<DisplayItem> items_;
 
-  struct Inputs {
-    Inputs();
-    ~Inputs();
+  // The visual rects associated with each of the display items in the
+  // display item list. There is one rect per display item, and the
+  // position in |visual_rects| matches the position of the item in
+  // |items| . These rects are intentionally kept separate
+  // because they are not needed while walking the |items| for raster.
+  std::vector<gfx::Rect> visual_rects_;
+  std::vector<size_t> begin_item_indices_;
 
-    ContiguousContainer<DisplayItem> items;
-    // The visual rects associated with each of the display items in the
-    // display item list. There is one rect per display item, and the
-    // position in |visual_rects| matches the position of the item in
-    // |items| . These rects are intentionally kept separate
-    // because they are not needed while walking the |items| for raster.
-    std::vector<gfx::Rect> visual_rects;
-    std::vector<size_t> begin_item_indices;
-    bool all_items_are_suitable_for_gpu_rasterization = true;
-  };
-
-  Inputs inputs_;
+  int approximate_op_count_ = 0;
+  bool all_items_are_suitable_for_gpu_rasterization_ = true;
+  // For testing purposes only. Whether to keep visual rects across calls to
+  // Finalize().
+  bool retain_visual_rects_ = false;
 
   friend class base::RefCountedThreadSafe<DisplayItemList>;
   FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage);
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 8c8637c..2ad91ae 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -386,50 +386,7 @@
   TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
   const media::VideoPixelFormat input_frame_format = video_frame->format();
 
-  // TODO(hubbe): Make this a video frame method.
-  int bits_per_channel = 0;
-  switch (input_frame_format) {
-    case media::PIXEL_FORMAT_UNKNOWN:
-      NOTREACHED();
-    // Fall through!
-    case media::PIXEL_FORMAT_I420:
-    case media::PIXEL_FORMAT_YV12:
-    case media::PIXEL_FORMAT_YV16:
-    case media::PIXEL_FORMAT_YV12A:
-    case media::PIXEL_FORMAT_YV24:
-    case media::PIXEL_FORMAT_NV12:
-    case media::PIXEL_FORMAT_NV21:
-    case media::PIXEL_FORMAT_UYVY:
-    case media::PIXEL_FORMAT_YUY2:
-    case media::PIXEL_FORMAT_ARGB:
-    case media::PIXEL_FORMAT_XRGB:
-    case media::PIXEL_FORMAT_RGB24:
-    case media::PIXEL_FORMAT_RGB32:
-    case media::PIXEL_FORMAT_MJPEG:
-    case media::PIXEL_FORMAT_MT21:
-    case media::PIXEL_FORMAT_Y8:
-    case media::PIXEL_FORMAT_I422:
-      bits_per_channel = 8;
-      break;
-    case media::PIXEL_FORMAT_YUV420P9:
-    case media::PIXEL_FORMAT_YUV422P9:
-    case media::PIXEL_FORMAT_YUV444P9:
-      bits_per_channel = 9;
-      break;
-    case media::PIXEL_FORMAT_YUV420P10:
-    case media::PIXEL_FORMAT_YUV422P10:
-    case media::PIXEL_FORMAT_YUV444P10:
-      bits_per_channel = 10;
-      break;
-    case media::PIXEL_FORMAT_YUV420P12:
-    case media::PIXEL_FORMAT_YUV422P12:
-    case media::PIXEL_FORMAT_YUV444P12:
-      bits_per_channel = 12;
-      break;
-    case media::PIXEL_FORMAT_Y16:
-      bits_per_channel = 16;
-      break;
-  }
+  int bits_per_channel = video_frame->BitsPerChannel(input_frame_format);
 
   // Only YUV and Y16 software video frames are supported.
   DCHECK(media::IsYuvPlanar(input_frame_format) ||
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
index c475793..880cb8c 100644
--- a/cc/surfaces/surface_factory.cc
+++ b/cc/surfaces/surface_factory.cc
@@ -41,14 +41,6 @@
   Destroy(std::move(current_surface_));
 }
 
-void SurfaceFactory::Reset() {
-  EvictSurface();
-  // Disown Surfaces that are still alive so that they don't try to unref
-  // resources that we're not tracking any more.
-  weak_factory_.InvalidateWeakPtrs();
-  holder_.Reset();
-}
-
 void SurfaceFactory::SubmitCompositorFrame(
     const LocalSurfaceId& local_surface_id,
     CompositorFrame frame,
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h
index 911c044..39a45fd 100644
--- a/cc/surfaces/surface_factory.h
+++ b/cc/surfaces/surface_factory.h
@@ -50,10 +50,6 @@
   // the old surface will be dealt with).
   void EvictSurface();
 
-  // Destroys and disowns the current surface, and resets all resource
-  // references. This is useful when resources are invalid (e.g. lost context).
-  void Reset();
-
   // Submits the frame to the current surface being managed by the factory if
   // the local frame ids match, or creates a new surface with the given local
   // frame id, destroys the old one, and submits the frame to this new surface.
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index 2ae43000..0e445dd 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -584,86 +584,6 @@
   EXPECT_FALSE(client_.returned_resources().empty());
 }
 
-// Tests that SurfaceFactory returns resources after Reset().
-TEST_F(SurfaceFactoryTest, Reset) {
-  LocalSurfaceId id(7, kArbitraryToken);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame;
-  frame.resource_list.push_back(resource);
-  factory_->SubmitCompositorFrame(id, std::move(frame),
-                                  SurfaceFactory::DrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), id);
-
-  SurfaceId surface_id(kArbitraryFrameSinkId, id);
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(client_.returned_resources().empty());
-  factory_->Reset();
-  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_FALSE(client_.returned_resources().empty());
-  local_surface_id_ = LocalSurfaceId();
-}
-
-// Tests that SurfaceFactory returns resources after Reset() if dependency
-// unregistered.
-TEST_F(SurfaceFactoryTest, ResetDependenceUnRegistered) {
-  LocalSurfaceId id(7, kArbitraryToken);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame;
-  frame.resource_list.push_back(resource);
-  factory_->SubmitCompositorFrame(id, std::move(frame),
-                                  SurfaceFactory::DrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), id);
-
-  SurfaceId surface_id(kArbitraryFrameSinkId, id);
-  Surface* surface = manager_.GetSurfaceForId(surface_id);
-  surface->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(client_.returned_resources().empty());
-  factory_->Reset();
-  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_FALSE(client_.returned_resources().empty());
-  local_surface_id_ = LocalSurfaceId();
-}
-
-// Tests that SurfaceFactory doesn't return resources after Reset() if
-// dependency registered.
-TEST_F(SurfaceFactoryTest, ResetDependencyRegistered) {
-  LocalSurfaceId id(7, kArbitraryToken);
-
-  TransferableResource resource;
-  resource.id = 1;
-  resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
-  CompositorFrame frame;
-  frame.resource_list.push_back(resource);
-  factory_->SubmitCompositorFrame(id, std::move(frame),
-                                  SurfaceFactory::DrawCallback());
-  EXPECT_EQ(last_created_surface_id().local_surface_id(), id);
-
-  manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
-
-  SurfaceId surface_id(kArbitraryFrameSinkId, id);
-  Surface* surface = manager_.GetSurfaceForId(surface_id);
-  surface->AddDestructionDependency(
-      SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(client_.returned_resources().empty());
-  factory_->Reset();
-  EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(client_.returned_resources().empty());
-
-  manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
-  EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
-  EXPECT_TRUE(client_.returned_resources().empty());
-  local_surface_id_ = LocalSurfaceId();
-}
-
 TEST_F(SurfaceFactoryTest, DestroySequence) {
   LocalSurfaceId local_surface_id2(5, kArbitraryToken);
   std::unique_ptr<SurfaceFactory> factory2(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index e79d47a..1643480 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -531,6 +531,7 @@
         mIncognitoTabCreator = tabCreators.second;
 
         OfflinePageUtils.observeTabModelSelector(this, mTabModelSelector);
+        NewTabPageUma.monitorNTPCreation(mTabModelSelector);
 
         if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
index ce662d7..01c791d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -190,9 +190,15 @@
             MediaNotificationManager manager = getManager();
             if (manager == null || manager.mMediaNotificationInfo == null) return false;
 
-            manager.onServiceStarted(this);
-
-            processAction(intent, manager);
+            if (intent.getAction() == null) {
+                // The intent comes from {@link startService()} or
+                // {@link startServiceWithNotification}.
+                manager.onServiceStarted(this);
+            } else {
+                // The intent comes from the notification. In this case, {@link onServiceStarted()}
+                // does need to be called.
+                processAction(intent, manager);
+            }
             return true;
         }
 
@@ -616,6 +622,8 @@
      * @param service the service that was started
      */
     private void onServiceStarted(ListenerService service) {
+        if (mService == service) return;
+
         mService = service;
         updateNotification();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
index 172ff86..5732a124 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
@@ -12,6 +12,7 @@
 import org.chromium.chrome.browser.shapedetection.TextDetectionImpl;
 import org.chromium.chrome.browser.webshare.ShareServiceImplementationFactory;
 import org.chromium.content_public.browser.InterfaceRegistrar;
+import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.PaymentRequest;
 import org.chromium.services.service_manager.InterfaceRegistry;
@@ -28,6 +29,8 @@
         InterfaceRegistrar.Registry.addContextRegistrar(new ChromeContextInterfaceRegistrar());
         InterfaceRegistrar.Registry.addWebContentsRegistrar(
                 new ChromeWebContentsInterfaceRegistrar());
+        InterfaceRegistrar.Registry.addRenderFrameHostRegistrar(
+                new ChromeRenderFrameHostInterfaceRegistrar());
     }
 
     private static class ChromeContextInterfaceRegistrar implements InterfaceRegistrar<Context> {
@@ -45,9 +48,18 @@
             implements InterfaceRegistrar<WebContents> {
         @Override
         public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
-            registry.addInterface(PaymentRequest.MANAGER, new PaymentRequestFactory(webContents));
             registry.addInterface(
                     ShareService.MANAGER, new ShareServiceImplementationFactory(webContents));
         }
     }
+
+    private static class ChromeRenderFrameHostInterfaceRegistrar
+            implements InterfaceRegistrar<RenderFrameHost> {
+        @Override
+        public void registerInterfaces(
+                InterfaceRegistry registry, final RenderFrameHost renderFrameHost) {
+            registry.addInterface(
+                    PaymentRequest.MANAGER, new PaymentRequestFactory(renderFrameHost));
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
index deb2e7d..d6c08f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
@@ -16,6 +16,8 @@
 import org.chromium.chrome.browser.rappor.RapporServiceBridge;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.PageTransition;
@@ -266,6 +268,15 @@
     }
 
     /**
+     * Records how often new tabs with a NewTabPage are created. This helps to determine how often
+     * users navigate back to already opened NTPs.
+     * @param tabModelSelector Model selector controlling the creation of new tabs.
+     */
+    public static void monitorNTPCreation(TabModelSelector tabModelSelector) {
+        tabModelSelector.addObserver(new TabCreationRecorder());
+    }
+
+    /**
      * Records the type of load for the NTP, such as cold or warm start.
      */
     public static void recordLoadType(ChromeActivity activity) {
@@ -308,6 +319,18 @@
     }
 
     /**
+     * Records the number of new NTPs opened in a new tab. Use through
+     * {@link NewTabPageUma#monitorNTPCreation(TabModelSelector)}.
+     */
+    private static class TabCreationRecorder extends EmptyTabModelSelectorObserver {
+        @Override
+        public void onNewTabCreated(Tab tab) {
+            if (!NewTabPage.isNTPUrl(tab.getUrl())) return;
+            RecordUserAction.record("MobileNTPOpenedInNewTab");
+        }
+    }
+
+    /**
      * Records stats related to content suggestion visits, such as the time spent on the website, or
      * if the user comes back to the NTP. Use through
      * {@link NewTabPageUma#monitorContentSuggestionVisit(Tab, int)}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
index 17f19df..dd84cca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
@@ -5,7 +5,7 @@
 package org.chromium.chrome.browser.payments;
 
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.mojo.system.MojoException;
 import org.chromium.payments.mojom.CanMakePaymentQueryResult;
 import org.chromium.payments.mojom.PaymentDetails;
@@ -20,7 +20,7 @@
  * Creates instances of PaymentRequest.
  */
 public class PaymentRequestFactory implements InterfaceFactory<PaymentRequest> {
-    private final WebContents mWebContents;
+    private final RenderFrameHost mRenderFrameHost;
 
     /**
      * An implementation of PaymentRequest that immediately rejects all connections.
@@ -71,8 +71,8 @@
      *
      * @param webContents The web contents that may invoke the PaymentRequest API.
      */
-    public PaymentRequestFactory(WebContents webContents) {
-        mWebContents = webContents;
+    public PaymentRequestFactory(RenderFrameHost renderFrameHost) {
+        mRenderFrameHost = renderFrameHost;
     }
 
     @Override
@@ -81,8 +81,8 @@
             return new InvalidPaymentRequest();
         }
 
-        if (mWebContents == null) return new InvalidPaymentRequest();
+        if (mRenderFrameHost == null) return new InvalidPaymentRequest();
 
-        return new PaymentRequestImpl(mWebContents);
+        return new PaymentRequestImpl(mRenderFrameHost);
     }
 }
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 3c06b63d..644351f 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
@@ -47,7 +47,9 @@
 import org.chromium.components.payments.CurrencyFormatter;
 import org.chromium.components.payments.PaymentValidator;
 import org.chromium.components.url_formatter.UrlFormatter;
+import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.WebContentsStatics;
 import org.chromium.mojo.system.MojoException;
 import org.chromium.payments.mojom.CanMakePaymentQueryResult;
 import org.chromium.payments.mojom.PaymentComplete;
@@ -246,6 +248,7 @@
     };
 
     private final Handler mHandler = new Handler();
+    private final RenderFrameHost mRenderFrameHost;
     private final WebContents mWebContents;
     private final String mSchemelessOriginForPaymentApp;
     private final String mOriginForDisplay;
@@ -348,10 +351,11 @@
      *
      * @param webContents The web contents that have invoked the PaymentRequest API.
      */
-    public PaymentRequestImpl(WebContents webContents) {
-        assert webContents != null;
+    public PaymentRequestImpl(RenderFrameHost renderFrameHost) {
+        assert renderFrameHost != null;
 
-        mWebContents = webContents;
+        mRenderFrameHost = renderFrameHost;
+        mWebContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost);
 
         mSchemelessOriginForPaymentApp = UrlFormatter.formatUrlForSecurityDisplay(
                 mWebContents.getLastCommittedUrl(), false /* omit scheme for payment apps. */);
@@ -359,7 +363,8 @@
         mOriginForDisplay = UrlFormatter.formatUrlForSecurityDisplay(
                 mWebContents.getLastCommittedUrl(), true /* include scheme in display */);
 
-        mMerchantName = webContents.getTitle();
+        mMerchantName = mWebContents.getTitle();
+
         mCertificateChain = CertificateChainHelper.getCertificateChain(mWebContents);
 
         mApps = new ArrayList<>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
index e161cdf..a667832f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTest.java
@@ -233,12 +233,12 @@
 
     /**
      * Tests that scanning the Daydream View NFC tag on supported devices
-     * fires the onvrdisplayactivate event.
+     * fires the vrdisplayactivate event.
      */
     @SmallTest
     @Restriction(RESTRICTION_TYPE_DAYDREAM_VIEW)
-    public void testNfcFiresOnvrdisplayactivate() throws InterruptedException {
-        String testName = "test_nfc_fires_onvrdisplayactivate";
+    public void testNfcFiresVrdisplayactivate() throws InterruptedException {
+        String testName = "test_nfc_fires_vrdisplayactivate";
         loadUrl(getHtmlTestFile(testName), 10);
         simNfcScanAndWait(mWebContents);
         endTest(mWebContents);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 4c7ab12..d1c92e8 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1216,6 +1216,8 @@
     "signin/signin_status_metrics_provider_chromeos.h",
     "signin/signin_tracker_factory.cc",
     "signin/signin_tracker_factory.h",
+    "signin/signin_util.cc",
+    "signin/signin_util.h",
     "site_details.cc",
     "site_details.h",
     "speech/chrome_speech_recognition_manager_delegate.cc",
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index ccb6bc0..ad12f6f8 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3168,13 +3168,13 @@
                  render_frame_host));
 
 #if defined(OS_ANDROID)
+  registry->AddInterface(
+      render_frame_host->GetJavaInterfaces()
+          ->CreateInterfaceFactory<payments::mojom::PaymentRequest>());
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   if (web_contents) {
     registry->AddInterface(
-        web_contents->GetJavaInterfaces()
-            ->CreateInterfaceFactory<payments::mojom::PaymentRequest>());
-    registry->AddInterface(
         base::Bind(&ForwardShareServiceRequest,
                    web_contents->GetJavaInterfaces()->GetWeakPtr()));
   }
diff --git a/chrome/browser/chrome_site_per_process_browsertest.cc b/chrome/browser/chrome_site_per_process_browsertest.cc
index de4374a4..6c45c0a 100644
--- a/chrome/browser/chrome_site_per_process_browsertest.cc
+++ b/chrome/browser/chrome_site_per_process_browsertest.cc
@@ -100,8 +100,16 @@
   return device_scale_factor;
 }
 
+// Flaky on Windows 10. http://crbug.com/700150
+#if defined(OS_WIN)
+#define MAYBE_InterstitialLoadsWithCorrectDeviceScaleFactor \
+  DISABLED_InterstitialLoadsWithCorrectDeviceScaleFactor
+#else
+#define MAYBE_InterstitialLoadsWithCorrectDeviceScaleFactor \
+  InterstitialLoadsWithCorrectDeviceScaleFactor
+#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIExpiredCertBrowserTest,
-                       InterstitialLoadsWithCorrectDeviceScaleFactor) {
+                       MAYBE_InterstitialLoadsWithCorrectDeviceScaleFactor) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
   ui_test_utils::NavigateToURL(browser(), main_url);
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 47ff0add..d59ec468 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -258,7 +258,7 @@
          AreArcAllOptInPreferencesManagedForProfile(profile_));
     if (!suppress_play_store_app) {
       playstore_launcher_.reset(
-          new ArcAppLauncher(profile_, kPlayStoreAppId, true));
+          new ArcAppLauncher(profile_, kPlayStoreAppId, true, false));
     }
 
     for (auto& observer : observer_list_)
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 6ba3c6d..1705418 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -967,6 +967,10 @@
       "api/log_private/syslog_parser.cc",
       "api/log_private/syslog_parser.h",
       "api/messaging/native_message_host_chromeos.cc",
+      "api/networking_cast_private/chrome_networking_cast_private_delegate.cc",
+      "api/networking_cast_private/chrome_networking_cast_private_delegate.h",
+      "api/networking_cast_private/networking_cast_private_api.cc",
+      "api/networking_cast_private/networking_cast_private_api.h",
       "api/networking_private/crypto_verify_impl.cc",
       "api/networking_private/crypto_verify_impl.h",
       "api/platform_keys/platform_keys_api.cc",
@@ -1071,6 +1075,10 @@
 
   if (is_win || is_mac) {
     sources += [
+      "api/networking_cast_private/chrome_networking_cast_private_delegate.cc",
+      "api/networking_cast_private/chrome_networking_cast_private_delegate.h",
+      "api/networking_cast_private/networking_cast_private_api.cc",
+      "api/networking_cast_private/networking_cast_private_api.h",
       "api/networking_private/crypto_verify_impl.cc",
       "api/networking_private/crypto_verify_impl.h",
       "api/networking_private/networking_private_credentials_getter.h",
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 9aa074a..0ffe5d98 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/extensions/api/declarative_content/default_content_predicate_evaluators.h"
 #include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h"
 #include "chrome/browser/extensions/api/metrics_private/chrome_metrics_private_delegate.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
 #include "chrome/browser/extensions/api/storage/managed_value_store_cache.h"
 #include "chrome/browser/extensions/api/storage/sync_value_store_cache.h"
 #include "chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.h"
@@ -168,6 +169,16 @@
   return metrics_private_delegate_.get();
 }
 
+NetworkingCastPrivateDelegate*
+ChromeExtensionsAPIClient::GetNetworkingCastPrivateDelegate() {
+#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX)
+  if (!networking_cast_private_delegate_)
+    networking_cast_private_delegate_ =
+        ChromeNetworkingCastPrivateDelegate::Create();
+#endif
+  return networking_cast_private_delegate_.get();
+}
+
 #if defined(OS_CHROMEOS)
 NonNativeFileSystemDelegate*
 ChromeExtensionsAPIClient::GetNonNativeFileSystemDelegate() {
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.h b/chrome/browser/extensions/api/chrome_extensions_api_client.h
index 55611b7..bd5c116 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -54,6 +54,7 @@
       const override;
   ManagementAPIDelegate* CreateManagementAPIDelegate() const override;
   MetricsPrivateDelegate* GetMetricsPrivateDelegate() override;
+  NetworkingCastPrivateDelegate* GetNetworkingCastPrivateDelegate() override;
 
 #if defined(OS_CHROMEOS)
   NonNativeFileSystemDelegate* GetNonNativeFileSystemDelegate() override;
@@ -67,6 +68,8 @@
 
  private:
   std::unique_ptr<ChromeMetricsPrivateDelegate> metrics_private_delegate_;
+  std::unique_ptr<NetworkingCastPrivateDelegate>
+      networking_cast_private_delegate_;
 
 #if defined(OS_CHROMEOS)
   std::unique_ptr<NonNativeFileSystemDelegate> non_native_file_system_delegate_;
diff --git a/chrome/browser/extensions/api/networking_cast_private/OWNERS b/chrome/browser/extensions/api/networking_cast_private/OWNERS
new file mode 100644
index 0000000..b321c2f
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/OWNERS
@@ -0,0 +1,2 @@
+stevenjb@chromium.org
+tbarzic@chromium.org
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
new file mode 100644
index 0000000..f6fb067
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -0,0 +1,66 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
+
+#include "base/callback.h"
+#include "chrome/browser/extensions/api/networking_private/networking_private_verify_delegate_factory_impl.h"
+#include "extensions/common/api/networking_private.h"
+
+namespace extensions {
+
+namespace {
+
+ChromeNetworkingCastPrivateDelegate::FactoryCallback* g_factory_callback =
+    nullptr;
+
+}  // namespace
+
+std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+ChromeNetworkingCastPrivateDelegate::Create() {
+  if (g_factory_callback)
+    return g_factory_callback->Run();
+  return std::unique_ptr<ChromeNetworkingCastPrivateDelegate>(
+      new ChromeNetworkingCastPrivateDelegate(
+          NetworkingPrivateVerifyDelegateFactoryImpl().CreateDelegate()));
+}
+
+void ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+    FactoryCallback* factory_callback) {
+  g_factory_callback = factory_callback;
+}
+
+ChromeNetworkingCastPrivateDelegate::ChromeNetworkingCastPrivateDelegate(
+    std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate> crypto_verify)
+    : crypto_verify_(std::move(crypto_verify)) {}
+
+ChromeNetworkingCastPrivateDelegate::~ChromeNetworkingCastPrivateDelegate() {}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyDestination(
+    const api::networking_private::VerificationProperties& properties,
+    const VerifiedCallback& success_callback,
+    const FailureCallback& failure_callback) {
+  crypto_verify_->VerifyDestination(properties, success_callback,
+                                    failure_callback);
+}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptCredentials(
+    const std::string& guid,
+    const api::networking_private::VerificationProperties& properties,
+    const DataCallback& success_callback,
+    const FailureCallback& failure_callback) {
+  crypto_verify_->VerifyAndEncryptCredentials(
+      guid, properties, success_callback, failure_callback);
+}
+
+void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
+    const std::string& data,
+    const api::networking_private::VerificationProperties& properties,
+    const DataCallback& success_callback,
+    const FailureCallback& failure_callback) {
+  crypto_verify_->VerifyAndEncryptData(properties, data, success_callback,
+                                       failure_callback);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
new file mode 100644
index 0000000..618e4ca
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
@@ -0,0 +1,66 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "extensions/browser/api/networking_private/networking_cast_private_delegate.h"
+#include "extensions/browser/api/networking_private/networking_private_delegate.h"
+
+namespace extensions {
+
+// Chrome implementation of extensions::NetworkingCastPrivateDelegate.
+class ChromeNetworkingCastPrivateDelegate
+    : public NetworkingCastPrivateDelegate {
+ public:
+  using FactoryCallback =
+      base::Callback<std::unique_ptr<ChromeNetworkingCastPrivateDelegate>()>;
+  static void SetFactoryCallbackForTest(FactoryCallback* factory_callback);
+
+  static std::unique_ptr<ChromeNetworkingCastPrivateDelegate> Create();
+
+  ~ChromeNetworkingCastPrivateDelegate() override;
+
+  // NetworkingCastPrivateDelegate overrides:
+  void VerifyDestination(
+      const api::networking_private::VerificationProperties& properties,
+      const VerifiedCallback& success_callback,
+      const FailureCallback& failure_callback) override;
+  void VerifyAndEncryptCredentials(
+      const std::string& guid,
+      const api::networking_private::VerificationProperties& properties,
+      const DataCallback& success_callback,
+      const FailureCallback& failure_callback) override;
+  void VerifyAndEncryptData(
+      const std::string& data,
+      const api::networking_private::VerificationProperties& properties,
+      const DataCallback& success_callback,
+      const FailureCallback& failure_callback) override;
+
+ private:
+  // Friend the test so it can inject stub VerifyDelegate implementation.
+  // TODO(tbarzic): Remove this when NetworkingCastPrivateDelegate stops
+  // depending on
+  //     NetworkingPrivateDelegate::VerifyDelegate.
+  friend class NetworkingCastPrivateApiTest;
+
+  explicit ChromeNetworkingCastPrivateDelegate(
+      std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate>
+          verify_delegate);
+
+  // NetworkingPrivates API's crypto utility to which verification requests
+  // will be routed.
+  std::unique_ptr<NetworkingPrivateDelegate::VerifyDelegate> crypto_verify_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeNetworkingCastPrivateDelegate);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_CHROME_NETWORKING_CAST_PRIVATE_DELEGATE_H_
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
new file mode 100644
index 0000000..cd81046
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.cc
@@ -0,0 +1,239 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "chrome/common/extensions/api/networking_cast_private.h"
+#include "extensions/browser/api/extensions_api_client.h"
+#include "extensions/browser/api/networking_private/networking_cast_private_delegate.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/network/network_device_handler.h"
+#include "chromeos/network/network_handler.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+#endif
+
+namespace private_api = extensions::api::networking_private;
+namespace cast_api = extensions::api::networking_cast_private;
+
+namespace extensions {
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+// Parses TDLS status returned by network handler to networking_cast_private
+// TDLS status type.
+cast_api::TDLSStatus ParseTDLSStatus(const std::string& status) {
+  if (status == shill::kTDLSConnectedState)
+    return cast_api::TDLS_STATUS_CONNECTED;
+  if (status == shill::kTDLSNonexistentState)
+    return cast_api::TDLS_STATUS_NONEXISTENT;
+  if (status == shill::kTDLSDisabledState)
+    return cast_api::TDLS_STATUS_DISABLED;
+  if (status == shill::kTDLSDisconnectedState)
+    return cast_api::TDLS_STATUS_DISCONNECTED;
+  if (status == shill::kTDLSUnknownState)
+    return cast_api::TDLS_STATUS_UNKNOWN;
+
+  NOTREACHED() << "Unknown TDLS status " << status;
+  return cast_api::TDLS_STATUS_UNKNOWN;
+}
+#endif
+
+std::unique_ptr<private_api::VerificationProperties>
+AsPrivateApiVerificaitonProperties(
+    const cast_api::VerificationProperties& properties) {
+  std::unique_ptr<base::DictionaryValue> cast_properties_dict =
+      properties.ToValue();
+  CHECK(cast_properties_dict);
+  return private_api::VerificationProperties::FromValue(*cast_properties_dict);
+}
+
+}  // namespace
+
+NetworkingCastPrivateVerifyDestinationFunction::
+    ~NetworkingCastPrivateVerifyDestinationFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyDestinationFunction::Run() {
+  std::unique_ptr<cast_api::VerifyDestination::Params> params =
+      cast_api::VerifyDestination::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  NetworkingCastPrivateDelegate* delegate =
+      ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+  std::unique_ptr<private_api::VerificationProperties> private_api_properties =
+      AsPrivateApiVerificaitonProperties(params->properties);
+  delegate->VerifyDestination(
+      *private_api_properties,
+      base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Success,
+                 this),
+      base::Bind(&NetworkingCastPrivateVerifyDestinationFunction::Failure,
+                 this));
+
+  // VerifyDestination might respond synchronously, e.g. in tests.
+  return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyDestinationFunction::Success(bool result) {
+  Respond(ArgumentList(cast_api::VerifyDestination::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyDestinationFunction::Failure(
+    const std::string& error) {
+  Respond(Error(error));
+}
+
+NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::
+    ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Run() {
+  std::unique_ptr<cast_api::VerifyAndEncryptCredentials::Params> params =
+      cast_api::VerifyAndEncryptCredentials::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  NetworkingCastPrivateDelegate* delegate =
+      ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+  std::unique_ptr<private_api::VerificationProperties> private_api_properties =
+      AsPrivateApiVerificaitonProperties(params->properties);
+  delegate->VerifyAndEncryptCredentials(
+      params->network_guid, *private_api_properties,
+      base::Bind(
+          &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success,
+          this),
+      base::Bind(
+          &NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure,
+          this));
+
+  // VerifyAndEncryptCredentials might respond synchronously, e.g. in tests.
+  return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Success(
+    const std::string& result) {
+  Respond(ArgumentList(
+      cast_api::VerifyAndEncryptCredentials::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyAndEncryptCredentialsFunction::Failure(
+    const std::string& error) {
+  Respond(Error(error));
+}
+
+NetworkingCastPrivateVerifyAndEncryptDataFunction::
+    ~NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateVerifyAndEncryptDataFunction::Run() {
+  std::unique_ptr<cast_api::VerifyAndEncryptData::Params> params =
+      cast_api::VerifyAndEncryptData::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  NetworkingCastPrivateDelegate* delegate =
+      ExtensionsAPIClient::Get()->GetNetworkingCastPrivateDelegate();
+  std::unique_ptr<private_api::VerificationProperties> private_api_properties =
+      AsPrivateApiVerificaitonProperties(params->properties);
+  delegate->VerifyAndEncryptData(
+      params->data, *private_api_properties,
+      base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Success,
+                 this),
+      base::Bind(&NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure,
+                 this));
+
+  // VerifyAndEncryptData might respond synchronously, e.g. in tests.
+  return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void NetworkingCastPrivateVerifyAndEncryptDataFunction::Success(
+    const std::string& result) {
+  Respond(
+      ArgumentList(cast_api::VerifyAndEncryptData::Results::Create(result)));
+}
+
+void NetworkingCastPrivateVerifyAndEncryptDataFunction::Failure(
+    const std::string& error) {
+  Respond(Error(error));
+}
+
+NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::
+    ~NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Run() {
+  std::unique_ptr<cast_api::SetWifiTDLSEnabledState::Params> params =
+      cast_api::SetWifiTDLSEnabledState::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+#if defined(OS_CHROMEOS)
+  chromeos::NetworkHandler::Get()->network_device_handler()->SetWifiTDLSEnabled(
+      params->ip_or_mac_address, params->enabled,
+      base::Bind(&NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Success,
+                 this),
+      base::Bind(&NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Failure,
+                 this));
+
+  // SetWifiTDLSEnabled might respond synchronously, e.g. in tests.
+  return did_respond() ? AlreadyResponded() : RespondLater();
+#else
+  return RespondNow(Error("Not supported"));
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+void NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Success(
+    const std::string& result) {
+  Respond(ArgumentList(cast_api::SetWifiTDLSEnabledState::Results::Create(
+      ParseTDLSStatus(result))));
+}
+
+void NetworkingCastPrivateSetWifiTDLSEnabledStateFunction::Failure(
+    const std::string& error,
+    std::unique_ptr<base::DictionaryValue> error_data) {
+  Respond(Error(error));
+}
+#endif
+
+NetworkingCastPrivateGetWifiTDLSStatusFunction::
+    ~NetworkingCastPrivateGetWifiTDLSStatusFunction() {}
+
+ExtensionFunction::ResponseAction
+NetworkingCastPrivateGetWifiTDLSStatusFunction::Run() {
+  std::unique_ptr<cast_api::GetWifiTDLSStatus::Params> params =
+      cast_api::GetWifiTDLSStatus::Params::Create(*args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+#if defined(OS_CHROMEOS)
+  chromeos::NetworkHandler::Get()->network_device_handler()->GetWifiTDLSStatus(
+      params->ip_or_mac_address,
+      base::Bind(&NetworkingCastPrivateGetWifiTDLSStatusFunction::Success,
+                 this),
+      base::Bind(&NetworkingCastPrivateGetWifiTDLSStatusFunction::Failure,
+                 this));
+
+  // GetWifiTDLSStatus might respond synchronously, e.g. in tests.
+  return did_respond() ? AlreadyResponded() : RespondLater();
+#else
+  return RespondNow(Error("Not supported"));
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+void NetworkingCastPrivateGetWifiTDLSStatusFunction::Success(
+    const std::string& result) {
+  Respond(ArgumentList(
+      cast_api::GetWifiTDLSStatus::Results::Create(ParseTDLSStatus(result))));
+}
+
+void NetworkingCastPrivateGetWifiTDLSStatusFunction::Failure(
+    const std::string& error,
+    std::unique_ptr<base::DictionaryValue> error_data) {
+  Respond(Error(error));
+}
+#endif
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
new file mode 100644
index 0000000..749e8588
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_api.h
@@ -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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "extensions/browser/extension_function.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace extensions {
+
+class NetworkingCastPrivateVerifyDestinationFunction
+    : public UIThreadExtensionFunction {
+ public:
+  NetworkingCastPrivateVerifyDestinationFunction() {}
+  DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyDestination",
+                             NETWORKINGCASTPRIVATE_VERIFYDESTINATION);
+
+ protected:
+  ~NetworkingCastPrivateVerifyDestinationFunction() override;
+
+  // ExtensionFunction:
+  ResponseAction Run() override;
+
+  void Success(bool result);
+  void Failure(const std::string& error);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateVerifyDestinationFunction);
+};
+
+class NetworkingCastPrivateVerifyAndEncryptCredentialsFunction
+    : public UIThreadExtensionFunction {
+ public:
+  NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() {}
+  DECLARE_EXTENSION_FUNCTION(
+      "networking.castPrivate.verifyAndEncryptCredentials",
+      NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTCREDENTIALS);
+
+ protected:
+  ~NetworkingCastPrivateVerifyAndEncryptCredentialsFunction() override;
+
+  // ExtensionFunction:
+  ResponseAction Run() override;
+
+  void Success(const std::string& result);
+  void Failure(const std::string& error);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(
+      NetworkingCastPrivateVerifyAndEncryptCredentialsFunction);
+};
+
+class NetworkingCastPrivateVerifyAndEncryptDataFunction
+    : public UIThreadExtensionFunction {
+ public:
+  NetworkingCastPrivateVerifyAndEncryptDataFunction() {}
+  DECLARE_EXTENSION_FUNCTION("networking.castPrivate.verifyAndEncryptData",
+                             NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTDATA);
+
+ protected:
+  ~NetworkingCastPrivateVerifyAndEncryptDataFunction() override;
+
+  // ExtensionFunction:
+  ResponseAction Run() override;
+
+  void Success(const std::string& result);
+  void Failure(const std::string& error);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateVerifyAndEncryptDataFunction);
+};
+
+class NetworkingCastPrivateSetWifiTDLSEnabledStateFunction
+    : public UIThreadExtensionFunction {
+ public:
+  NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() {}
+  DECLARE_EXTENSION_FUNCTION("networking.castPrivate.setWifiTDLSEnabledState",
+                             NETWORKINGCASTPRIVATE_SETWIFITDLSENABLEDSTATE);
+
+ protected:
+  ~NetworkingCastPrivateSetWifiTDLSEnabledStateFunction() override;
+
+  // ExtensionFunction:
+  ResponseAction Run() override;
+
+#if defined(OS_CHROMEOS)
+  void Success(const std::string& result);
+  void Failure(const std::string& error,
+               std::unique_ptr<base::DictionaryValue> error_data);
+#endif
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(
+      NetworkingCastPrivateSetWifiTDLSEnabledStateFunction);
+};
+
+class NetworkingCastPrivateGetWifiTDLSStatusFunction
+    : public UIThreadExtensionFunction {
+ public:
+  NetworkingCastPrivateGetWifiTDLSStatusFunction() {}
+  DECLARE_EXTENSION_FUNCTION("networking.castPrivate.getWifiTDLSStatus",
+                             NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS);
+
+ protected:
+  ~NetworkingCastPrivateGetWifiTDLSStatusFunction() override;
+
+  // ExtensionFunction:
+  ResponseAction Run() override;
+
+#if defined(OS_CHROMEOS)
+  void Success(const std::string& result);
+  void Failure(const std::string& error,
+               std::unique_ptr<base::DictionaryValue> error_data);
+#endif
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateGetWifiTDLSStatusFunction);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_NETWORKING_CAST_PRIVATE_NETWORKING_CAST_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
new file mode 100644
index 0000000..bdfc502
--- /dev/null
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
@@ -0,0 +1,144 @@
+// 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 <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "extensions/browser/api/networking_private/networking_private_delegate.h"
+#include "extensions/common/api/networking_private.h"
+#include "extensions/common/switches.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill_service_client.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#endif
+
+namespace extensions {
+
+namespace {
+
+class TestVerifyDelegate : public NetworkingPrivateDelegate::VerifyDelegate {
+ public:
+  TestVerifyDelegate() = default;
+  ~TestVerifyDelegate() override = default;
+
+  void VerifyDestination(const VerificationProperties& properties,
+                         const BoolCallback& success_callback,
+                         const FailureCallback& failure_callback) override {
+    success_callback.Run(true);
+  }
+
+  void VerifyAndEncryptCredentials(
+      const std::string& guid,
+      const VerificationProperties& properties,
+      const StringCallback& success_callback,
+      const FailureCallback& failure_callback) override {
+    success_callback.Run("encrypted_credentials");
+  }
+
+  void VerifyAndEncryptData(const VerificationProperties& properties,
+                            const std::string& data,
+                            const StringCallback& success_callback,
+                            const FailureCallback& failure_callback) override {
+    success_callback.Run("encrypted_data");
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestVerifyDelegate);
+};
+
+}  // namespace
+
+class NetworkingCastPrivateApiTest : public ExtensionApiTest {
+ public:
+  NetworkingCastPrivateApiTest() = default;
+  ~NetworkingCastPrivateApiTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ExtensionApiTest::SetUpCommandLine(command_line);
+    // Whitelist the extension ID of the test extension.
+    command_line->AppendSwitchASCII(
+        extensions::switches::kWhitelistedExtensionID,
+        "epcifkihnkjgphfkloaaleeakhpmgdmn");
+  }
+
+  void SetUp() override {
+    networking_cast_private_delegate_factory_ = base::Bind(
+        &NetworkingCastPrivateApiTest::CreateNetworkingCastPrivateDelegate,
+        base::Unretained(this));
+    ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(
+        &networking_cast_private_delegate_factory_);
+
+    ExtensionApiTest::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    ExtensionApiTest::SetUpOnMainThread();
+
+#if defined(OS_CHROMEOS)
+    chromeos::DBusThreadManager* dbus_manager =
+        chromeos::DBusThreadManager::Get();
+    chromeos::ShillDeviceClient::TestInterface* device_test =
+        dbus_manager->GetShillDeviceClient()->GetTestInterface();
+    device_test->ClearDevices();
+    device_test->AddDevice("/device/stub_wifi_device1", shill::kTypeWifi,
+                           "stub_wifi_device");
+    device_test->SetTDLSState(shill::kTDLSConnectedState);
+
+    chromeos::ShillServiceClient::TestInterface* service_test =
+        dbus_manager->GetShillServiceClient()->GetTestInterface();
+    service_test->ClearServices();
+    service_test->AddService("stub_wifi", "stub_wifi_guid", "wifi",
+                             shill::kTypeWifi, shill::kStateOnline,
+                             true /* add_to_visible */);
+#endif  // defined(OS_CHROMEOS)
+  }
+
+  void TearDown() override {
+    ExtensionApiTest::TearDown();
+    ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr);
+  }
+
+  bool TdlsSupported() {
+#if defined(OS_CHROMEOS)
+    return true;
+#else
+    return false;
+#endif
+  }
+
+ private:
+  std::unique_ptr<ChromeNetworkingCastPrivateDelegate>
+  CreateNetworkingCastPrivateDelegate() {
+    return std::unique_ptr<ChromeNetworkingCastPrivateDelegate>(
+        new ChromeNetworkingCastPrivateDelegate(
+            base::MakeUnique<TestVerifyDelegate>()));
+  }
+
+  ChromeNetworkingCastPrivateDelegate::FactoryCallback
+      networking_cast_private_delegate_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkingCastPrivateApiTest);
+};
+
+IN_PROC_BROWSER_TEST_F(NetworkingCastPrivateApiTest, Basic) {
+  const std::string arg =
+      base::StringPrintf("{\"tdlsSupported\": %d}", TdlsSupported());
+  EXPECT_TRUE(RunPlatformAppTestWithArg("networking_cast_private", arg.c_str()))
+      << message_;
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc
index 0d6afba..193f85ce 100644
--- a/chrome/browser/profiles/profile_attributes_entry.cc
+++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -1,19 +1,10 @@
 // Copyright 2015 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-#include "chrome/browser/browser_process.h"
+
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_service.h"
-
-namespace {
-bool IsForceSigninEnabled() {
-  PrefService* prefs = g_browser_process->local_state();
-  return prefs && prefs->GetBoolean(prefs::kForceBrowserSignin);
-}
-}  // namespace
+#include "chrome/browser/signin/signin_util.h"
 
 ProfileAttributesEntry::ProfileAttributesEntry()
     : profile_info_cache_(nullptr), profile_path_(base::FilePath()) {}
@@ -26,7 +17,7 @@
   DCHECK(profile_path_.empty());
   DCHECK(!path.empty());
   profile_path_ = path;
-  is_force_signin_enabled_ = IsForceSigninEnabled();
+  is_force_signin_enabled_ = signin_util::IsForceSigninEnabled();
   if (!IsAuthenticated() && is_force_signin_enabled_)
     is_force_signin_profile_locked_ = true;
 }
@@ -242,7 +233,10 @@
 
 void ProfileAttributesEntry::LockForceSigninProfile(bool is_lock) {
   DCHECK(is_force_signin_enabled_);
+  if (is_force_signin_profile_locked_ == is_lock)
+    return;
   is_force_signin_profile_locked_ = is_lock;
+  profile_info_cache_->NotifyIsSigninRequiredChanged(profile_path_);
 }
 
 void ProfileAttributesEntry::SetIsEphemeral(bool value) {
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
index b789da4..fc1ef5d 100644
--- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc
+++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -12,12 +12,17 @@
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/supervised_user/supervised_user_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::Mock;
+using ::testing::_;
+
 namespace {
 // The ProfileMetadataEntry accessors aren't just plain old accessors to local
 // members so they'll be tested. The following helpers will make the testing
@@ -132,6 +137,13 @@
   content::TestBrowserThreadBundle thread_bundle_;
 };
 
+class ProfileAttributesTestObserver
+    : public ProfileAttributesStorage::Observer {
+ public:
+  MOCK_METHOD1(OnProfileSigninRequiredChanged,
+               void(const base::FilePath& profile_path));
+};
+
 TEST_F(ProfileAttributesStorageTest, ProfileNotFound) {
   EXPECT_EQ(0U, storage()->GetNumberOfProfiles());
 
@@ -436,3 +448,30 @@
               storage()->ChooseAvatarIconIndexForNewProfile());
   }
 }
+
+TEST_F(ProfileAttributesStorageTest, ProfileForceSigninLock) {
+  signin_util::SetForceSigninForTesting(true);
+  ProfileAttributesTestObserver observer;
+  ProfileAttributesEntry* entry;
+
+  AddTestingProfile();
+  ASSERT_TRUE(storage()->GetProfileAttributesWithPath(
+      GetProfilePath("testing_profile_path0"), &entry));
+  storage()->AddObserver(&observer);
+  ASSERT_FALSE(entry->IsSigninRequired());
+
+  EXPECT_CALL(observer, OnProfileSigninRequiredChanged(_)).Times(0);
+  entry->LockForceSigninProfile(false);
+  ASSERT_FALSE(entry->IsSigninRequired());
+  Mock::VerifyAndClear(&observer);
+
+  EXPECT_CALL(observer, OnProfileSigninRequiredChanged(_)).Times(1);
+  entry->LockForceSigninProfile(true);
+  ASSERT_TRUE(entry->IsSigninRequired());
+  Mock::VerifyAndClear(&observer);
+
+  EXPECT_CALL(observer, OnProfileSigninRequiredChanged(_)).Times(1);
+  entry->SetIsSigninRequired(false);
+  ASSERT_FALSE(entry->IsSigninRequired());
+  Mock::VerifyAndClear(&observer);
+}
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index 7249a7d..7707f2b 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -792,10 +792,7 @@
   info->SetBoolean(kSigninRequiredKey, value);
   // This takes ownership of |info|.
   SetInfoForProfileAtIndex(index, info.release());
-
-  base::FilePath profile_path = GetPathOfProfileAtIndex(index);
-  for (auto& observer : observer_list_)
-    observer.OnProfileSigninRequiredChanged(profile_path);
+  NotifyIsSigninRequiredChanged(GetPathOfProfileAtIndex(index));
 }
 
 void ProfileInfoCache::SetProfileIsEphemeralAtIndex(size_t index, bool value) {
@@ -890,6 +887,12 @@
   SetInfoForProfileAtIndex(index, info.release());
 }
 
+void ProfileInfoCache::NotifyIsSigninRequiredChanged(
+    const base::FilePath& profile_path) {
+  for (auto& observer : observer_list_)
+    observer.OnProfileSigninRequiredChanged(profile_path);
+}
+
 const base::FilePath& ProfileInfoCache::GetUserDataDir() const {
   return user_data_dir_;
 }
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index bd700a7..08ae3ed 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -152,6 +152,9 @@
   void SetStatsBookmarksOfProfileAtIndex(size_t index, int value);
   void SetStatsSettingsOfProfileAtIndex(size_t index, int value);
 
+  // Notify IsSignedInRequired to all observer
+  void NotifyIsSigninRequiredChanged(const base::FilePath& profile_path);
+
   const base::FilePath& GetUserDataDir() const;
 
   // Register cache related preferences in Local State.
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 014877c..0c4229c8 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -51,6 +51,7 @@
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -336,6 +337,14 @@
 }
 #endif
 
+#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+void SignOut(SigninManager* signin_manager) {
+  signin_manager->SignOut(
+      signin_metrics::AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN,
+      signin_metrics::SignoutDelete::IGNORE_METRIC);
+}
+#endif
+
 }  // namespace
 
 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
@@ -1564,8 +1573,21 @@
     bool has_entry = storage.GetProfileAttributesWithPath(profile->GetPath(),
                                                           &entry);
     if (has_entry) {
+#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+      bool was_authenticated_status = entry->IsAuthenticated();
+#endif
       // The ProfileAttributesStorage's info must match the Signin Manager.
       entry->SetAuthInfo(account_info.gaia, username);
+#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+      // Sign out if force-sign-in policy is enabled and profile is not signed
+      // in.
+      if (signin_util::IsForceSigninEnabled() && was_authenticated_status &&
+          !entry->IsAuthenticated()) {
+        BrowserThread::PostTask(
+            BrowserThread::UI, FROM_HERE,
+            base::Bind(&SignOut, static_cast<SigninManager*>(signin_manager)));
+      }
+#endif
       return;
     }
   }
diff --git a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
index af8851a..37bc620 100644
--- a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -186,10 +186,11 @@
       'dependencies': [
         '../compiled_resources2.gyp:route',
         '../settings_page/compiled_resources2.gyp:settings_animated_pages',
-        'sync_browser_proxy',
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+        'sync_browser_proxy',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index b7bd67fb..f08e94f 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -32,6 +32,12 @@
         margin-top: 20px;
       }
 
+      #existingPassphrase {
+        /* This particular list frame is not indented. */
+        -webkit-padding-start: var(--settings-box-row-padding);
+        border-bottom: var(--settings-separator-line);
+      }
+
       #existingPassphraseContainer,
       #passphraseRecoverHint {
         align-items: center;
@@ -62,6 +68,37 @@
     </div>
     <div id="[[pages.CONFIGURE]]"
         hidden$="[[!isStatus_(pages.CONFIGURE, pageStatus_)]]">
+      <template is="dom-if" if="[[syncPrefs.passphraseRequired]]">
+        <div id="existingPassphrase" class="list-frame">
+          <div class="list-item">
+            <span>
+              [[enterPassphrasePrompt_(syncPrefs.passphraseTypeIsCustom)]]
+              <a href="$i18nRaw{syncErrorHelpUrl}" target="_blank">
+                $i18n{learnMore}
+              </a>
+            </span>
+          </div>
+          <div id="existingPassphraseContainer" class="list-item">
+            <paper-input id="existingPassphraseInput" type="password"
+                value="{{existingPassphrase_}}"
+                placeholder="$i18n{passphrasePlaceholder}"
+                error-message="$i18n{incorrectPassphraseError}">
+              <iron-a11y-keys id="keys" keys="enter"
+                  on-keys-pressed="onSubmitExistingPassphraseTap_">
+              </iron-a11y-keys>
+            </paper-input>
+            <paper-button id="submitExistingPassphrase"
+                on-tap="onSubmitExistingPassphraseTap_" class="action-button"
+                disabled="[[!existingPassphrase_]]">
+              $i18n{submitPassphraseButton}
+            </paper-button>
+          </div>
+          <div id="passphraseRecoverHint" class="list-item">
+            <span>$i18nRaw{passphraseRecover}</span>
+          </div>
+        </div>
+      </template>
+
       <div class="settings-box first">
         <div id="syncEverythingCheckboxLabel" class="start">
           $i18n{syncEverythingCheckboxLabel}
@@ -225,7 +262,8 @@
             aria-describedby="manageSyncedDataSecondary"></button>
       </div>
 
-      <div class="settings-box two-line single-column">
+      <div id="encryptionDescription" hidden="[[syncPrefs.passphraseRequired]]"
+          class="settings-box two-line single-column">
         <div>$i18n{encryptionOptionsTitle}</div>
         <div class="secondary">$i18n{syncDataEncryptedText}</div>
       </div>
@@ -286,37 +324,6 @@
           </div>
         </div>
       </template>
-
-      <template is="dom-if" if="[[syncPrefs.passphraseRequired]]">
-        <div class="list-frame">
-          <div class="list-item">
-            <span>
-              [[enterPassphrasePrompt_(syncPrefs.passphraseTypeIsCustom)]]
-              <a href="$i18nRaw{syncErrorHelpUrl}" target="_blank">
-                $i18n{learnMore}
-              </a>
-            </span>
-          </div>
-          <div id="existingPassphraseContainer" class="list-item">
-            <paper-input id="existingPassphraseInput" type="password"
-                value="{{existingPassphrase_}}"
-                placeholder="$i18n{passphrasePlaceholder}"
-                error-message="$i18n{incorrectPassphraseError}">
-              <iron-a11y-keys id="keys" keys="enter"
-                  on-keys-pressed="onSubmitExistingPassphraseTap_">
-              </iron-a11y-keys>
-            </paper-input>
-            <paper-button id="submitExistingPassphrase"
-                on-tap="onSubmitExistingPassphraseTap_" class="action-button"
-                disabled="[[!existingPassphrase_]]">
-              $i18n{submitPassphraseButton}
-            </paper-button>
-          </div>
-          <div id="passphraseRecoverHint" class="list-item">
-            <span>$i18nRaw{passphraseRecover}</span>
-          </div>
-        </div>
-      </template>
     </div>
   </template>
   <script src="sync_page.js"></script>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js
index b22155de..37d603b 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -225,6 +225,16 @@
     // Hide the new passphrase box if the sync data has been encrypted.
     if (this.syncPrefs.encryptAllData)
       this.creatingNewPassphrase_ = false;
+
+    // Focus the password input box if password is needed to start sync.
+    if (this.syncPrefs.passphraseRequired) {
+      // Async to allow the dom-if templates to render first.
+      this.async(function() {
+        var input = /** @type {!PaperInputElement} */ (
+            this.$$('#existingPassphraseInput'));
+        input.inputElement.focus();
+      }.bind(this));
+    }
   },
 
   /**
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index afc0aa9..cc6fb7c 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -133,8 +133,7 @@
         </iron-icon></paper-button>
       <iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
           hidden="[[!pageVisibility.advancedSettings]]">
-        <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
-            on-iron-activate="onSelectorActivate_">
+        <iron-selector id="subMenu" selectable="a" attr-for-selected="href">
 <if expr="chromeos">
           <a href="/dateTime">
             <iron-icon icon="settings:access-time"></iron-icon>
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 3a30291d3..584775e 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -275,14 +275,20 @@
 #endif
 }
 
-void ChromeSigninClient::PreSignOut(const base::Callback<void()>& sign_out) {
+void ChromeSigninClient::PreSignOut(
+    const base::Callback<void()>& sign_out,
+    signin_metrics::ProfileSignout signout_source_metric) {
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
   if (is_force_signin_enabled_ && !profile_->IsSystemProfile() &&
       !profile_->IsGuestSession() && !profile_->IsSupervised()) {
+    // TODO(zmin): force window closing based on the reason of sign-out.
+    // This will be updated after force window closing CL is commited.
+
+    // User can't abort the window closing unless user sign out manually.
     BrowserList::CloseAllBrowsersWithProfile(
         profile_,
         base::Bind(&ChromeSigninClient::OnCloseBrowsersSuccess,
-                   base::Unretained(this), sign_out),
+                   base::Unretained(this), sign_out, signout_source_metric),
         base::Bind(&ChromeSigninClient::OnCloseBrowsersAborted,
                    base::Unretained(this)),
         false);
@@ -290,7 +296,7 @@
 #else
   {
 #endif
-    SigninClient::PreSignOut(sign_out);
+    SigninClient::PreSignOut(sign_out, signout_source_metric);
   }
 }
 
@@ -431,8 +437,9 @@
 
 void ChromeSigninClient::OnCloseBrowsersSuccess(
     const base::Callback<void()>& sign_out,
+    const signin_metrics::ProfileSignout signout_source_metric,
     const base::FilePath& profile_path) {
-  SigninClient::PreSignOut(sign_out);
+  SigninClient::PreSignOut(sign_out, signout_source_metric);
 
   LockForceSigninProfile(profile_path);
   // After sign out, lock the profile and show UserManager if necessary.
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index da0b0a22..10866bb 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -73,7 +73,9 @@
   void PostSignedIn(const std::string& account_id,
                     const std::string& username,
                     const std::string& password) override;
-  void PreSignOut(const base::Callback<void()>& sign_out) override;
+  void PreSignOut(
+      const base::Callback<void()>& sign_out,
+      signin_metrics::ProfileSignout signout_source_metric) override;
 
   // SigninErrorController::Observer implementation.
   void OnErrorChanged() override;
@@ -105,8 +107,10 @@
 
  private:
   void MaybeFetchSigninTokenHandle();
-  void OnCloseBrowsersSuccess(const base::Callback<void()>& sign_out,
-                              const base::FilePath& profile_path);
+  void OnCloseBrowsersSuccess(
+      const base::Callback<void()>& sign_out,
+      const signin_metrics::ProfileSignout signout_source_metric,
+      const base::FilePath& profile_path);
   void OnCloseBrowsersAborted(const base::FilePath& profile_path);
 
   Profile* profile_;
diff --git a/chrome/browser/signin/signin_util.cc b/chrome/browser/signin/signin_util.cc
new file mode 100644
index 0000000..e5f50790
--- /dev/null
+++ b/chrome/browser/signin/signin_util.cc
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/signin/signin_util.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
+
+namespace signin_util {
+namespace {
+
+enum ForceSigninPolicyCache {
+  NOT_CACHED = 0,
+  ENABLE,
+  DISABLE
+} g_is_force_signin_enabled_cache = NOT_CACHED;
+
+void SetForceSigninPolicy(bool enable) {
+  g_is_force_signin_enabled_cache = enable ? ENABLE : DISABLE;
+}
+
+}  // namespace
+
+bool IsForceSigninEnabled() {
+  if (g_is_force_signin_enabled_cache == NOT_CACHED) {
+    PrefService* prefs = g_browser_process->local_state();
+    if (prefs)
+      SetForceSigninPolicy(prefs->GetBoolean(prefs::kForceBrowserSignin));
+    else
+      return false;
+  }
+  return (g_is_force_signin_enabled_cache == ENABLE);
+}
+
+void SetForceSigninForTesting(bool enable) {
+  SetForceSigninPolicy(enable);
+}
+
+}  // namespace signin_util
diff --git a/chrome/browser/signin/signin_util.h b/chrome/browser/signin/signin_util.h
new file mode 100644
index 0000000..315fc63
--- /dev/null
+++ b/chrome/browser/signin/signin_util.h
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_
+#define CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_
+
+namespace signin_util {
+
+// Return whether the force sign in policy is enabled or not.
+// The state of this policy will not be changed without relaunch Chrome.
+bool IsForceSigninEnabled();
+
+// Enable or disable force sign in for testing.
+void SetForceSigninForTesting(bool enable);
+
+}  // namespace signin_util
+
+#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_H_
diff --git a/chrome/browser/signin/signin_util_unittest.cc b/chrome/browser/signin/signin_util_unittest.cc
new file mode 100644
index 0000000..d436f78
--- /dev/null
+++ b/chrome/browser/signin/signin_util_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/signin/signin_util.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+
+class SigninUtilTest : public BrowserWithTestWindowTest {
+ public:
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+
+    prefs_.reset(new TestingPrefServiceSimple());
+  }
+
+  void TearDown() override { BrowserWithTestWindowTest::TearDown(); }
+
+  std::unique_ptr<TestingPrefServiceSimple> prefs_;
+};
+
+TEST_F(SigninUtilTest, GetForceSigninPolicy) {
+  ASSERT_FALSE(signin_util::IsForceSigninEnabled());
+  chrome::RegisterLocalState(prefs_->registry());
+  TestingBrowserProcess::GetGlobal()->SetLocalState(prefs_.get());
+
+  g_browser_process->local_state()->SetBoolean(prefs::kForceBrowserSignin,
+                                               true);
+  ASSERT_TRUE(signin_util::IsForceSigninEnabled());
+  g_browser_process->local_state()->SetBoolean(prefs::kForceBrowserSignin,
+                                               false);
+  ASSERT_TRUE(signin_util::IsForceSigninEnabled());
+
+  TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
+}
diff --git a/chrome/browser/signin/token_revoker_test_utils.cc b/chrome/browser/signin/token_revoker_test_utils.cc
index 25add2de..a5b1967 100644
--- a/chrome/browser/signin/token_revoker_test_utils.cc
+++ b/chrome/browser/signin/token_revoker_test_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/signin/token_revoker_test_utils.h b/chrome/browser/signin/token_revoker_test_utils.h
index b8705c7..e60624a 100644
--- a/chrome/browser/signin/token_revoker_test_utils.h
+++ b/chrome/browser/signin/token_revoker_test_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
index 878e244..8509703 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.cc
@@ -7,16 +7,21 @@
 #include <memory>
 
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "ui/events/event_constants.h"
 
 ArcAppLauncher::ArcAppLauncher(content::BrowserContext* context,
                                const std::string& app_id,
-                               bool landscape_layout)
-    : context_(context), app_id_(app_id), landscape_layout_(landscape_layout) {
+                               bool landscape_layout,
+                               bool deferred_launch_allowed)
+    : context_(context),
+      app_id_(app_id),
+      landscape_layout_(landscape_layout),
+      deferred_launch_allowed_(deferred_launch_allowed) {
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context_);
   DCHECK(prefs);
 
   std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id_);
-  if (app_info && app_info->ready)
+  if (app_info && (app_info->ready || deferred_launch_allowed_))
     LaunchApp();
   else
     prefs->AddObserver(this);
@@ -34,12 +39,12 @@
 void ArcAppLauncher::OnAppRegistered(
     const std::string& app_id,
     const ArcAppListPrefs::AppInfo& app_info) {
-  if (app_id == app_id_ && app_info.ready)
+  if (app_id == app_id_ && (app_info.ready || deferred_launch_allowed_))
     LaunchApp();
 }
 
 void ArcAppLauncher::OnAppReadyChanged(const std::string& app_id, bool ready) {
-  if (app_id == app_id_ && ready)
+  if (app_id == app_id_ && (ready || deferred_launch_allowed_))
     LaunchApp();
 }
 
@@ -50,7 +55,7 @@
   DCHECK(prefs && prefs->GetApp(app_id_));
   prefs->RemoveObserver(this);
 
-  if (!arc::LaunchApp(context_, app_id_, landscape_layout_))
+  if (!arc::LaunchApp(context_, app_id_, landscape_layout_, ui::EF_NONE))
     VLOG(2) << "Failed to launch app: " + app_id_ + ".";
 
   app_launched_ = true;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_launcher.h b/chrome/browser/ui/app_list/arc/arc_app_launcher.h
index 613ad2bd..3043ff0c 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_launcher.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_launcher.h
@@ -20,7 +20,8 @@
  public:
   ArcAppLauncher(content::BrowserContext* context,
                  const std::string& app_id,
-                 bool landscape_layout);
+                 bool landscape_layout,
+                 bool deferred_launch_allowed);
   ~ArcAppLauncher() override;
 
   bool app_launched() const { return app_launched_; }
@@ -38,7 +39,11 @@
   // ARC app id and requested layout.
   const std::string app_id_;
   const bool landscape_layout_;
-  // Flag idicating that ARC app was launched.
+  // If it is set to true that means app is allowed to launch in deferred mode
+  // once it is registered, regardless it is ready or not. Otherwise app is
+  // launched when it becomes ready.
+  const bool deferred_launch_allowed_;
+  // Flag indicating that ARC app was launched.
   bool app_launched_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(ArcAppLauncher);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 294e5ed..7f0bb0b 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -854,7 +854,7 @@
   } else {
     AppInfo app_info(updated_name, package_name, activity, intent_uri,
                      icon_resource_id, base::Time(), GetInstallTime(app_id),
-                     sticky, notifications_enabled, true,
+                     sticky, notifications_enabled, app_ready,
                      launchable && arc::ShouldShowInLauncher(app_id), shortcut,
                      launchable, orientation_lock);
     for (auto& observer : observer_list_)
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc
index 94ad8c2..8fb88d3a 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -97,9 +97,8 @@
 
   arc_app_list_pref_ = ArcAppListPrefs::Get(profile_);
   DCHECK(arc_app_list_pref_);
-  base::RunLoop run_loop;
-  arc_app_list_pref_->SetDefaltAppsReadyCallback(run_loop.QuitClosure());
-  run_loop.Run();
+  if (wait_default_apps_)
+    WaitForDefaultApps();
 
   // Check initial conditions.
   if (arc::ShouldArcAlwaysStart()) {
@@ -115,6 +114,13 @@
       app_instance_.get());
 }
 
+void ArcAppTest::WaitForDefaultApps() {
+  DCHECK(arc_app_list_pref_);
+  base::RunLoop run_loop;
+  arc_app_list_pref_->SetDefaltAppsReadyCallback(run_loop.QuitClosure());
+  run_loop.Run();
+}
+
 void ArcAppTest::CreateFakeAppsAndPackages() {
   arc::mojom::AppInfo app;
   // Make sure we have enough data for test.
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.h b/chrome/browser/ui/app_list/arc/arc_app_test.h
index 8163acd..db1fa73 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_test.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_test.h
@@ -59,6 +59,8 @@
 
   void RemovePackage(const arc::mojom::ArcPackageInfo& package);
 
+  void WaitForDefaultApps();
+
   // The 0th item is sticky but not the followings.
   const std::vector<arc::mojom::AppInfo>& fake_apps() const {
     return fake_apps_;
@@ -85,6 +87,10 @@
     return arc_service_manager_.get();
   }
 
+  void set_wait_default_apps(bool wait_default_apps) {
+    wait_default_apps_ = wait_default_apps;
+  }
+
  private:
   const user_manager::User* CreateUserAndLogin();
   bool FindPackage(const arc::mojom::ArcPackageInfo& package);
@@ -95,6 +101,8 @@
 
   ArcAppListPrefs* arc_app_list_pref_ = nullptr;
 
+  bool wait_default_apps_ = true;
+
   std::unique_ptr<arc::ArcServiceManager> arc_service_manager_;
   std::unique_ptr<arc::ArcSessionManager> arc_session_manager_;
   std::unique_ptr<arc::ArcPlayStoreEnabledPreferenceHandler>
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index 4b35b2d..86d4af1 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -433,14 +433,31 @@
   // ArcAppModelBuilderTest:
   void OnBeforeArcTestSetup() override {
     ArcDefaultAppList::UseTestAppsDirectory();
+    arc_test()->set_wait_default_apps(IsWaitDefaultAppsNeeded());
     arc::ArcPackageSyncableServiceFactory::GetInstance()->SetTestingFactory(
         profile_.get(), nullptr);
   }
 
+  // Returns true if test needs to wait for default apps on setup.
+  virtual bool IsWaitDefaultAppsNeeded() const { return true; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ArcDefaulAppTest);
 };
 
+class ArcAppLauncherForDefaulAppTest : public ArcDefaulAppTest {
+ public:
+  ArcAppLauncherForDefaulAppTest() = default;
+  ~ArcAppLauncherForDefaulAppTest() override = default;
+
+ protected:
+  // ArcDefaulAppTest:
+  bool IsWaitDefaultAppsNeeded() const override { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ArcAppLauncherForDefaulAppTest);
+};
+
 class ArcPlayStoreAppTest : public ArcDefaulAppTest {
  public:
   ArcPlayStoreAppTest() = default;
@@ -1271,11 +1288,11 @@
   const std::string id2 = ArcAppTest::GetAppId(app2);
   const std::string id3 = ArcAppTest::GetAppId(app3);
 
-  ArcAppLauncher launcher1(profile(), id1, true);
+  ArcAppLauncher launcher1(profile(), id1, true, false);
   EXPECT_FALSE(launcher1.app_launched());
   EXPECT_TRUE(prefs->HasObserver(&launcher1));
 
-  ArcAppLauncher launcher3(profile(), id3, true);
+  ArcAppLauncher launcher3(profile(), id3, true, false);
   EXPECT_FALSE(launcher1.app_launched());
   EXPECT_TRUE(prefs->HasObserver(&launcher1));
   EXPECT_FALSE(launcher3.app_launched());
@@ -1294,7 +1311,7 @@
   EXPECT_FALSE(prefs->HasObserver(&launcher1));
   EXPECT_TRUE(prefs->HasObserver(&launcher3));
 
-  ArcAppLauncher launcher2(profile(), id2, true);
+  ArcAppLauncher launcher2(profile(), id2, true, false);
   EXPECT_TRUE(launcher2.app_launched());
   EXPECT_FALSE(prefs->HasObserver(&launcher2));
   ASSERT_EQ(2u, app_instance()->launch_requests().size());
@@ -1439,6 +1456,37 @@
   }
 }
 
+TEST_P(ArcAppLauncherForDefaulAppTest, AppLauncherForDefaultApps) {
+  ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
+  ASSERT_NE(nullptr, prefs);
+
+  ASSERT_GE(fake_default_apps().size(), 2U);
+  const arc::mojom::AppInfo& app1 = fake_default_apps()[0];
+  const arc::mojom::AppInfo& app2 = fake_default_apps()[1];
+  const std::string id1 = ArcAppTest::GetAppId(app1);
+  const std::string id2 = ArcAppTest::GetAppId(app2);
+
+  // Launch when app is registered and ready.
+  ArcAppLauncher launcher1(profile(), id1, true, false);
+  // Launch when app is registered.
+  ArcAppLauncher launcher2(profile(), id2, true, true);
+
+  EXPECT_FALSE(launcher1.app_launched());
+  EXPECT_FALSE(launcher2.app_launched());
+
+  arc_test()->WaitForDefaultApps();
+
+  // Only second app is expected to be launched.
+  EXPECT_FALSE(launcher1.app_launched());
+  EXPECT_TRUE(launcher2.app_launched());
+
+  app_instance()->RefreshAppList();
+  app_instance()->SendRefreshAppList(fake_default_apps());
+  // Default apps are ready now and it is expected that first app was launched
+  // now.
+  EXPECT_TRUE(launcher1.app_launched());
+}
+
 TEST_P(ArcDefaulAppTest, DefaultAppsNotAvailable) {
   ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
   ASSERT_NE(nullptr, prefs);
@@ -1528,6 +1576,9 @@
                         ArcDefaulAppTest,
                         ::testing::ValuesIn(kUnmanagedArcStates));
 INSTANTIATE_TEST_CASE_P(,
+                        ArcAppLauncherForDefaulAppTest,
+                        ::testing::ValuesIn(kUnmanagedArcStates));
+INSTANTIATE_TEST_CASE_P(,
                         ArcDefaulAppForManagedUserTest,
                         ::testing::ValuesIn(kManagedArcStates));
 INSTANTIATE_TEST_CASE_P(,
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h
index e091173..8c75cb96 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -43,6 +43,8 @@
 
 // Launch an app with given layout and let the system decides how big and where
 // to place it.
+// TODO (khmel) replace bool for |landscape_layout| with enum class in order
+// to prevent using another LaunchApp with different signature mistakenly.
 bool LaunchApp(content::BrowserContext* context,
                const std::string& app_id,
                bool landscape_layout,
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber_unittest.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber_unittest.cc
index 465c770..45a009f 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber_unittest.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
 
-#include "ash/common/accelerators/accelerator_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/bind.h"
diff --git a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
index 9f445f5..cfc048a 100644
--- a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.cc
@@ -6,11 +6,11 @@
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/arc/arc_support_host.h"
-#include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_launcher.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
+#include "ui/events/event_constants.h"
 
 ArcPlaystoreShortcutLauncherItemController::
     ArcPlaystoreShortcutLauncherItemController(
@@ -27,15 +27,8 @@
     int64_t display_id,
     ash::ShelfLaunchSource source,
     const ItemSelectedCallback& callback) {
-  Profile* profile = controller()->profile();
-  ArcAppListPrefs* arc_app_prefs = ArcAppListPrefs::Get(profile);
-  DCHECK(arc_app_prefs);
-
-  // Play Store should always be registered and arc::LaunchApp can handle all
-  // cases.
-  DCHECK(arc_app_prefs->IsRegistered(arc::kPlayStoreAppId));
-  arc::LaunchApp(profile, arc::kPlayStoreAppId, true);
-
+  playstore_launcher_ = base::MakeUnique<ArcAppLauncher>(
+      controller()->profile(), arc::kPlayStoreAppId, true, true);
   callback.Run(ash::SHELF_ACTION_NONE,
                GetAppMenuItems(event ? event->flags() : ui::EF_NONE));
 }
diff --git a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.h
index ce1ad68a..84322f0 100644
--- a/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/arc_playstore_shortcut_launcher_item_controller.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h"
 
+class ArcAppLauncher;
 class ChromeLauncherController;
 
 class ArcPlaystoreShortcutLauncherItemController
@@ -26,6 +27,8 @@
                     const ItemSelectedCallback& callback) override;
 
  private:
+  std::unique_ptr<ArcAppLauncher> playstore_launcher_;
+
   DISALLOW_COPY_AND_ASSIGN(ArcPlaystoreShortcutLauncherItemController);
 };
 
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
index 647ac32..525b426 100644
--- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
@@ -129,8 +129,10 @@
     const std::string autofill_card_type =
         autofill::data_util::GetCardTypeForBasicCardPaymentType(
             supported_network);
-    std::unique_ptr<views::ImageView> card_icon_view =
-        CreateCardIconView(autofill_card_type);
+    std::unique_ptr<views::ImageView> card_icon_view = CreateInstrumentIconView(
+        autofill::data_util::GetPaymentRequestData(autofill_card_type)
+            .icon_resource_id,
+        base::UTF8ToUTF16(supported_network));
     card_icon_view->SetImageSize(kCardIconSize);
 
     icons_row->AddChildView(card_icon_view.release());
diff --git a/chrome/browser/ui/views/payments/payment_method_view_controller.cc b/chrome/browser/ui/views/payments/payment_method_view_controller.cc
index 1cf6cc90..b8a73452 100644
--- a/chrome/browser/ui/views/payments/payment_method_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_method_view_controller.cc
@@ -14,9 +14,8 @@
 #include "chrome/browser/ui/views/payments/payment_request_row_view.h"
 #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/autofill/core/browser/autofill_type.h"
-#include "components/autofill/core/browser/credit_card.h"
 #include "components/payments/content/payment_request_state.h"
+#include "components/payments/core/payment_instrument.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -42,16 +41,16 @@
 
 class PaymentMethodListItem : public payments::PaymentRequestItemList::Item {
  public:
-  // Does not take ownership of |card|, which  should not be null and should
-  // outlive this object. |list| is the PaymentRequestItemList object that will
-  // own this.
-  PaymentMethodListItem(autofill::CreditCard* card,
+  // Does not take ownership of |instrument|, which  should not be null and
+  // should outlive this object. |list| is the PaymentRequestItemList object
+  // that will own this.
+  PaymentMethodListItem(PaymentInstrument* instrument,
                         PaymentRequestSpec* spec,
                         PaymentRequestState* state,
                         PaymentRequestItemList* list,
                         bool selected)
       : payments::PaymentRequestItemList::Item(spec, state, list, selected),
-        card_(card) {}
+        instrument_(instrument) {}
   ~PaymentMethodListItem() override {}
 
  private:
@@ -100,11 +99,9 @@
         views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
     card_info_container->SetLayoutManager(box_layout.release());
 
+    card_info_container->AddChildView(new views::Label(instrument_->label()));
     card_info_container->AddChildView(
-        new views::Label(card_->TypeAndLastFourDigits()));
-    card_info_container->AddChildView(new views::Label(
-        card_->GetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
-                       g_browser_process->GetApplicationLocale())));
+        new views::Label(instrument_->sublabel()));
     // TODO(anthonyvd): Add the "card is incomplete" label once the
     // completedness logic is implemented.
     layout->AddView(card_info_container.release());
@@ -112,8 +109,8 @@
     checkmark_ = CreateCheckmark(selected());
     layout->AddView(checkmark_.get());
 
-    std::unique_ptr<views::ImageView> card_icon_view =
-        CreateCardIconView(card_->type());
+    std::unique_ptr<views::ImageView> card_icon_view = CreateInstrumentIconView(
+        instrument_->icon_resource_id(), instrument_->label());
     card_icon_view->SetImageSize(gfx::Size(32, 20));
     layout->AddView(card_icon_view.release());
 
@@ -126,7 +123,7 @@
     if (checkmark_)
       checkmark_->SetVisible(selected());
 
-    state()->SetSelectedCreditCard(card_);
+    state()->SetSelectedInstrument(instrument_);
   }
 
   // views::ButtonListener:
@@ -145,7 +142,7 @@
     return true;
   }
 
-  autofill::CreditCard* card_;
+  PaymentInstrument* instrument_;
   std::unique_ptr<views::ImageView> checkmark_;
 
   DISALLOW_COPY_AND_ASSIGN(PaymentMethodListItem);
@@ -158,14 +155,15 @@
     PaymentRequestState* state,
     PaymentRequestDialogView* dialog)
     : PaymentRequestSheetController(spec, state, dialog) {
-  const std::vector<autofill::CreditCard*>& available_cards =
-      state->credit_cards();
+  const std::vector<std::unique_ptr<PaymentInstrument>>& available_instruments =
+      state->available_instruments();
 
-  for (autofill::CreditCard* card : available_cards) {
+  for (const std::unique_ptr<PaymentInstrument>& instrument :
+       available_instruments) {
     std::unique_ptr<PaymentMethodListItem> item =
         base::MakeUnique<PaymentMethodListItem>(
-            card, spec, state, &payment_method_list_,
-            card == state->selected_credit_card());
+            instrument.get(), spec, state, &payment_method_list_,
+            instrument.get() == state->selected_instrument());
     payment_method_list_.AddItem(std::move(item));
   }
 }
diff --git a/chrome/browser/ui/views/payments/payment_method_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/payment_method_view_controller_browsertest.cc
index 4cd3feb..d1beb30 100644
--- a/chrome/browser/ui/views/payments/payment_method_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/payment_method_view_controller_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/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_test_utils.h"
@@ -39,15 +40,16 @@
   InvokePaymentRequestUI();
   OpenPaymentMethodScreen();
 
-  PaymentRequest* request = GetPaymentRequests(GetActiveWebContents())[0];
-  EXPECT_EQ(1U, request->state()->credit_cards().size());
+  PaymentRequest* request = GetPaymentRequests(GetActiveWebContents()).front();
+  EXPECT_EQ(1U, request->state()->available_instruments().size());
 
   views::View* list_view = dialog_view()->GetViewByID(
       static_cast<int>(DialogViewID::PAYMENT_METHOD_SHEET_LIST_VIEW));
   EXPECT_TRUE(list_view);
   EXPECT_EQ(1, list_view->child_count());
 
-  EXPECT_EQ(card, *request->state()->selected_credit_card());
+  EXPECT_EQ(request->state()->available_instruments().front().get(),
+            request->state()->selected_instrument());
   views::View* checkmark_view = list_view->child_at(0)->GetViewByID(
       static_cast<int>(DialogViewID::CHECKMARK_VIEW));
   EXPECT_TRUE(checkmark_view->visible());
@@ -60,23 +62,27 @@
   card1.set_use_count(5U);
   AddCreditCard(card1);
 
-  autofill::CreditCard card2 = autofill::test::GetCreditCard2();
+  // Slightly different visa.
+  autofill::CreditCard card2 = autofill::test::GetCreditCard();
+  card2.SetNumber(base::ASCIIToUTF16("4111111111111112"));
   card2.set_use_count(1U);
   AddCreditCard(card2);
 
   InvokePaymentRequestUI();
   OpenPaymentMethodScreen();
 
-  PaymentRequest* request = GetPaymentRequests(GetActiveWebContents())[0];
-  EXPECT_EQ(2U, request->state()->credit_cards().size());
-  EXPECT_EQ(card1, *request->state()->selected_credit_card());
+  PaymentRequest* request = GetPaymentRequests(GetActiveWebContents()).front();
+  EXPECT_EQ(2U, request->state()->available_instruments().size());
+  EXPECT_EQ(request->state()->available_instruments().front().get(),
+            request->state()->selected_instrument());
 
   views::View* list_view = dialog_view()->GetViewByID(
       static_cast<int>(DialogViewID::PAYMENT_METHOD_SHEET_LIST_VIEW));
   EXPECT_TRUE(list_view);
   EXPECT_EQ(2, list_view->child_count());
 
-  EXPECT_EQ(card1, *request->state()->selected_credit_card());
+  EXPECT_EQ(request->state()->available_instruments().front().get(),
+            request->state()->selected_instrument());
   views::View* checkmark_view = list_view->child_at(0)->GetViewByID(
       static_cast<int>(DialogViewID::CHECKMARK_VIEW));
   EXPECT_TRUE(checkmark_view->visible());
@@ -88,14 +94,16 @@
   // Simulate selecting the second card.
   ClickOnDialogViewAndWait(list_view->child_at(1));
 
-  EXPECT_EQ(card2, *request->state()->selected_credit_card());
+  EXPECT_EQ(request->state()->available_instruments().back().get(),
+            request->state()->selected_instrument());
   EXPECT_FALSE(checkmark_view->visible());
   EXPECT_TRUE(checkmark_view2->visible());
 
   // Clicking on the second card again should not modify any state.
   ClickOnDialogViewAndWait(list_view->child_at(1));
 
-  EXPECT_EQ(card2, *request->state()->selected_credit_card());
+  EXPECT_EQ(request->state()->available_instruments().back().get(),
+            request->state()->selected_instrument());
   EXPECT_FALSE(checkmark_view->visible());
   EXPECT_TRUE(checkmark_view2->visible());
 }
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 4e3a9b4..1b8cb04 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -170,18 +170,16 @@
   return container;
 }
 
-std::unique_ptr<views::ImageView> CreateCardIconView(
-    const std::string& card_type) {
+std::unique_ptr<views::ImageView> CreateInstrumentIconView(
+    int icon_resource_id,
+    const base::string16& tooltip_text) {
   std::unique_ptr<views::ImageView> card_icon_view =
       base::MakeUnique<views::ImageView>();
   card_icon_view->set_can_process_events_within_subtree(false);
-  card_icon_view->SetImage(
-      ResourceBundle::GetSharedInstance()
-          .GetImageNamed(autofill::data_util::GetPaymentRequestData(card_type)
-                             .icon_resource_id)
-          .AsImageSkia());
-  card_icon_view->SetTooltipText(
-      autofill::CreditCard::TypeForDisplay(card_type));
+  card_icon_view->SetImage(ResourceBundle::GetSharedInstance()
+                               .GetImageNamed(icon_resource_id)
+                               .AsImageSkia());
+  card_icon_view->SetTooltipText(tooltip_text);
   card_icon_view->SetBorder(views::CreateRoundedRectBorder(
       1, 3, card_icon_view->GetNativeTheme()->GetSystemColor(
                 ui::NativeTheme::kColorId_UnfocusedBorderColor)));
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.h b/chrome/browser/ui/views/payments/payment_request_views_util.h
index 69aad15..be1882b 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.h
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.h
@@ -55,10 +55,12 @@
     const base::string16& title,
     views::VectorIconButtonDelegate* delegate);
 
-// Returns a card image view for the given |card_type|. Includes a rounded rect
-// border. Callers need to set the size of the resulting ImageView.
-std::unique_ptr<views::ImageView> CreateCardIconView(
-    const std::string& card_type);
+// Returns an instrument image view for the given |icon_resource_id|. Includes
+// a rounded rect border. Callers need to set the size of the resulting
+// ImageView. Callers should set a |tooltip_text|.
+std::unique_ptr<views::ImageView> CreateInstrumentIconView(
+    int icon_resource_id,
+    const base::string16& tooltip_text);
 
 // Represents formatting options for each of the different contexts in which an
 // Address label may be displayed.
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
index fbb6a8d..a2cf94c 100644
--- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -23,13 +23,12 @@
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
-#include "components/autofill/core/browser/autofill_type.h"
-#include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/content/payment_request_state.h"
 #include "components/payments/core/currency_formatter.h"
+#include "components/payments/core/payment_instrument.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -438,11 +437,11 @@
 // +----------------------------------------------+
 std::unique_ptr<views::Button>
 PaymentSheetViewController::CreatePaymentMethodRow() {
-  autofill::CreditCard* selected_card = state()->selected_credit_card();
+  PaymentInstrument* selected_instrument = state()->selected_instrument();
 
   std::unique_ptr<views::View> content_view;
   std::unique_ptr<views::ImageView> card_icon_view;
-  if (selected_card) {
+  if (selected_instrument) {
     content_view = base::MakeUnique<views::View>();
 
     views::GridLayout* layout = new views::GridLayout(content_view.get());
@@ -452,14 +451,12 @@
                        1, views::GridLayout::USE_PREF, 0, 0);
 
     layout->StartRow(0, 0);
-    layout->AddView(new views::Label(selected_card->TypeAndLastFourDigits()));
+    layout->AddView(new views::Label(selected_instrument->label()));
     layout->StartRow(0, 0);
-    layout->AddView(new views::Label(
-        selected_card->GetInfo(
-            autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
-            g_browser_process->GetApplicationLocale())));
+    layout->AddView(new views::Label(selected_instrument->sublabel()));
 
-    card_icon_view = CreateCardIconView(selected_card->type());
+    card_icon_view = CreateInstrumentIconView(
+        selected_instrument->icon_resource_id(), selected_instrument->label());
     card_icon_view->SetImageSize(gfx::Size(32, 20));
   }
 
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index 539491f..bc057b4 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -181,15 +181,13 @@
   BackgroundColorHoverButton(ProfileChooserView* profile_chooser_view,
                              const base::string16& text)
       : views::LabelButton(profile_chooser_view, text),
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-        profile_chooser_view_(profile_chooser_view),
-#endif
         title_(nullptr),
         subtitle_(nullptr) {
     DCHECK(profile_chooser_view);
     SetImageLabelSpacing(kMenuEdgeMargin - 2);
     SetBorder(views::CreateEmptyBorder(0, kMenuEdgeMargin, 0, kMenuEdgeMargin));
     SetFocusForPlatform();
+    SetFocusPainter(nullptr);
 
     label()->SetHandlesTooltips(false);
   }
@@ -217,73 +215,64 @@
 
  private:
   // views::View:
-  void OnNativeThemeChanged(const ui::NativeTheme* theme) override {
-    // The first time the theme changes, the state will not be hovered
-    // or pressed and the colors will be initialized.  It's okay to
-    // reset the colors when the theme changes and the button is NOT
-    // hovered or pressed because the labels will be in a normal state.
-    if (state() == STATE_HOVERED || state() == STATE_PRESSED)
-      return;
+  void OnFocus() override {
+    LabelButton::OnFocus();
+    UpdateColors();
+  }
 
+  void OnBlur() override {
+    LabelButton::OnBlur();
+    UpdateColors();
+  }
+
+  void OnNativeThemeChanged(const ui::NativeTheme* theme) override {
     LabelButton::OnNativeThemeChanged(theme);
-    views::Label* title = title_ ? title_ : label();
-    normal_title_color_ = title->enabled_color();
-    if (subtitle_)
-      normal_subtitle_color_ = subtitle_->disabled_color();
+    UpdateColors();
   }
 
   // views::CustomButton:
   void StateChanged(ButtonState old_state) override {
     LabelButton::StateChanged(old_state);
 
-    auto set_title_color = [&](SkColor color) {
-      if (title_)
-        title_->SetEnabledColor(color);
-      else
-        SetEnabledTextColors(color);
-    };
+    // As in a menu, focus follows the mouse (including blurring when the mouse
+    // leaves the button). If we don't do this, the focused view and the hovered
+    // view might both have the selection highlight.
+    if (state() == STATE_HOVERED || state() == STATE_PRESSED)
+      RequestFocus();
+    else if (state() == STATE_NORMAL && HasFocus())
+      GetFocusManager()->SetFocusedView(nullptr);
 
-    bool was_prelight =
-        old_state == STATE_HOVERED || old_state == STATE_PRESSED;
-    bool is_prelight = state() == STATE_HOVERED || state() == STATE_PRESSED;
-    if (was_prelight && !is_prelight) {
-      // The pointer is no longer over this button.  Set the
-      // background and text colors back to their normal states.
-      set_background(nullptr);
-      set_title_color(normal_title_color_);
-      if (subtitle_)
-        subtitle_->SetDisabledColor(normal_subtitle_color_);
-    } else if (!was_prelight && is_prelight) {
-      // The pointer moved over this button.  Set the background and
-      // text colors back to their hovered states.
-      SkColor bg_color = profiles::kHoverColor;
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-      if (ThemeServiceFactory::GetForProfile(
-              profile_chooser_view_->browser()->profile())
-              ->UsingSystemTheme()) {
-        // When using the system (GTK) theme, use the selected menuitem colors.
-        bg_color = GetNativeTheme()->GetSystemColor(
-            ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor);
-        SkColor text_color = GetNativeTheme()->GetSystemColor(
-            ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor);
-        set_title_color(text_color);
-        if (subtitle_)
-          subtitle_->SetDisabledColor(text_color);
-      }
-#endif
-      set_background(views::Background::CreateSolidBackground(bg_color));
+    UpdateColors();
+  }
+
+  void UpdateColors() {
+    bool is_selected = HasFocus();
+
+    set_background(
+        is_selected
+            ? views::Background::CreateSolidBackground(
+                  GetNativeTheme()->GetSystemColor(
+                      ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor))
+            : nullptr);
+
+    SkColor text_color = GetNativeTheme()->GetSystemColor(
+        is_selected ? ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor
+                    : ui::NativeTheme::kColorId_LabelEnabledColor);
+    SetEnabledTextColors(text_color);
+    if (title_)
+      title_->SetEnabledColor(text_color);
+
+    if (subtitle_) {
+      DCHECK(!subtitle_->enabled());
+      subtitle_->SetDisabledColor(GetNativeTheme()->GetSystemColor(
+          is_selected
+              ? ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor
+              : ui::NativeTheme::kColorId_LabelDisabledColor));
     }
   }
 
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-  ProfileChooserView* profile_chooser_view_;
-#endif
-
   views::Label* title_;
-  SkColor normal_title_color_;
-
   views::Label* subtitle_;
-  SkColor normal_subtitle_color_;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundColorHoverButton);
 };
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index 142e598..6698269 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/profiles/profile_window.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/signin/local_auth.h"
+#include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -1010,12 +1011,16 @@
 
   // Unlock the profile after browser opens so startup can read the lock bit.
   // Any necessary authentication must have been successful to reach this point.
+  ProfileAttributesEntry* entry = nullptr;
   if (!browser->profile()->IsGuestSession()) {
-    ProfileAttributesEntry* entry = nullptr;
     bool has_entry = g_browser_process->profile_manager()->
         GetProfileAttributesStorage().
         GetProfileAttributesWithPath(browser->profile()->GetPath(), &entry);
     DCHECK(has_entry);
+    // If force sign in is enabled and profile is not signed in, do not close
+    // UserManager and unlock profile.
+    if (signin_util::IsForceSigninEnabled() && !entry->IsAuthenticated())
+      return;
     entry->SetIsSigninRequired(false);
   }
 
diff --git a/chrome/common/extensions/api/BUILD.gn b/chrome/common/extensions/api/BUILD.gn
index 031fea79..fb51030 100644
--- a/chrome/common/extensions/api/BUILD.gn
+++ b/chrome/common/extensions/api/BUILD.gn
@@ -89,6 +89,11 @@
 if (!is_android) {
   schema_sources += [ "processes.idl" ]
 }
+
+if (is_chromeos || is_mac || is_win) {
+  schema_sources += [ "networking_cast_private.idl" ]
+}
+
 if (is_chromeos) {
   schema_sources += [
     "certificate_provider.idl",
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index 1b53499c..858a45d 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -612,6 +612,11 @@
     "dependencies": ["permission:musicManagerPrivate"],
     "contexts": ["blessed_extension"]
   },
+  "networking.castPrivate": {
+    "channel": "stable",
+    "contexts": ["blessed_extension"],
+    "dependencies": ["permission:networking.castPrivate"]
+  },
   "notifications": {
     "dependencies": ["permission:notifications"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index d2eca346..86d2d69 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -507,6 +507,19 @@
     "channel": "stable",
     "extension_types": ["extension", "platform_app"]
   },
+  "networking.castPrivate": {
+    "channel": "stable",
+    "extension_types": ["extension", "platform_app"],
+    "platforms": ["chromeos", "mac", "win"],
+    "whitelist": [
+      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // http://crbug.com/588179
+      "FA01E0B81978950F2BC5A50512FD769725F57510",  // http://crbug.com/588179
+      "B11A93E7E5B541F8010245EBDE2C74647D6C14B9",  // http://crbug.com/588179
+      "F155646B5D1CA545F7E1E4E20D573DFDD44C2540",  // http://crbug.com/588179
+      "16CA7A47AAE4BE49B1E75A6B960C3875E945B264",  // http://crbug.com/588179
+      "226CF815E39A363090A1E547D53063472B8279FA"   // http://crbug.com/588179
+    ]
+  },
   "management": [
     {
       "channel": "stable",
diff --git a/chrome/common/extensions/api/networking_cast_private.idl b/chrome/common/extensions/api/networking_cast_private.idl
new file mode 100644
index 0000000..cc4335cd
--- /dev/null
+++ b/chrome/common/extensions/api/networking_cast_private.idl
@@ -0,0 +1,109 @@
+// 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.
+
+// The networking.castPrivate API is a private API that exposes networking
+// utilities needed by cast extension and setup app.
+[nodoc] namespace networking.castPrivate {
+  enum TDLSStatus {
+    // TDLS is connected.
+    CONNECTED,
+    // TDLS is not supported.
+    NONEXISTENT,
+    // TDLS is supported, but disabled.
+    DISABLED,
+    // TDLS is enabled, but not connected
+    DISCONNECTED,
+    // TDLS status is not yet determined.
+    UNKNOWN
+  };
+
+  dictionary VerificationProperties {
+    // A string containing a PEM-encoded (including the 'BEGIN CERTIFICATE'
+    // header and 'END CERTIFICATE' footer) X.509 certificate for use in
+    // verifying the signed data.
+    DOMString certificate;
+
+    // An array of PEM-encoded X.509 intermediate certificate authority
+    // certificates. Each PEM-encoded certificate is expected to have the
+    // 'BEGIN CERTIFICATE' header and 'END CERTIFICATE' footer.
+    DOMString[]? intermediateCertificates;
+
+    // A string containing a base64-encoded RSAPublicKey ASN.1 structure,
+    // representing the public key to be used by
+    // $(ref:verifyAndEncryptCredentials) and $(ref:verifyAndEncryptData)
+    // methods.
+    DOMString publicKey;
+
+    // A string containing a base64-encoded random binary data for use in
+    // verifying the signed data.
+    DOMString nonce;
+
+    // A string containing the identifying data string signed by the device.
+    DOMString signedData;
+
+    // A string containing the serial number of the device.
+    DOMString deviceSerial;
+
+    // A string containing the SSID of the device. Should be empty for new
+    // configurations.
+    DOMString deviceSsid;
+
+    // A string containing the BSSID of the device. Should be empty for new
+    // configurations.
+    DOMString deviceBssid;
+  };
+
+  callback BooleanCallback = void(boolean result);
+  callback StringCallback = void(DOMString result);
+  callback TDLSStatusCallback = void(TDLSStatus status);
+
+  interface Functions {
+    // Verifies that the device is a trusted device.
+    // |properties|: Properties of the destination to use in verifying that it
+    //     is a trusted device.
+    // |callback|: A callback function that indicates whether or not the device
+    //     is a trusted device.
+    static void verifyDestination(VerificationProperties properties,
+                                  BooleanCallback callback);
+
+    // Verifies that the device is a trusted device and retrieves encrypted
+    // network credentials.
+    // |properties|: Properties of the destination to use in verifying that it
+    //     is a trusted device.
+    // |networkGuid|: The GUID of the Cellular network to activate.
+    // |callback|: A callback function that receives base64-encoded encrypted
+    //     credential data to send to a trusted device.
+    static void verifyAndEncryptCredentials(VerificationProperties properties,
+                                            DOMString networkGuid,
+                                            StringCallback callback);
+
+    // Verifies that the device is a trusted device and encrypts supplied
+    // data with device public key.
+    // |properties|: Properties of the destination to use in verifying that it
+    //     is a trusted device.
+    // |data|: A string containing the base64-encoded data to encrypt.
+    // |callback|: A callback function that receives base64-encoded encrypted
+    //     data to send to a trusted device.
+    static void verifyAndEncryptData(VerificationProperties properties,
+                                     DOMString data,
+                                     StringCallback callback);
+
+    // Enables TDLS for WiFi traffic with a specified peer if available.
+    // |ip_or_mac_address|: The IP or MAC address of the peer with which to
+    //     enable a TDLS connection.
+    // |enabled|: If true, enable TDLS, otherwise disable TDLS.
+    // |callback|: A callback function that receives a string with an error or
+    //     the current TDLS status.
+    static void setWifiTDLSEnabledState(DOMString ip_or_mac_address,
+                                        boolean enabled,
+                                        optional TDLSStatusCallback callback);
+
+    // Returns the current TDLS status for the specified peer.
+    // |ip_or_mac_address|: The IP or MAC address of the peer.
+    // |callback|: A callback function that receives a string with the current
+    //     TDLS status.
+    static void getWifiTDLSStatus(DOMString ip_or_mac_address,
+                                  TDLSStatusCallback callback);
+  };
+};
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index fa08cada..3d361a7 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -139,6 +139,7 @@
        APIPermissionInfo::kFlagCannotBeOptional},
       {APIPermission::kMusicManagerPrivate, "musicManagerPrivate",
        APIPermissionInfo::kFlagCannotBeOptional},
+      {APIPermission::kNetworkingCastPrivate, "networking.castPrivate"},
       {APIPermission::kPreferencesPrivate, "preferencesPrivate",
        APIPermissionInfo::kFlagCannotBeOptional},
       {APIPermission::kSystemPrivate, "systemPrivate",
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 7e3d40d..fcba6a74 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -838,6 +838,7 @@
   skip.insert(APIPermission::kMediaPlayerPrivate);
   skip.insert(APIPermission::kMediaRouterPrivate);
   skip.insert(APIPermission::kMetricsPrivate);
+  skip.insert(APIPermission::kNetworkingCastPrivate);
   skip.insert(APIPermission::kPreferencesPrivate);
   skip.insert(APIPermission::kImageWriterPrivate);
   skip.insert(APIPermission::kResourcesPrivate);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 9719d1d3..ff00205 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2603,6 +2603,9 @@
         "../browser/profiles/profile_statistics_browsertest.cc",
       ]
     }
+    if (is_mac || is_win || is_chromeos) {
+      sources += [ "../browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc" ]
+    }
     if (enable_app_list) {
       sources += [
         "../browser/apps/drive/drive_app_converter_browsertest.cc",
@@ -4792,6 +4795,7 @@
       "../browser/media/webrtc/native_desktop_media_list_unittest.cc",
       "../browser/metrics/desktop_session_duration/desktop_session_duration_tracker_unittest.cc",
       "../browser/signin/signin_global_error_unittest.cc",
+      "../browser/signin/signin_util_unittest.cc",
       "../browser/ui/webui/signin/signin_create_profile_handler_unittest.cc",
       "../browser/ui/webui/signin/sync_confirmation_handler_unittest.cc",
       "../browser/upgrade_detector_impl_unittest.cc",
diff --git a/chrome/test/chromedriver/performance_logger.cc b/chrome/test/chromedriver/performance_logger.cc
index 5887650e..d7f61c54 100644
--- a/chrome/test/chromedriver/performance_logger.cc
+++ b/chrome/test/chromedriver/performance_logger.cc
@@ -199,7 +199,7 @@
     // 'value' will be between 0-1 and represents how full the DevTools trace
     // buffer is. If the buffer is full, warn the user.
     double buffer_usage = 0;
-    if (!params.GetDouble("value", &buffer_usage)) {
+    if (!params.GetDouble("percentFull", &buffer_usage)) {
       // Tracing.bufferUsage event will occur once per second, and it really
       // only serves as a warning, so if we can't reliably tell whether the
       // buffer is full, just fail silently instead of spamming the logs.
diff --git a/chrome/test/chromedriver/performance_logger_unittest.cc b/chrome/test/chromedriver/performance_logger_unittest.cc
index 0c906ec9..68168622 100644
--- a/chrome/test/chromedriver/performance_logger_unittest.cc
+++ b/chrome/test/chromedriver/performance_logger_unittest.cc
@@ -380,7 +380,7 @@
   client.AddListener(&logger);
   logger.OnConnected(&client);
   base::DictionaryValue params;
-  params.SetDouble("value", 1.0);
+  params.SetDouble("percentFull", 1.0);
   ASSERT_EQ(kOk, client.TriggerEvent("Tracing.bufferUsage", params).code());
 
   ASSERT_EQ(1u, log.GetEntries().size());
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index cd41f3e..4d4b5ea7 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -94,6 +94,8 @@
 _OS_SPECIFIC_FILTER['win'] = [
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=299
     'ChromeLogPathCapabilityTest.testChromeLogPath',
+    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=1712
+    'ChromeDownloadDirTest.*',
 ]
 _OS_SPECIFIC_FILTER['linux'] = [
     # Xvfb doesn't support maximization.
diff --git a/chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_onvrdisplayactivate.html b/chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_vrdisplayactivate.html
similarity index 96%
rename from chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_onvrdisplayactivate.html
rename to chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_vrdisplayactivate.html
index 4afac65..9a9f21a 100644
--- a/chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_onvrdisplayactivate.html
+++ b/chrome/test/data/android/webvr_instrumentation/html/test_nfc_fires_vrdisplayactivate.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <!--
 Tests that scanning the Daydream View NFC tag on supported devices fires the
-ondisplayactivate event
+vrdisplayactivate event
 -->
 <html>
   <head>
diff --git a/chrome/test/data/android/webvr_instrumentation/html/test_requestPresent_enters_vr.html b/chrome/test/data/android/webvr_instrumentation/html/test_requestPresent_enters_vr.html
index 059ff72..c37f791 100644
--- a/chrome/test/data/android/webvr_instrumentation/html/test_requestPresent_enters_vr.html
+++ b/chrome/test/data/android/webvr_instrumentation/html/test_requestPresent_enters_vr.html
@@ -13,7 +13,7 @@
     <script src="../resources/webvr_boilerplate.js"></script>
     <script>
       var t = async_test("A successful requestPresent call actually enters VR");
-      window.addEventListener("onvrdisplaypresentchange", () => {t.done();}, false);
+      window.addEventListener("vrdisplaypresentchange", () => {t.done();}, false);
     </script>
   </body>
 </html>
diff --git a/chrome/test/data/extensions/api_test/networking_cast_private/manifest.json b/chrome/test/data/extensions/api_test/networking_cast_private/manifest.json
new file mode 100644
index 0000000..965e147f
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/networking_cast_private/manifest.json
@@ -0,0 +1,15 @@
+{
+  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC74Vbx3EbhPc/FOvn6+HxCjMSml0HdPMiuRjj5a3b+MnRML1iJ9OAgbKUYJ/u3s25/cGq8pNB0NbyupHGEqvqAE7TcNr1mdgs0PWxh2IOI1GKrxlzxpqzQuFmxq5WHKr5RrwZ4/Xq0t/+e8JkvhZdW0jarz/28Jom0gkM5lorsewIDAQAB",
+  "name": "networking cast extension API interface test",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "Test of chrome.networking.castPrivate methods",
+  "app": {
+    "background": {
+      "scripts": ["test.js"]
+    }
+  },
+  "permissions": [
+    "networking.castPrivate"
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/networking_cast_private/test.js b/chrome/test/data/extensions/api_test/networking_cast_private/test.js
new file mode 100644
index 0000000..f70b961
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/networking_cast_private/test.js
@@ -0,0 +1,73 @@
+// 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.
+
+var callbackPass = chrome.test.callbackPass;
+var callbackFail = chrome.test.callbackFail;
+var assertTrue = chrome.test.assertTrue;
+var assertEq = chrome.test.assertEq;
+
+// Test properties for the verification API.
+var verificationProperties = {
+  certificate: 'certificate',
+  intermediateCertificates: ['ica1', 'ica2', 'ica3'],
+  publicKey: 'cHVibGljX2tleQ==',  // Base64('public_key')
+  nonce: 'nonce',
+  signedData: 'c2lnbmVkX2RhdGE=',  // Base64('signed_data')
+  deviceSerial: 'device_serial',
+  deviceSsid: 'Device 0123',
+  deviceBssid: '00:01:02:03:04:05'
+};
+
+chrome.test.getConfig(function(config) {
+  var args = JSON.parse(config.customArg);
+
+  chrome.test.runTests([
+    function verifyDestination() {
+      chrome.networking.castPrivate.verifyDestination(
+          verificationProperties,
+          callbackPass(function(isValid) {
+            assertTrue(isValid);
+          }));
+    },
+    function verifyAndEncryptCredentials() {
+      var networkGuid = 'wifi_guid';
+      chrome.networking.castPrivate.verifyAndEncryptCredentials(
+          verificationProperties,
+          networkGuid,
+          callbackPass(function(result) {
+            assertEq('encrypted_credentials', result);
+          }));
+    },
+    function verifyAndEncryptData() {
+      chrome.networking.castPrivate.verifyAndEncryptData(
+          verificationProperties,
+          'data',
+          callbackPass(function(result) {
+            assertEq('encrypted_data', result);
+          }));
+    },
+    function setWifiTDLSEnabledState() {
+      if (args.tdlsSupported) {
+        chrome.networking.castPrivate.setWifiTDLSEnabledState(
+            'aa:bb:cc:dd:ee:ff', true, callbackPass(function(result) {
+              assertEq('CONNECTED', result);
+            }));
+      } else {
+        chrome.networking.castPrivate.setWifiTDLSEnabledState(
+            'aa:bb:cc:dd:ee:ff', true, callbackFail('Not supported'));
+      }
+    },
+    function getWifiTDLSStatus() {
+      if (args.tdlsSupported) {
+        chrome.networking.castPrivate.getWifiTDLSStatus(
+            'aa:bb:cc:dd:ee:ff', callbackPass(function(result) {
+              assertEq('CONNECTED', result);
+            }));
+      } else {
+        chrome.networking.castPrivate.getWifiTDLSStatus(
+            'aa:bb:cc:dd:ee:ff', callbackFail('Not supported'));
+      }
+    },
+  ]);
+});
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js
index ff1d784..d222865b 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -372,6 +372,7 @@
 
         Polymer.dom.flush();
 
+        assertTrue(syncPage.$.encryptionDescription.hidden);
         assertTrue(syncPage.$.encryptionRadioGroupContainer.hidden);
       });
 
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index e8c7376..6b671fb2 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1159,8 +1159,9 @@
 TEST_PPAPI_NACL_SUBTESTS(MAYBE_Compositor0, RUN_COMPOSITOR_SUBTESTS_0)
 TEST_PPAPI_NACL_SUBTESTS(MAYBE_Compositor1, RUN_COMPOSITOR_SUBTESTS_1)
 
-#if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_CHROMEOS)
-// Flaky on ChromeOS, Linux and Windows (crbug.com/438729)
+#if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_CHROMEOS) || \
+    defined(OS_MACOSX)
+// Flaky on ChromeOS, Linux, Windows, and Mac (crbug.com/438729)
 #define MAYBE_MediaStreamAudioTrack DISABLED_MediaStreamAudioTrack
 #else
 #define MAYBE_MediaStreamAudioTrack MediaStreamAudioTrack
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index d88ee0a..681c2cb 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -447,7 +447,10 @@
 
 buildflag_header("chromecast_features") {
   header = "chromecast_features.h"
-  flags = [ "IS_CAST_AUDIO_ONLY=$is_cast_audio_only" ]
+  flags = [
+    "IS_CAST_AUDIO_ONLY=$is_cast_audio_only",
+    "IS_CAST_USING_CMA_BACKEND=$is_cast_using_cma_backend",
+  ]
 }
 
 if (is_android) {
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 81bf1e9..b33af270 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -284,13 +284,13 @@
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   AddDefaultCommandLineSwitches(command_line);
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   media_resource_tracker_ = nullptr;
-#endif  // !defined(OS_ANDROID)
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 }
 
 CastBrowserMainParts::~CastBrowserMainParts() {
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   if (media_thread_ && media_pipeline_backend_manager_) {
     // Make sure that media_pipeline_backend_manager_ is destroyed after any
     // pending media thread tasks. The CastAudioOutputStream implementation
@@ -306,14 +306,12 @@
     media_thread_->task_runner()->DeleteSoon(
         FROM_HERE, media_pipeline_backend_manager_.release());
   }
-#endif  // !defined(OS_ANDROID)
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
 CastBrowserMainParts::GetMediaTaskRunner() {
-#if defined(OS_ANDROID)
-  return nullptr;
-#else
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   if (!media_thread_) {
     media_thread_.reset(new base::Thread("CastMediaThread"));
     base::Thread::Options options;
@@ -321,10 +319,12 @@
     CHECK(media_thread_->StartWithOptions(options));
   }
   return media_thread_->task_runner();
-#endif
+#else
+  return nullptr;
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 }
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 media::MediaResourceTracker* CastBrowserMainParts::media_resource_tracker() {
   if (!media_resource_tracker_) {
     media_resource_tracker_ = new media::MediaResourceTracker(
@@ -341,7 +341,7 @@
   }
   return media_pipeline_backend_manager_.get();
 }
-#endif
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 
 media::MediaCapsImpl* CastBrowserMainParts::media_caps() {
   return media_caps_.get();
@@ -495,7 +495,7 @@
           video_plane_controller_.get(), window_manager_.get()));
   cast_browser_process_->cast_service()->Initialize();
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   media_resource_tracker()->InitializeMediaLib();
 #endif
   ::media::InitializeMediaLibrary();
diff --git a/chromecast/browser/cast_browser_main_parts.h b/chromecast/browser/cast_browser_main_parts.h
index 51defab..822e930 100644
--- a/chromecast/browser/cast_browser_main_parts.h
+++ b/chromecast/browser/cast_browser_main_parts.h
@@ -9,6 +9,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "build/buildflag.h"
+#include "chromecast/chromecast_features.h"
 #include "content/public/browser/browser_main_parts.h"
 #include "content/public/common/main_function_params.h"
 
@@ -45,7 +47,7 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   media::MediaResourceTracker* media_resource_tracker();
   media::MediaPipelineBackendManager* media_pipeline_backend_manager();
 #endif
@@ -70,7 +72,7 @@
   std::unique_ptr<media::MediaCapsImpl> media_caps_;
   std::unique_ptr<CastWindowManager> window_manager_;
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   // CMA thread used by AudioManager, MojoRenderer, and MediaPipelineBackend.
   std::unique_ptr<base::Thread> media_thread_;
 
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 978db0e..eac81d927 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -71,10 +71,12 @@
 #if defined(OS_ANDROID)
 #include "components/cdm/browser/cdm_message_filter_android.h"
 #include "components/crash/content/browser/crash_dump_manager_android.h"
-#else
-#include "chromecast/media/cdm/cast_cdm_factory.h"
 #endif  // defined(OS_ANDROID)
 
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
+#include "chromecast/media/cdm/cast_cdm_factory.h"
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
+
 namespace chromecast {
 namespace shell {
 
@@ -146,7 +148,7 @@
   return nullptr;
 }
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 media::VideoResolutionPolicy*
 CastContentBrowserClient::GetVideoResolutionPolicy() {
   return nullptr;
@@ -195,7 +197,7 @@
 #endif  // defined(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
   return nullptr;
 }
-#endif  // !defined(OS_ANDROID)
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
 
 media::MediaCapsImpl* CastContentBrowserClient::media_caps() {
   DCHECK(cast_browser_main_parts_);
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 879dc35..200ad6d7 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -13,6 +13,8 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "build/buildflag.h"
+#include "chromecast/chromecast_features.h"
 #include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/content_browser_client.h"
 
@@ -84,7 +86,7 @@
 
   virtual media::VideoModeSwitcher* GetVideoModeSwitcher();
 
-#if !defined(OS_ANDROID)
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   // Gets object for enforcing video resolution policy restrictions.
   virtual media::VideoResolutionPolicy* GetVideoResolutionPolicy();
 
@@ -101,7 +103,7 @@
   ::media::ScopedAudioManagerPtr CreateAudioManager(
       ::media::AudioLogFactory* audio_log_factory) override;
   std::unique_ptr<::media::CdmFactory> CreateCdmFactory() override;
-#endif
+#endif  // BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
   media::MediaCapsImpl* media_caps();
 
   // Invoked when the metrics client ID changes.
diff --git a/chromecast/media/cdm/BUILD.gn b/chromecast/media/cdm/BUILD.gn
index 2cf3f96f..d6fb2ea 100644
--- a/chromecast/media/cdm/BUILD.gn
+++ b/chromecast/media/cdm/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//chromecast/chromecast.gni")
+import("//media/media_options.gni")
 
 source_set("cdm") {
   sources = [
@@ -15,7 +16,7 @@
     "//media",
   ]
 
-  if (!is_android) {
+  if (is_cast_using_cma_backend) {
     sources += [
       "cast_cdm.cc",
       "cast_cdm.h",
@@ -29,14 +30,14 @@
       "//chromecast/media/base",
       "//url:url",
     ]
-  } else {
-    if (use_playready) {
-      sources += [
-        "playready_drm_delegate_android.cc",
-        "playready_drm_delegate_android.h",
-      ]
+  }
 
-      deps += [ "//media/base/android" ]
-    }
+  if (is_android && use_playready) {
+    sources += [
+      "playready_drm_delegate_android.cc",
+      "playready_drm_delegate_android.h",
+    ]
+
+    deps += [ "//media/base/android" ]
   }
 }
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn
index e24eee2..4d096ddd 100644
--- a/chromecast/media/cma/backend/BUILD.gn
+++ b/chromecast/media/cma/backend/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/chromecast_build.gni")
 import("//chromecast/chromecast.gni")
+import("//media/media_options.gni")
 
 source_set("backend") {
   sources = [
@@ -26,7 +27,12 @@
   ]
 
   if (is_android) {
-    deps += [ ":cast_media_android" ]
+    if (is_cast_using_cma_backend) {
+      # TODO(tsunghung): use the real implementation when it's done.
+      deps += [ ":default" ]
+    } else {
+      deps += [ ":cast_media_android" ]
+    }
   } else {
     deps += [ ":libcast_media_1.0" ]
   }
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc
index 65a1bae7..d5c8769f 100644
--- a/components/metrics/file_metrics_provider.cc
+++ b/components/metrics/file_metrics_provider.cc
@@ -337,10 +337,18 @@
     return ACCESS_RESULT_INVALID_CONTENTS;
   }
 
-  // Create an allocator for the mapped file. Ownership passes to the allocator.
-  source->allocator.reset(new base::PersistentHistogramAllocator(
+  // Map the file and validate it.
+  std::unique_ptr<base::PersistentMemoryAllocator> memory_allocator =
       base::MakeUnique<base::FilePersistentMemoryAllocator>(
-          std::move(mapped), 0, 0, base::StringPiece(), read_only)));
+          std::move(mapped), 0, 0, base::StringPiece(), read_only);
+  if (memory_allocator->GetMemoryState() ==
+      base::PersistentMemoryAllocator::MEMORY_DELETED) {
+    return ACCESS_RESULT_MEMORY_DELETED;
+  }
+
+  // Create an allocator for the mapped file. Ownership passes to the allocator.
+  source->allocator = base::MakeUnique<base::PersistentHistogramAllocator>(
+      std::move(memory_allocator));
 
   return ACCESS_RESULT_SUCCESS;
 }
diff --git a/components/metrics/file_metrics_provider.h b/components/metrics/file_metrics_provider.h
index 001fe83..43d4d30 100644
--- a/components/metrics/file_metrics_provider.h
+++ b/components/metrics/file_metrics_provider.h
@@ -130,6 +130,9 @@
     // File could not be opened.
     ACCESS_RESULT_NO_OPEN,
 
+    // File contents were internally deleted.
+    ACCESS_RESULT_MEMORY_DELETED,
+
     ACCESS_RESULT_MAX
   };
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index 4ba32f4..a869f2b 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -91,10 +91,10 @@
 void FormFetcherImpl::OnGetPasswordStoreResults(
     std::vector<std::unique_ptr<PasswordForm>> results) {
   DCHECK_EQ(State::WAITING, state_);
-  state_ = State::NOT_WAITING;
 
   if (need_to_refetch_) {
     // The received results are no longer up to date, need to re-request.
+    state_ = State::NOT_WAITING;
     Fetch();
     need_to_refetch_ = false;
     return;
@@ -167,6 +167,8 @@
 
 void FormFetcherImpl::ProcessPasswordStoreResults(
     std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+  DCHECK_EQ(State::WAITING, state_);
+  state_ = State::NOT_WAITING;
   federated_ = SplitFederatedMatches(&results);
   non_federated_ = std::move(results);
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 864a2b6..219e7e59 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -500,4 +500,57 @@
               UnorderedElementsAre(Pointee(federated_form)));
 }
 
+// When the FormFetcher delegates to the HttpPasswordMigrator, its state should
+// be WAITING until the migrator passes the results.
+TEST_F(FormFetcherImplTest, StateIsWaitingDuringMigration) {
+  GURL::Replacements https_rep;
+  https_rep.SetSchemeStr(url::kHttpsScheme);
+  const GURL https_origin = form_digest_.origin.ReplaceComponents(https_rep);
+  form_digest_ = PasswordStore::FormDigest(
+      PasswordForm::SCHEME_HTML, https_origin.GetOrigin().spec(), https_origin);
+
+  // A new form fetcher is created to be able to set the form digest and
+  // migration flag.
+  form_fetcher_ = base::MakeUnique<FormFetcherImpl>(
+      form_digest_, &client_, /* should_migrate_http_passwords */ true);
+
+  PasswordForm https_form = CreateNonFederated();
+
+  // Create HTTP form for the same orgin (except scheme), which will be passed
+  // to the migrator.
+  GURL::Replacements http_rep;
+  http_rep.SetSchemeStr(url::kHttpScheme);
+  PasswordForm http_form = https_form;
+  http_form.origin = https_form.origin.ReplaceComponents(http_rep);
+  http_form.signon_realm = http_form.origin.GetOrigin().spec();
+
+  std::vector<PasswordForm> empty_forms;
+
+  // Ensure there is an attempt to migrate credentials on HTTPS origins and
+  // extract the migrator.
+  const GURL form_digest_http_origin =
+      form_digest_.origin.ReplaceComponents(http_rep);
+  PasswordStore::FormDigest http_form_digest(
+      PasswordForm::SCHEME_HTML, form_digest_http_origin.GetOrigin().spec(),
+      form_digest_http_origin);
+  Fetch();
+  // First the FormFetcher is waiting for the initial response from
+  // PasswordStore.
+  EXPECT_EQ(FormFetcher::State::WAITING, form_fetcher_->GetState());
+  base::WeakPtr<PasswordStoreConsumer> migrator_ptr;
+  EXPECT_CALL(*mock_store_, GetLogins(http_form_digest, _))
+      .WillOnce(WithArg<1>(GetAndAssignWeakPtr(&migrator_ptr)));
+  form_fetcher_->OnGetPasswordStoreResults(MakeResults(empty_forms));
+  ASSERT_TRUE(migrator_ptr);
+  // While the initial results from PasswordStore arrived to the FormFetcher, it
+  // should be still waiting for the migrator.
+  EXPECT_EQ(FormFetcher::State::WAITING, form_fetcher_->GetState());
+
+  // Now perform the actual migration.
+  EXPECT_CALL(*mock_store_, AddLogin(https_form));
+  static_cast<HttpPasswordMigrator*>(migrator_ptr.get())
+      ->OnGetPasswordStoreResults(MakeResults({http_form}));
+  EXPECT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+}
+
 }  // namespace password_manager
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc
index 310cc5ac..77f03bf 100644
--- a/components/payments/content/payment_request.cc
+++ b/components/payments/content/payment_request.cc
@@ -125,8 +125,6 @@
 }
 
 void PaymentRequest::Pay() {
-  DCHECK(state_->is_ready_to_pay());
-
   state_->GeneratePaymentResponse();
 }
 
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc
index 3d321120..5a92e86 100644
--- a/components/payments/content/payment_request_spec.cc
+++ b/components/payments/content/payment_request_spec.cc
@@ -124,6 +124,9 @@
       }
     }
   }
+
+  supported_card_networks_set_.insert(supported_card_networks_.begin(),
+                                      supported_card_networks_.end());
 }
 
 void PaymentRequestSpec::NotifyOnInvalidSpecProvided() {
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h
index d205a1b..729d7ca 100644
--- a/components/payments/content/payment_request_spec.h
+++ b/components/payments/content/payment_request_spec.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_SPEC_H_
 #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_SPEC_H_
 
+#include <set>
 #include <string>
 #include <vector>
 
@@ -46,9 +47,12 @@
   bool request_payer_phone() const { return options_->request_payer_phone; }
   bool request_payer_email() const { return options_->request_payer_email; }
 
-  const std::vector<std::string>& supported_card_networks() {
+  const std::vector<std::string>& supported_card_networks() const {
     return supported_card_networks_;
   }
+  const std::set<std::string>& supported_card_networks_set() const {
+    return supported_card_networks_set_;
+  }
 
   // Uses CurrencyFormatter to format |amount| with the currency symbol for this
   // request's currency. Will use currency of the "total" display item, because
@@ -85,9 +89,11 @@
   const std::string app_locale_;
   std::unique_ptr<CurrencyFormatter> currency_formatter_;
 
-  // A list of supported basic card networks, in order that they were specified
-  // by the merchant.
+  // A list/set of supported basic card networks. The list is used to keep the
+  // order in which they were specified by the merchant. The set is used for
+  // fast lookup of supported methods.
   std::vector<std::string> supported_card_networks_;
+  std::set<std::string> supported_card_networks_set_;
 
   base::ObserverList<Observer> observers_;
 
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index e37422a..01b95a3 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -13,11 +13,6 @@
 
 namespace payments {
 
-namespace {
-// Identifier for the basic card payment method in the PaymentMethodData.
-static const char* const kBasicCardMethodName = "basic-card";
-}  // namespace
-
 PaymentRequestState::PaymentRequestState(
     PaymentRequestSpec* spec,
     Delegate* delegate,
@@ -30,7 +25,7 @@
       personal_data_manager_(personal_data_manager),
       selected_shipping_profile_(nullptr),
       selected_contact_profile_(nullptr),
-      selected_credit_card_(nullptr),
+      selected_instrument_(nullptr),
       selected_shipping_option_(nullptr) {
   PopulateProfileCache();
   UpdateSelectedShippingOption();
@@ -59,16 +54,10 @@
 }
 
 void PaymentRequestState::GeneratePaymentResponse() {
-  // TODO(mathp): PaymentRequest should know about the currently selected
-  // instrument, and not |selected_credit_card_| which is too specific.
-  // TODO(mathp): The method_name should reflect what the merchant asked, and
-  // not necessarily basic-card.
-  selected_payment_instrument_.reset(new AutofillPaymentInstrument(
-      kBasicCardMethodName, *selected_credit_card_, shipping_profiles_,
-      app_locale_));
+  DCHECK(is_ready_to_pay());
   // Fetch the instrument details, will call back into
   // PaymentRequest::OnInstrumentsDetailsReady.
-  selected_payment_instrument_->InvokePaymentApp(this);
+  selected_instrument_->InvokePaymentApp(this);
 }
 
 void PaymentRequestState::SetSelectedShippingProfile(
@@ -83,8 +72,8 @@
   UpdateIsReadyToPayAndNotifyObservers();
 }
 
-void PaymentRequestState::SetSelectedCreditCard(autofill::CreditCard* card) {
-  selected_credit_card_ = card;
+void PaymentRequestState::SetSelectedInstrument(PaymentInstrument* instrument) {
+  selected_instrument_ = instrument;
   UpdateIsReadyToPayAndNotifyObservers();
 }
 
@@ -113,11 +102,27 @@
     contact_profiles_.push_back(profile_cache_[i].get());
   }
 
+  // Create the list of available instruments.
   const std::vector<autofill::CreditCard*>& cards =
       personal_data_manager_->GetCreditCardsToSuggest();
+  const std::set<std::string>& supported_card_networks =
+      spec_->supported_card_networks_set();
   for (autofill::CreditCard* card : cards) {
-    card_cache_.push_back(base::MakeUnique<autofill::CreditCard>(*card));
-    credit_cards_.push_back(card_cache_.back().get());
+    std::string basic_card_network =
+        autofill::data_util::GetPaymentRequestData(card->type())
+            .basic_card_payment_type;
+    if (!supported_card_networks.count(basic_card_network))
+      continue;
+
+    // TODO(crbug.com/701952): Should use the method name preferred by the
+    // merchant (either "basic-card" or the basic card network e.g. "visa").
+
+    // Copy the credit cards as part of AutofillPaymentInstrument so they are
+    // indirectly owned by this object.
+    std::unique_ptr<PaymentInstrument> instrument =
+        base::MakeUnique<AutofillPaymentInstrument>(
+            basic_card_network, *card, shipping_profiles_, app_locale_);
+    available_instruments_.push_back(std::move(instrument));
   }
 }
 
@@ -128,15 +133,20 @@
   if (!contact_profiles().empty())
     selected_contact_profile_ = contact_profiles()[0];
 
-  // TODO(anthonyvd): Change this code to prioritize server cards and implement
-  // a way to modify this function's return value.
-  const std::vector<autofill::CreditCard*> cards = credit_cards();
-  auto first_complete_card =
-      std::find_if(cards.begin(), cards.end(),
-                   [](autofill::CreditCard* card) { return card->IsValid(); });
+  // TODO(crbug.com/702063): Change this code to prioritize instruments by use
+  // count and other means, and implement a way to modify this function's return
+  // value.
+  const std::vector<std::unique_ptr<PaymentInstrument>>& instruments =
+      available_instruments();
+  auto first_complete_instrument =
+      std::find_if(instruments.begin(), instruments.end(),
+                   [](const std::unique_ptr<PaymentInstrument>& instrument) {
+                     return instrument->IsValid();
+                   });
 
-  selected_credit_card_ =
-      first_complete_card == cards.end() ? nullptr : *first_complete_card;
+  selected_instrument_ = first_complete_instrument == instruments.end()
+                             ? nullptr
+                             : first_complete_instrument->get();
 
   UpdateIsReadyToPayAndNotifyObservers();
 }
@@ -153,18 +163,10 @@
 }
 
 bool PaymentRequestState::ArePaymentDetailsSatisfied() {
-  // TODO(mathp): A masked card may not satisfy IsValid().
-  if (selected_credit_card_ == nullptr || !selected_credit_card_->IsValid())
-    return false;
-
-  const std::string basic_card_payment_type =
-      autofill::data_util::GetPaymentRequestData(selected_credit_card_->type())
-          .basic_card_payment_type;
-  return !spec_->supported_card_networks().empty() &&
-         std::find(spec_->supported_card_networks().begin(),
-                   spec_->supported_card_networks().end(),
-                   basic_card_payment_type) !=
-             spec_->supported_card_networks().end();
+  // There is no need to check for supported networks, because only supported
+  // instruments are listed/created in the flow.
+  // TODO(crbug.com/702063): A masked card may not satisfy IsValid().
+  return selected_instrument_ != nullptr && selected_instrument_->IsValid();
 }
 
 bool PaymentRequestState::ArePaymentOptionsSatisfied() {
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h
index 1363690..edae5e8 100644
--- a/components/payments/content/payment_request_state.h
+++ b/components/payments/content/payment_request_state.h
@@ -12,7 +12,6 @@
 
 namespace autofill {
 class AutofillProfile;
-class CreditCard;
 class PersonalDataManager;
 }  // namespace autofill
 
@@ -76,11 +75,11 @@
   autofill::AutofillProfile* selected_contact_profile() const {
     return selected_contact_profile_;
   }
-  // Returns the currently selected credit card for this PaymentRequest flow.
+  // Returns the currently selected instrument for this PaymentRequest flow.
   // It's not guaranteed to be complete. Returns nullptr if there is no selected
-  // card.
-  autofill::CreditCard* selected_credit_card() const {
-    return selected_credit_card_;
+  // instrument.
+  PaymentInstrument* selected_instrument() const {
+    return selected_instrument_;
   }
   mojom::PaymentShippingOption* selected_shipping_option() {
     return selected_shipping_option_;
@@ -94,15 +93,16 @@
   const std::vector<autofill::AutofillProfile*>& contact_profiles() {
     return contact_profiles_;
   }
-  const std::vector<autofill::CreditCard*>& credit_cards() {
-    return credit_cards_;
+  const std::vector<std::unique_ptr<PaymentInstrument>>&
+  available_instruments() {
+    return available_instruments_;
   }
 
   // Setters to change the selected information. Will have the side effect of
   // recomputing "is ready to pay" and notify observers.
   void SetSelectedShippingProfile(autofill::AutofillProfile* profile);
   void SetSelectedContactProfile(autofill::AutofillProfile* profile);
-  void SetSelectedCreditCard(autofill::CreditCard* card);
+  void SetSelectedInstrument(PaymentInstrument* instrument);
 
   bool is_ready_to_pay() { return is_ready_to_pay_; }
 
@@ -115,7 +115,7 @@
   // profile_cache_.
   void PopulateProfileCache();
 
-  // Sets the initial selections for credit card and profiles, and notifies
+  // Sets the initial selections for instruments and profiles, and notifies
   // observers.
   void SetDefaultProfileSelections();
 
@@ -150,21 +150,19 @@
 
   autofill::AutofillProfile* selected_shipping_profile_;
   autofill::AutofillProfile* selected_contact_profile_;
-  autofill::CreditCard* selected_credit_card_;
+  PaymentInstrument* selected_instrument_;
   // The shipping options (and thus this pointer) are owned by |spec_| which
   // outlives this object.
   mojom::PaymentShippingOption* selected_shipping_option_;
 
-  std::unique_ptr<PaymentInstrument> selected_payment_instrument_;
-
   // Profiles may change due to (e.g.) sync events, so profiles are cached after
   // loading and owned here. They are populated once only, and ordered by
   // frecency.
   std::vector<std::unique_ptr<autofill::AutofillProfile>> profile_cache_;
   std::vector<autofill::AutofillProfile*> shipping_profiles_;
   std::vector<autofill::AutofillProfile*> contact_profiles_;
-  std::vector<std::unique_ptr<autofill::CreditCard>> card_cache_;
-  std::vector<autofill::CreditCard*> credit_cards_;
+  // Credit cards are directly owned by the instruments in this list.
+  std::vector<std::unique_ptr<PaymentInstrument>> available_instruments_;
 
   base::ObserverList<Observer> observers_;
 
diff --git a/components/payments/content/payment_request_state_unittest.cc b/components/payments/content/payment_request_state_unittest.cc
index be56d1f..c9455875 100644
--- a/components/payments/content/payment_request_state_unittest.cc
+++ b/components/payments/content/payment_request_state_unittest.cc
@@ -24,10 +24,15 @@
   PaymentRequestStateTest()
       : num_on_selected_information_changed_called_(0),
         address_(autofill::test::GetFullProfile()),
-        credit_card_(autofill::test::GetCreditCard()) {
+        credit_card_visa_(autofill::test::GetCreditCard()),
+        credit_card_amex_(autofill::test::GetCreditCard2()) {
     test_personal_data_manager_.AddTestingProfile(&address_);
-    credit_card_.set_billing_address_id(address_.guid());
-    test_personal_data_manager_.AddTestingCreditCard(&credit_card_);
+    credit_card_visa_.set_billing_address_id(address_.guid());
+    credit_card_visa_.set_use_count(5u);
+    test_personal_data_manager_.AddTestingCreditCard(&credit_card_visa_);
+    credit_card_amex_.set_billing_address_id(address_.guid());
+    credit_card_amex_.set_use_count(1u);
+    test_personal_data_manager_.AddTestingCreditCard(&credit_card_amex_);
   }
   ~PaymentRequestStateTest() override {}
 
@@ -86,7 +91,6 @@
   }
 
   autofill::AutofillProfile* test_address() { return &address_; }
-  autofill::CreditCard* test_credit_card() { return &credit_card_; }
 
  private:
   std::unique_ptr<PaymentRequestState> state_;
@@ -97,7 +101,8 @@
 
   // Test data.
   autofill::AutofillProfile address_;
-  autofill::CreditCard credit_card_;
+  autofill::CreditCard credit_card_visa_;
+  autofill::CreditCard credit_card_amex_;
 };
 
 // Test that the last shipping option is selected.
@@ -133,28 +138,18 @@
   EXPECT_TRUE(state()->is_ready_to_pay());
 }
 
-// Testing that the card is supported when determining "is ready to pay". In
-// this test the merchant only supports Visa.
-TEST_F(PaymentRequestStateTest, ReadyToPay_SelectUnsupportedCard) {
+// Testing that only supported intruments are shown. In this test the merchant
+// only supports Visa.
+TEST_F(PaymentRequestStateTest, UnsupportedCardAreNotAvailable) {
   // Default options.
   RecreateStateWithOptions(mojom::PaymentOptions::New());
 
-  // Ready to pay because the default card is selected and supported.
+  // Ready to pay because the default instrument is selected and supported.
   EXPECT_TRUE(state()->is_ready_to_pay());
 
-  autofill::CreditCard amex_card = autofill::test::GetCreditCard2();  // Amex.
-  state()->SetSelectedCreditCard(&amex_card);
-  EXPECT_EQ(1, num_on_selected_information_changed_called());
-
-  // Not ready to pay because the card is not supported.
-  EXPECT_FALSE(state()->is_ready_to_pay());
-
-  // Go back to the Visa card.
-  state()->SetSelectedCreditCard(test_credit_card());  // Visa card.
-  EXPECT_EQ(2, num_on_selected_information_changed_called());
-
-  // Visa card is supported by the merchant.
-  EXPECT_TRUE(state()->is_ready_to_pay());
+  // There's only one instrument available, even though there's an Amex in
+  // PersonalDataManager.
+  EXPECT_EQ(1u, state()->available_instruments().size());
 }
 
 // Test selecting a contact info profile will make the user ready to pay.
@@ -185,13 +180,13 @@
 TEST_F(PaymentRequestStateTest, GeneratePaymentResponse) {
   // Default options (no shipping, no contact info).
   RecreateStateWithOptions(mojom::PaymentOptions::New());
-  state()->SetSelectedCreditCard(test_credit_card());
+  state()->SetSelectedInstrument(state()->available_instruments()[0].get());
   EXPECT_EQ(1, num_on_selected_information_changed_called());
   EXPECT_TRUE(state()->is_ready_to_pay());
 
   // TODO(mathp): Currently synchronous, when async will need a RunLoop.
   state()->GeneratePaymentResponse();
-  EXPECT_EQ("basic-card", response()->method_name);
+  EXPECT_EQ("visa", response()->method_name);
   EXPECT_EQ(
       "{\"billingAddress\":"
       "{\"addressLine\":[\"666 Erebus St.\",\"Apt 8\"],"
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index 892c2c8..b0b5e5b 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -14,6 +14,7 @@
     "currency_formatter.h",
     "payment_address.cc",
     "payment_address.h",
+    "payment_instrument.cc",
     "payment_instrument.h",
     "payment_request_data_util.cc",
     "payment_request_data_util.h",
diff --git a/components/payments/core/autofill_payment_instrument.cc b/components/payments/core/autofill_payment_instrument.cc
index 3f55efd..00c59b6 100644
--- a/components/payments/core/autofill_payment_instrument.cc
+++ b/components/payments/core/autofill_payment_instrument.cc
@@ -15,11 +15,18 @@
 
 AutofillPaymentInstrument::AutofillPaymentInstrument(
     const std::string& method_name,
-    const autofill::CreditCard& credit_card,
+    const autofill::CreditCard& card,
     const std::vector<autofill::AutofillProfile*>& billing_profiles,
     const std::string& app_locale)
-    : PaymentInstrument(method_name),
-      credit_card_(credit_card),
+    : PaymentInstrument(
+          method_name,
+          /* label= */ card.TypeAndLastFourDigits(),
+          /* sublabel= */
+          card.GetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
+                       app_locale),
+          autofill::data_util::GetPaymentRequestData(card.type())
+              .icon_resource_id),
+      credit_card_(card),
       billing_profiles_(billing_profiles),
       app_locale_(app_locale) {}
 AutofillPaymentInstrument::~AutofillPaymentInstrument() {}
@@ -39,4 +46,8 @@
   delegate->OnInstrumentDetailsReady(method_name(), stringified_details);
 }
 
+bool AutofillPaymentInstrument::IsValid() {
+  return credit_card_.IsValid();
+}
+
 }  // namespace payments
diff --git a/components/payments/core/autofill_payment_instrument.h b/components/payments/core/autofill_payment_instrument.h
index d6d9ec6c..ca0e125 100644
--- a/components/payments/core/autofill_payment_instrument.h
+++ b/components/payments/core/autofill_payment_instrument.h
@@ -26,17 +26,21 @@
   // |billing_profiles| is owned by the caller and should outlive this object.
   AutofillPaymentInstrument(
       const std::string& method_name,
-      const autofill::CreditCard& credit_card,
+      const autofill::CreditCard& card,
       const std::vector<autofill::AutofillProfile*>& billing_profiles,
       const std::string& app_locale);
   ~AutofillPaymentInstrument() override;
 
   // PaymentInstrument:
   void InvokePaymentApp(PaymentInstrument::Delegate* delegate) override;
+  bool IsValid() override;
 
  private:
+  // A copy of the card is owned by this object.
   const autofill::CreditCard credit_card_;
+  // Not owned by this object, should outlive this.
   const std::vector<autofill::AutofillProfile*>& billing_profiles_;
+
   const std::string app_locale_;
 
   DISALLOW_COPY_AND_ASSIGN(AutofillPaymentInstrument);
diff --git a/components/payments/core/payment_instrument.cc b/components/payments/core/payment_instrument.cc
new file mode 100644
index 0000000..324c47a9
--- /dev/null
+++ b/components/payments/core/payment_instrument.cc
@@ -0,0 +1,20 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/payments/core/payment_instrument.h"
+
+namespace payments {
+
+PaymentInstrument::PaymentInstrument(const std::string& method_name,
+                                     const base::string16& label,
+                                     const base::string16& sublabel,
+                                     int icon_resource_id)
+    : method_name_(method_name),
+      label_(label),
+      sublabel_(sublabel),
+      icon_resource_id_(icon_resource_id) {}
+
+PaymentInstrument::~PaymentInstrument() {}
+
+}  // namespace payments
diff --git a/components/payments/core/payment_instrument.h b/components/payments/core/payment_instrument.h
index a9348d5..7b3d0e0 100644
--- a/components/payments/core/payment_instrument.h
+++ b/components/payments/core/payment_instrument.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/strings/string16.h"
 
 namespace payments {
 
@@ -28,19 +29,29 @@
     virtual void OnInstrumentDetailsError() = 0;
   };
 
-  virtual ~PaymentInstrument() {}
+  virtual ~PaymentInstrument();
 
   // Will call into the |delegate| (can't be null) on success or error.
   virtual void InvokePaymentApp(Delegate* delegate) = 0;
+  // Returns true if the card is valid to be used as a payment method.
+  virtual bool IsValid() = 0;
 
-  const std::string& method_name() { return method_name_; }
+  const std::string& method_name() const { return method_name_; }
+  const base::string16& label() const { return label_; }
+  const base::string16& sublabel() const { return sublabel_; }
+  int icon_resource_id() const { return icon_resource_id_; }
 
  protected:
-  explicit PaymentInstrument(const std::string& method_name)
-      : method_name_(method_name) {}
+  PaymentInstrument(const std::string& method_name,
+                    const base::string16& label,
+                    const base::string16& sublabel,
+                    int icon_resource_id);
 
  private:
   const std::string method_name_;
+  const base::string16 label_;
+  const base::string16 sublabel_;
+  int icon_resource_id_;
 
   DISALLOW_COPY_AND_ASSIGN(PaymentInstrument);
 };
diff --git a/components/signin/core/browser/signin_client.cc b/components/signin/core/browser/signin_client.cc
index 9473e0b..6ca52420 100644
--- a/components/signin/core/browser/signin_client.cc
+++ b/components/signin/core/browser/signin_client.cc
@@ -32,7 +32,9 @@
   return signin_scoped_device_id;
 }
 
-void SigninClient::PreSignOut(const base::Callback<void()>& sign_out) {
+void SigninClient::PreSignOut(
+    const base::Callback<void()>& sign_out,
+    signin_metrics::ProfileSignout signout_source_metric) {
   sign_out.Run();
 }
 
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
index a4910c15..8281810 100644
--- a/components/signin/core/browser/signin_client.h
+++ b/components/signin/core/browser/signin_client.h
@@ -10,6 +10,7 @@
 #include "base/time/time.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/core/browser/account_info.h"
+#include "components/signin/core/browser/signin_metrics.h"
 #include "components/signin/core/browser/webdata/token_web_data.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "net/cookies/cookie_store.h"
@@ -98,7 +99,8 @@
 
   // Called before Google signout started, call |sign_out| to start the sign out
   // process.
-  virtual void PreSignOut(const base::Callback<void()>& sign_out);
+  virtual void PreSignOut(const base::Callback<void()>& sign_out,
+                          signin_metrics::ProfileSignout signout_source_metric);
 
   virtual bool IsFirstRun() const = 0;
   virtual base::Time GetInstallDate() = 0;
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc
index 27fce04..d27931d 100644
--- a/components/signin/core/browser/signin_manager.cc
+++ b/components/signin/core/browser/signin_manager.cc
@@ -149,9 +149,10 @@
 void SigninManager::SignOut(
     signin_metrics::ProfileSignout signout_source_metric,
     signin_metrics::SignoutDelete signout_delete_metric) {
-  client_->PreSignOut(base::Bind(&SigninManager::DoSignOut,
-                                 base::Unretained(this), signout_source_metric,
-                                 signout_delete_metric));
+  client_->PreSignOut(
+      base::Bind(&SigninManager::DoSignOut, base::Unretained(this),
+                 signout_source_metric, signout_delete_metric),
+      signout_source_metric);
 }
 
 void SigninManager::DoSignOut(
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h
index 0ba0eb04..061a414 100644
--- a/components/signin/core/browser/signin_metrics.h
+++ b/components/signin/core/browser/signin_metrics.h
@@ -46,7 +46,8 @@
   // The credentials are being transfered to a new profile, so the old one is
   // signed out.
   TRANSFER_CREDENTIALS,
-
+  // Signed out because credentials are invalid and force-sign-in is enabled.
+  AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN,
   // Keep this as the last enum.
   NUM_PROFILE_SIGNOUT_METRICS,
 };
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc
index cd10a75..ea1a1f9e 100644
--- a/components/translate/core/browser/translate_manager.cc
+++ b/components/translate/core/browser/translate_manager.cc
@@ -224,10 +224,7 @@
   InitTranslateEvent(language_code, target_lang, *translate_prefs);
 
   // Don't translate similar languages (ex: en-US to en).
-  // Also do not offer to translate between Simplified and Traditional Chinese.
-  if (language_code == target_lang ||
-      (language_code == "zh-CN" && target_lang == "zh-TW") ||
-      (language_code == "zh-TW" && target_lang == "zh-CN")) {
+  if (language_code == target_lang) {
     TranslateBrowserMetrics::ReportInitiationStatus(
         TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES);
     return;
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index dfe0696..fda38d7 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -307,64 +307,6 @@
       1);
 }
 
-// The test measures that Translate is not triggered for a zh-TW page for a
-// zh-CN user.
-TEST_F(TranslateManagerTest,
-       DontTranslateZhTraditionalPageForZhSimplifiedLocale) {
-  TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, kAcceptLanguages));
-
-  const char kMetricName[] = "Translate.InitiationStatus.v2";
-  base::HistogramTester histogram_tester;
-
-  const std::string locale = "zh-TW";
-  const std::string page_lang = "zh-CN";
-
-  network_notifier_.SimulateOnline();
-  manager_->set_application_locale(locale);
-  ON_CALL(mock_translate_client_, IsTranslatableURL(_))
-      .WillByDefault(Return(true));
-
-  EXPECT_EQ("zh-TW", translate_manager_->GetTargetLanguage(&translate_prefs_));
-  translate_manager_->GetLanguageState().LanguageDetermined(page_lang, true);
-  translate_manager_->InitiateTranslation(page_lang);
-
-  histogram_tester.ExpectUniqueSample(
-      kMetricName,
-      translate::TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES,
-      1);
-}
-
-// The test measures that Translate is not triggered for a zh-CN page for a
-// zh-TW user.
-TEST_F(TranslateManagerTest,
-       DontTranslateZhSimplifiedPageForZhTraditionalLocale) {
-  TranslateManager::SetIgnoreMissingKeyForTesting(true);
-  translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, kAcceptLanguages));
-
-  const char kMetricName[] = "Translate.InitiationStatus.v2";
-  base::HistogramTester histogram_tester;
-
-  const std::string locale = "zh-CN";
-  const std::string page_lang = "zh-TW";
-
-  network_notifier_.SimulateOnline();
-  manager_->set_application_locale(locale);
-  ON_CALL(mock_translate_client_, IsTranslatableURL(_))
-      .WillByDefault(Return(true));
-
-  EXPECT_EQ("zh-CN", translate_manager_->GetTargetLanguage(&translate_prefs_));
-  translate_manager_->GetLanguageState().LanguageDetermined(page_lang, true);
-  translate_manager_->InitiateTranslation(page_lang);
-
-  histogram_tester.ExpectUniqueSample(
-      kMetricName,
-      translate::TranslateBrowserMetrics::INITIATION_STATUS_SIMILAR_LANGUAGES,
-      1);
-}
-
 // Utility function to set the threshold params
 void ChangeThresholdInParams(
     const char* initiate_translation_confidence_threshold,
diff --git a/content/app/content_main.cc b/content/app/content_main.cc
index b983bf8..c5086ad 100644
--- a/content/app/content_main.cc
+++ b/content/app/content_main.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/debug/activity_tracker.h"
 #include "content/public/app/content_main_runner.h"
 
 namespace content {
@@ -14,13 +15,34 @@
   std::unique_ptr<ContentMainRunner> main_runner(ContentMainRunner::Create());
 
   int exit_code = main_runner->Initialize(params);
-  if (exit_code >= 0)
+  if (exit_code >= 0) {
+    base::debug::GlobalActivityTracker* tracker =
+        base::debug::GlobalActivityTracker::Get();
+    if (tracker) {
+      tracker->SetProcessPhase(
+          base::debug::GlobalActivityTracker::PROCESS_LAUNCH_FAILED);
+      tracker->process_data().SetInt("exit-code", exit_code);
+    }
     return exit_code;
+  }
 
   exit_code = main_runner->Run();
 
   main_runner->Shutdown();
 
+  base::debug::GlobalActivityTracker* tracker =
+      base::debug::GlobalActivityTracker::Get();
+  if (tracker) {
+    if (exit_code == 0) {
+      tracker->SetProcessPhaseIfEnabled(
+          base::debug::GlobalActivityTracker::PROCESS_EXITED_CLEANLY);
+    } else {
+      tracker->SetProcessPhaseIfEnabled(
+          base::debug::GlobalActivityTracker::PROCESS_EXITED_WITH_CODE);
+      tracker->process_data().SetInt("exit-code", exit_code);
+    }
+  }
+
   return exit_code;
 }
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 673a49c2..7fe0901 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -334,6 +334,8 @@
     "background_fetch/background_fetch_job_info.h",
     "background_fetch/background_fetch_request_info.cc",
     "background_fetch/background_fetch_request_info.h",
+    "background_fetch/background_fetch_service_impl.cc",
+    "background_fetch/background_fetch_service_impl.h",
     "background_sync/background_sync_context.cc",
     "background_sync/background_sync_context.h",
     "background_sync/background_sync_manager.cc",
diff --git a/content/browser/android/java_interfaces_impl.cc b/content/browser/android/java_interfaces_impl.cc
index 4169654..64ac665 100644
--- a/content/browser/android/java_interfaces_impl.cc
+++ b/content/browser/android/java_interfaces_impl.cc
@@ -11,6 +11,7 @@
 #include "base/android/context_utils.h"
 #include "base/android/jni_android.h"
 #include "base/memory/singleton.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/InterfaceRegistrarImpl_jni.h"
@@ -60,4 +61,13 @@
       web_contents->GetJavaWebContents().obj());
 }
 
+void BindInterfaceRegistryForRenderFrameHost(
+    service_manager::mojom::InterfaceProviderRequest request,
+    RenderFrameHostImpl* render_frame_host) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_InterfaceRegistrarImpl_createInterfaceRegistryForRenderFrameHost(
+      env, request.PassMessagePipe().release().value(),
+      render_frame_host->GetJavaRenderFrameHost().obj());
+}
+
 }  // namespace content
diff --git a/content/browser/android/java_interfaces_impl.h b/content/browser/android/java_interfaces_impl.h
index f78c063d..fd5cb80 100644
--- a/content/browser/android/java_interfaces_impl.h
+++ b/content/browser/android/java_interfaces_impl.h
@@ -9,12 +9,17 @@
 #include "services/service_manager/public/interfaces/interface_provider.mojom.h"
 
 namespace content {
+class RenderFrameHostImpl;
 class WebContents;
 
 void BindInterfaceRegistryForWebContents(
     service_manager::mojom::InterfaceProviderRequest request,
     WebContents* web_contents);
 
+void BindInterfaceRegistryForRenderFrameHost(
+    service_manager::mojom::InterfaceProviderRequest request,
+    RenderFrameHostImpl* render_frame_host);
+
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_ANDROID_JAVA_INTERFACES_IMPL_H_
diff --git a/content/browser/background_fetch/DEPS b/content/browser/background_fetch/DEPS
new file mode 100644
index 0000000..c0c3af0
--- /dev/null
+++ b/content/browser/background_fetch/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom.h",
+]
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc
new file mode 100644
index 0000000..cb81edc
--- /dev/null
+++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -0,0 +1,84 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/background_fetch/background_fetch_service_impl.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "content/browser/background_fetch/background_fetch_context.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace content {
+
+// static
+void BackgroundFetchServiceImpl::Create(
+    scoped_refptr<BackgroundFetchContext> background_fetch_context,
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+    blink::mojom::BackgroundFetchServiceRequest request) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  mojo::MakeStrongBinding(base::MakeUnique<BackgroundFetchServiceImpl>(
+                              std::move(background_fetch_context),
+                              std::move(service_worker_context)),
+                          std::move(request));
+}
+
+BackgroundFetchServiceImpl::BackgroundFetchServiceImpl(
+    scoped_refptr<BackgroundFetchContext> background_fetch_context,
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+    : background_fetch_context_(std::move(background_fetch_context)),
+      service_worker_context_(std::move(service_worker_context)) {
+  DCHECK(background_fetch_context_);
+  DCHECK(service_worker_context_);
+}
+
+BackgroundFetchServiceImpl::~BackgroundFetchServiceImpl() = default;
+
+void BackgroundFetchServiceImpl::UpdateUI(
+    int64_t service_worker_registration_id,
+    const std::string& tag,
+    const std::string& title,
+    const UpdateUICallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // TODO(peter): Get the BackgroundFetchJobController for the
+  // {service_worker_registration_id, tag} pair and call UpdateUI() on it.
+
+  callback.Run(blink::mojom::BackgroundFetchError::NONE);
+}
+
+void BackgroundFetchServiceImpl::Abort(int64_t service_worker_registration_id,
+                                       const std::string& tag) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // TODO(peter): Get the BackgroundFetchJobController for the
+  // {service_worker_registration_id, tag} pair and call Abort() on it.
+}
+
+void BackgroundFetchServiceImpl::GetRegistration(
+    int64_t service_worker_registration_id,
+    const std::string& tag,
+    const GetRegistrationCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // TODO(peter): Get the registration for {service_worker_registration_id, tag}
+  // and construct a BackgroundFetchRegistrationPtr for it.
+
+  callback.Run(blink::mojom::BackgroundFetchError::NONE,
+               nullptr /* registration */);
+}
+
+void BackgroundFetchServiceImpl::GetTags(int64_t service_worker_registration_id,
+                                         const GetTagsCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  // TODO(peter): Get the list of active Background Fetches associated with
+  // service_worker_registration_id and share their tags.
+
+  callback.Run(blink::mojom::BackgroundFetchError::NONE,
+               std::vector<std::string>());
+}
+
+}  // namespace content
diff --git a/content/browser/background_fetch/background_fetch_service_impl.h b/content/browser/background_fetch/background_fetch_service_impl.h
new file mode 100644
index 0000000..ffc2986
--- /dev/null
+++ b/content/browser/background_fetch/background_fetch_service_impl.h
@@ -0,0 +1,54 @@
+// 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_BACKGROUND_FETCH_BACKGROUND_FETCH_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_SERVICE_IMPL_H_
+
+#include <string>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom.h"
+
+namespace content {
+
+class BackgroundFetchContext;
+class ServiceWorkerContextWrapper;
+
+class BackgroundFetchServiceImpl : public blink::mojom::BackgroundFetchService {
+ public:
+  BackgroundFetchServiceImpl(
+      scoped_refptr<BackgroundFetchContext> background_fetch_context,
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+  ~BackgroundFetchServiceImpl() override;
+
+  static void Create(
+      scoped_refptr<BackgroundFetchContext> background_fetch_context,
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+      blink::mojom::BackgroundFetchServiceRequest request);
+
+  // blink::mojom::BackgroundFetchService implementation.
+  void UpdateUI(int64_t service_worker_registration_id,
+                const std::string& tag,
+                const std::string& title,
+                const UpdateUICallback& callback) override;
+  void Abort(int64_t service_worker_registration_id,
+             const std::string& tag) override;
+  void GetRegistration(int64_t service_worker_registration_id,
+                       const std::string& tag,
+                       const GetRegistrationCallback& callback) override;
+  void GetTags(int64_t service_worker_registration_id,
+               const GetTagsCallback& callback) override;
+
+ private:
+  scoped_refptr<BackgroundFetchContext> background_fetch_context_;
+  scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundFetchServiceImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_SERVICE_IMPL_H_
diff --git a/content/browser/device_sensors/device_sensor_browsertest.cc b/content/browser/device_sensors/device_sensor_browsertest.cc
index df8fbc7..f3d65a6 100644
--- a/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -57,6 +57,18 @@
     orientation_stopped_callback_ = orientation_stopped_callback;
   }
 
+  void SetOrientationAbsoluteStartedCallback(
+      base::Closure orientation_absolute_started_callback) {
+    orientation_absolute_started_callback_ =
+        orientation_absolute_started_callback;
+  }
+
+  void SetOrientationAbsoluteStoppedCallback(
+      base::Closure orientation_absolute_stopped_callback) {
+    orientation_absolute_stopped_callback_ =
+        orientation_absolute_stopped_callback;
+  }
+
   bool Start(device::ConsumerType consumer_type, void* buffer) override {
     EXPECT_TRUE(buffer);
 
@@ -79,6 +91,15 @@
         BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                                 orientation_started_callback_);
       } break;
+      case device::CONSUMER_TYPE_ORIENTATION_ABSOLUTE: {
+        device::DeviceOrientationHardwareBuffer* orientation_buffer =
+            static_cast<device::DeviceOrientationHardwareBuffer*>(buffer);
+        if (sensor_data_available_)
+          UpdateOrientationAbsolute(orientation_buffer);
+        SetOrientationBufferReady(orientation_buffer);
+        BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                                orientation_absolute_started_callback_);
+      } break;
       case device::CONSUMER_TYPE_LIGHT: {
         device::DeviceLightHardwareBuffer* light_buffer =
             static_cast<device::DeviceLightHardwareBuffer*>(buffer);
@@ -105,6 +126,10 @@
         BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                                 orientation_stopped_callback_);
         break;
+      case device::CONSUMER_TYPE_ORIENTATION_ABSOLUTE:
+        BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                                orientation_absolute_stopped_callback_);
+        break;
       case device::CONSUMER_TYPE_LIGHT:
         BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                                 light_stopped_callback_);
@@ -178,6 +203,20 @@
     buffer->seqlock.WriteEnd();
   }
 
+  void UpdateOrientationAbsolute(
+      device::DeviceOrientationHardwareBuffer* buffer) {
+    buffer->seqlock.WriteBegin();
+    buffer->data.alpha = 4;
+    buffer->data.hasAlpha = true;
+    buffer->data.beta = 5;
+    buffer->data.hasBeta = true;
+    buffer->data.gamma = 6;
+    buffer->data.hasGamma = true;
+    buffer->data.absolute = true;
+    buffer->data.allAvailableSensorsAreActive = true;
+    buffer->seqlock.WriteEnd();
+  }
+
   void UpdateLight(device::DeviceLightHardwareBuffer* buffer, double lux) {
     buffer->seqlock.WriteBegin();
     buffer->data.value = lux;
@@ -187,9 +226,11 @@
   // The below callbacks should be run on the UI thread.
   base::Closure motion_started_callback_;
   base::Closure orientation_started_callback_;
+  base::Closure orientation_absolute_started_callback_;
   base::Closure light_started_callback_;
   base::Closure motion_stopped_callback_;
   base::Closure orientation_stopped_callback_;
+  base::Closure orientation_absolute_stopped_callback_;
   base::Closure light_stopped_callback_;
   bool sensor_data_available_;
 
@@ -213,6 +254,8 @@
     motion_stopped_runloop_.reset(new base::RunLoop());
     orientation_started_runloop_.reset(new base::RunLoop());
     orientation_stopped_runloop_.reset(new base::RunLoop());
+    orientation_absolute_started_runloop_.reset(new base::RunLoop());
+    orientation_absolute_stopped_runloop_.reset(new base::RunLoop());
 #if defined(OS_ANDROID)
     // On Android, the DeviceSensorService lives on the UI thread.
     SetUpFetcher();
@@ -236,6 +279,10 @@
         orientation_started_runloop_->QuitClosure());
     fetcher_->SetOrientationStoppedCallback(
         orientation_stopped_runloop_->QuitClosure());
+    fetcher_->SetOrientationAbsoluteStartedCallback(
+        orientation_absolute_started_runloop_->QuitClosure());
+    fetcher_->SetOrientationAbsoluteStoppedCallback(
+        orientation_absolute_stopped_runloop_->QuitClosure());
     device::DeviceSensorService::GetInstance()->SetDataFetcherForTesting(
         fetcher_);
   }
@@ -279,6 +326,8 @@
   std::unique_ptr<base::RunLoop> motion_stopped_runloop_;
   std::unique_ptr<base::RunLoop> orientation_started_runloop_;
   std::unique_ptr<base::RunLoop> orientation_stopped_runloop_;
+  std::unique_ptr<base::RunLoop> orientation_absolute_started_runloop_;
+  std::unique_ptr<base::RunLoop> orientation_absolute_stopped_runloop_;
 
  private:
   base::WaitableEvent io_loop_finished_event_;
@@ -296,6 +345,19 @@
   orientation_stopped_runloop_->Run();
 }
 
+IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationAbsoluteTest) {
+  // The test page will register an event handler for absolute orientation
+  // events, expects to get an event with fake values, then removes the event
+  // handler and navigates to #pass.
+  GURL test_url =
+      GetTestUrl("device_sensors", "device_orientation_absolute_test.html");
+  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+  orientation_absolute_started_runloop_->Run();
+  orientation_absolute_stopped_runloop_->Run();
+}
+
 IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, LightTest) {
   // The test page will register an event handler for light events,
   // expects to get an event with fake values, then removes the event
@@ -350,6 +412,20 @@
   orientation_stopped_runloop_->Run();
 }
 
+IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, OrientationAbsoluteNullTest) {
+  // The test page registers an event handler for absolute orientation events
+  // and expects to get an event with null values, because no sensor data can be
+  // provided.
+  fetcher_->SetSensorDataAvailable(false);
+  GURL test_url = GetTestUrl("device_sensors",
+                             "device_orientation_absolute_null_test.html");
+  NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+  EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+  orientation_absolute_started_runloop_->Run();
+  orientation_absolute_stopped_runloop_->Run();
+}
+
 IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest, MotionNullTest) {
   // The test page registers an event handler for motion events and
   // expects to get an event with null values, because no sensor data can be
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 77fdcb7b..70c236e6 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -114,6 +114,7 @@
 #include "url/gurl.h"
 
 #if defined(OS_ANDROID)
+#include "content/browser/android/java_interfaces_impl.h"
 #include "content/browser/frame_host/render_frame_host_android.h"
 #include "content/browser/media/android/media_player_renderer.h"
 #include "content/public/browser/android/java_interfaces.h"
@@ -3507,6 +3508,16 @@
   }
   return render_frame_host_android->GetJavaObject();
 }
+
+service_manager::InterfaceProvider* RenderFrameHostImpl::GetJavaInterfaces() {
+  if (!java_interfaces_) {
+    service_manager::mojom::InterfaceProviderPtr provider;
+    BindInterfaceRegistryForRenderFrameHost(mojo::MakeRequest(&provider), this);
+    java_interfaces_.reset(new service_manager::InterfaceProvider);
+    java_interfaces_->Bind(std::move(provider));
+  }
+  return java_interfaces_.get();
+}
 #endif
 
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index b5c7fe6..8bed9932 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -619,6 +619,7 @@
 
 #if defined(OS_ANDROID)
   base::android::ScopedJavaLocalRef<jobject> GetJavaRenderFrameHost();
+  service_manager::InterfaceProvider* GetJavaInterfaces() override;
 #endif
 
  protected:
@@ -1144,6 +1145,10 @@
   // Tracks the feature policy which has been set on this frame.
   std::unique_ptr<FeaturePolicy> feature_policy_;
 
+#if defined(OS_ANDROID)
+  std::unique_ptr<service_manager::InterfaceProvider> java_interfaces_;
+#endif
+
   // NOTE: This must be the last member.
   base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 9086cd30..c65dad2 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -55,6 +55,7 @@
 #include "components/tracing/common/tracing_switches.h"
 #include "content/browser/appcache/appcache_dispatcher_host.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/background_fetch/background_fetch_service_impl.h"
 #include "content/browser/background_sync/background_sync_service_impl.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/blob_storage/blob_dispatcher_host.h"
@@ -1315,6 +1316,11 @@
       base::Bind(&PushMessagingManager::BindRequest,
                  base::Unretained(push_messaging_manager_.get())));
 
+  registry->AddInterface(base::Bind(
+      &BackgroundFetchServiceImpl::Create,
+      make_scoped_refptr(storage_partition_impl_->GetBackgroundFetchContext()),
+      make_scoped_refptr(storage_partition_impl_->GetServiceWorkerContext())));
+
   registry->AddInterface(base::Bind(&RenderProcessHostImpl::CreateMusGpuRequest,
                                     base::Unretained(this)));
 
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 95b3a95..b84229d 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -398,6 +398,9 @@
   if (GetPlatformNotificationContext())
     GetPlatformNotificationContext()->Shutdown();
 
+  if (GetBackgroundFetchContext())
+    GetBackgroundFetchContext()->Shutdown();
+
   if (GetBackgroundSyncContext())
     GetBackgroundSyncContext()->Shutdown();
 
@@ -489,6 +492,9 @@
                                           partition->service_worker_context_);
   partition->platform_notification_context_->Initialize();
 
+  partition->background_fetch_context_ = new BackgroundFetchContext(
+      context, partition.get(), partition->service_worker_context_);
+
   partition->background_sync_context_ = new BackgroundSyncContext();
   partition->background_sync_context_->Init(partition->service_worker_context_);
 
@@ -566,6 +572,10 @@
   return platform_notification_context_.get();
 }
 
+BackgroundFetchContext* StoragePartitionImpl::GetBackgroundFetchContext() {
+  return background_fetch_context_.get();
+}
+
 BackgroundSyncContext* StoragePartitionImpl::GetBackgroundSyncContext() {
   return background_sync_context_.get();
 }
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 92b46dd0..9157d5b 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/background_fetch/background_fetch_context.h"
 #include "content/browser/background_sync/background_sync_context.h"
 #include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
 #include "content/browser/broadcast_channel/broadcast_channel_provider.h"
@@ -78,6 +79,7 @@
   PlatformNotificationContextImpl* GetPlatformNotificationContext() override;
   void ClearBluetoothAllowedDevicesMapForTesting() override;
 
+  BackgroundFetchContext* GetBackgroundFetchContext();
   BackgroundSyncContext* GetBackgroundSyncContext();
   PaymentAppContextImpl* GetPaymentAppContext();
   BroadcastChannelProvider* GetBroadcastChannelProvider();
@@ -220,6 +222,7 @@
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
   scoped_refptr<HostZoomLevelContext> host_zoom_level_context_;
   scoped_refptr<PlatformNotificationContextImpl> platform_notification_context_;
+  scoped_refptr<BackgroundFetchContext> background_fetch_context_;
   scoped_refptr<BackgroundSyncContext> background_sync_context_;
   scoped_refptr<PaymentAppContextImpl> payment_app_context_;
   scoped_refptr<BroadcastChannelProvider> broadcast_channel_provider_;
diff --git a/content/common/message_port.cc b/content/common/message_port.cc
index 428162e..a57236a 100644
--- a/content/common/message_port.cc
+++ b/content/common/message_port.cc
@@ -153,15 +153,14 @@
   MojoResult rv = CreateWatcher(&State::CallOnHandleReady, &watcher_handle_);
   DCHECK_EQ(MOJO_RESULT_OK, rv);
 
-  // We use a scoped_refptr<State> instance as the watch context. This is owned
-  // by the watch and deleted upon receiving a cancellation notification.
-  scoped_refptr<State>* state_ref = new scoped_refptr<State>(this);
-  context_ = reinterpret_cast<uintptr_t>(state_ref);
+  // Balanced in CallOnHandleReady when MOJO_RESULT_CANCELLED is received.
+  AddRef();
 
   // NOTE: An HTML MessagePort does not receive an event to tell it when the
   // peer has gone away, so we only watch for readability here.
-  rv = MojoWatch(watcher_handle_.get().value(), handle_.get().value(),
-                 MOJO_HANDLE_SIGNAL_READABLE, context_);
+  rv =
+      MojoWatch(watcher_handle_.get().value(), handle_.get().value(),
+                MOJO_HANDLE_SIGNAL_READABLE, reinterpret_cast<uintptr_t>(this));
   DCHECK_EQ(MOJO_RESULT_OK, rv);
 
   ArmWatcher();
@@ -169,7 +168,6 @@
 
 void MessagePort::State::CancelWatch() {
   watcher_handle_.reset();
-  context_ = 0;
 }
 
 MessagePort::State::~State() = default;
@@ -191,7 +189,7 @@
   // The watcher could not be armed because it would notify immediately.
   DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
   DCHECK_EQ(1u, num_ready_contexts);
-  DCHECK_EQ(context_, ready_context);
+  DCHECK_EQ(reinterpret_cast<uintptr_t>(this), ready_context);
 
   if (ready_result == MOJO_RESULT_OK) {
     // The handle is already signaled, so we trigger a callback now.
@@ -222,12 +220,13 @@
                                            MojoResult result,
                                            MojoHandleSignalsState signals_state,
                                            MojoWatcherNotificationFlags flags) {
-  auto* state_ref = reinterpret_cast<scoped_refptr<State>*>(context);
+  auto* state = reinterpret_cast<State*>(context);
   if (result == MOJO_RESULT_CANCELLED) {
-    // Last notification. Delete the watch's owned State ref.
-    delete state_ref;
+    // Last notification. Release the watch context's owned State ref. This is
+    // balanced in MessagePort::State::AddWatch.
+    state->Release();
   } else {
-    (*state_ref)->OnHandleReady(result);
+    state->OnHandleReady(result);
   }
 }
 
diff --git a/content/common/message_port.h b/content/common/message_port.h
index fbd7280a..d3d198c 100644
--- a/content/common/message_port.h
+++ b/content/common/message_port.h
@@ -100,8 +100,6 @@
                                   MojoResult result,
                                   MojoHandleSignalsState signals_state,
                                   MojoWatcherNotificationFlags flags);
-
-    uintptr_t context_;
   };
   mutable scoped_refptr<State> state_;
 };
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc
index 789a7a8..b8474b6 100644
--- a/content/common/sandbox_win.cc
+++ b/content/common/sandbox_win.cc
@@ -10,6 +10,7 @@
 
 #include "base/base_switches.h"
 #include "base/command_line.h"
+#include "base/debug/activity_tracker.h"
 #include "base/debug/profiler.h"
 #include "base/files/file_util.h"
 #include "base/hash.h"
@@ -836,6 +837,13 @@
 
   TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS");
 
+  base::debug::GlobalActivityTracker* tracker =
+      base::debug::GlobalActivityTracker::Get();
+  if (tracker) {
+    tracker->RecordProcessLaunch(target.process_id(),
+                                 cmd_line->GetCommandLineString());
+  }
+
   if (sandbox::SBOX_ALL_OK != result) {
     UMA_HISTOGRAM_SPARSE_SLOWLY("Process.Sandbox.Launch.Error", last_error);
     if (result == sandbox::SBOX_ERROR_GENERIC)
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 77d840f8..6a31d09f 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -233,6 +233,7 @@
     "java/src/org/chromium/content_public/browser/SmartClipCallback.java",
     "java/src/org/chromium/content_public/browser/WebContents.java",
     "java/src/org/chromium/content_public/browser/WebContentsObserver.java",
+    "java/src/org/chromium/content_public/browser/WebContentsStatics.java",
     "java/src/org/chromium/content_public/common/MediaMetadata.java",
     "java/src/org/chromium/content_public/common/Referrer.java",
     "java/src/org/chromium/content_public/common/ResourceRequestBody.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
index ec7a125..081410e 100644
--- a/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java
@@ -10,6 +10,7 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.shapedetection.FaceDetectionProviderImpl;
 import org.chromium.content_public.browser.InterfaceRegistrar;
+import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.device.BatteryMonitor;
 import org.chromium.device.battery.BatteryMonitorFactory;
@@ -43,6 +44,16 @@
         InterfaceRegistrar.Registry.applyWebContentsRegistrars(registry, webContents);
     }
 
+    @CalledByNative
+    static void createInterfaceRegistryForRenderFrameHost(
+            int nativeHandle, RenderFrameHost renderFrameHost) {
+        ensureContentRegistrarsAreRegistered();
+
+        InterfaceRegistry registry = InterfaceRegistry.create(
+                CoreImpl.getInstance().acquireNativeHandle(nativeHandle).toMessagePipeHandle());
+        InterfaceRegistrar.Registry.applyRenderFrameHostRegistrars(registry, renderFrameHost);
+    }
+
     private static void ensureContentRegistrarsAreRegistered() {
         if (sHasRegisteredRegistrars) return;
         sHasRegisteredRegistrars = true;
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
index 90b9740..8a4526a9 100644
--- a/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/framehost/RenderFrameHostImpl.java
@@ -35,6 +35,11 @@
         mNativeRenderFrameHostAndroid = 0;
     }
 
+    /**
+     * Get the delegate associated with this RenderFrameHost.
+     *
+     * @return The delegate associated with this RenderFrameHost.
+     */
     public RenderFrameHostDelegate getRenderFrameHostDelegate() {
         return mDelegate;
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index 0f8738e..b942f907 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -21,7 +21,6 @@
 import org.chromium.content.browser.AppWebMessagePort;
 import org.chromium.content.browser.MediaSessionImpl;
 import org.chromium.content.browser.framehost.RenderFrameHostDelegate;
-import org.chromium.content.browser.framehost.RenderFrameHostImpl;
 import org.chromium.content_public.browser.AccessibilitySnapshotCallback;
 import org.chromium.content_public.browser.AccessibilitySnapshotNode;
 import org.chromium.content_public.browser.ContentBitmapCallback;
@@ -96,14 +95,6 @@
                 }
             };
 
-    public static WebContents fromRenderFrameHost(RenderFrameHost rfh) {
-        RenderFrameHostDelegate delegate = ((RenderFrameHostImpl) rfh).getRenderFrameHostDelegate();
-        if (delegate == null || !(delegate instanceof WebContents)) {
-            return null;
-        }
-        return (WebContents) delegate;
-    }
-
     private long mNativeWebContentsAndroid;
     private NavigationController mNavigationController;
     private RenderFrameHost mMainFrame;
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/InterfaceRegistrar.java b/content/public/android/java/src/org/chromium/content_public/browser/InterfaceRegistrar.java
index 45b3ffe0..131260b 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/InterfaceRegistrar.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/InterfaceRegistrar.java
@@ -25,6 +25,7 @@
     public static class Registry<ParamType> {
         private static Registry<Context> sContextRegistry;
         private static Registry<WebContents> sWebContentsRegistry;
+        private static Registry<RenderFrameHost> sRenderFrameHostRegistry;
 
         private List<InterfaceRegistrar<ParamType>> mRegistrars =
                 new ArrayList<InterfaceRegistrar<ParamType>>();
@@ -45,6 +46,14 @@
             sWebContentsRegistry.applyRegistrars(interfaceRegistry, webContents);
         }
 
+        public static void applyRenderFrameHostRegistrars(
+                InterfaceRegistry interfaceRegistry, RenderFrameHost renderFrameHost) {
+            if (sRenderFrameHostRegistry == null) {
+                return;
+            }
+            sRenderFrameHostRegistry.applyRegistrars(interfaceRegistry, renderFrameHost);
+        }
+
         public static void addContextRegistrar(InterfaceRegistrar<Context> registrar) {
             if (sContextRegistry == null) {
                 sContextRegistry = new Registry<Context>();
@@ -59,6 +68,14 @@
             sWebContentsRegistry.addRegistrar(registrar);
         }
 
+        public static void addRenderFrameHostRegistrar(
+                InterfaceRegistrar<RenderFrameHost> registrar) {
+            if (sRenderFrameHostRegistry == null) {
+                sRenderFrameHostRegistry = new Registry<RenderFrameHost>();
+            }
+            sRenderFrameHostRegistry.addRegistrar(registrar);
+        }
+
         private Registry() {}
 
         private void addRegistrar(InterfaceRegistrar<ParamType> registrar) {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContentsStatics.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsStatics.java
new file mode 100644
index 0000000..ef580b17
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContentsStatics.java
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content_public.browser;
+
+import org.chromium.content.browser.framehost.RenderFrameHostDelegate;
+import org.chromium.content.browser.framehost.RenderFrameHostImpl;
+
+/**
+ * Static public methods for WebContents.
+ */
+public class WebContentsStatics {
+    /**
+     * @return The WebContens associated witht the RenderFrameHost. This can be null.
+     */
+    public static WebContents fromRenderFrameHost(RenderFrameHost rfh) {
+        RenderFrameHostDelegate delegate = ((RenderFrameHostImpl) rfh).getRenderFrameHostDelegate();
+        if (delegate == null || !(delegate instanceof WebContents)) {
+            return null;
+        }
+        return (WebContents) delegate;
+    }
+}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java
index 508a224..6b01ef2 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java
@@ -20,6 +20,7 @@
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.WebContentsStatics;
 import org.chromium.content_shell.Shell;
 import org.chromium.content_shell_apk.ContentShellActivity;
 import org.chromium.content_shell_apk.ContentShellActivityTestRule;
@@ -355,7 +356,8 @@
                 Assert.assertEquals("RenderFrameHost has incorrect last committed URL", TEST_URL_2,
                         frameHost.getLastCommittedURL());
 
-                WebContents associatedWebContents = WebContentsImpl.fromRenderFrameHost(frameHost);
+                WebContents associatedWebContents =
+                        WebContentsStatics.fromRenderFrameHost(frameHost);
                 Assert.assertEquals("RenderFrameHost associated with different WebContents",
                         webContents, associatedWebContents);
             }
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 78a5d95..0b21bea8 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -9,6 +9,7 @@
           "ui::mojom::Gpu"
         ],
         "renderer": [
+          "blink::mojom::BackgroundFetchService",
           "blink::mojom::BackgroundSyncService",
           "blink::mojom::BroadcastChannelProvider",
           "blink::mojom::BudgetService",
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index 4bb87a6..8e0425ad 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -224,6 +224,14 @@
   // RenderFrame. See BindingsPolicy for details.
   virtual int GetEnabledBindings() const = 0;
 
+#if defined(OS_ANDROID)
+  // Returns an InterfaceProvider for Java-implemented interfaces that are
+  // scoped to this RenderFrameHost. This provides access to interfaces
+  // implemented in Java in the browser process to C++ code in the browser
+  // process.
+  virtual service_manager::InterfaceProvider* GetJavaInterfaces() = 0;
+#endif  // OS_ANDROID
+
  private:
   // This interface should only be implemented inside content.
   friend class RenderFrameHostImpl;
diff --git a/content/test/data/device_sensors/device_orientation_absolute_null_test.html b/content/test/data/device_sensors/device_orientation_absolute_null_test.html
new file mode 100644
index 0000000..266ef00d
--- /dev/null
+++ b/content/test/data/device_sensors/device_orientation_absolute_null_test.html
@@ -0,0 +1,31 @@
+<html>
+  <head>
+    <title>DeviceOrientationAbsolute all-null event test</title>
+  </head>
+  <body>
+    <div id="status">FAIL</div>
+  </body>
+  <script type="text/javascript">
+    function checkOrientationAbsoluteEvent(event) {
+      return event.alpha == null &&
+             event.beta == null &&
+             event.gamma == null;
+    }
+
+    function onOrientationAbsolute(event) {
+      window.removeEventListener('deviceorientationabsolute', onOrientationAbsolute);
+      checkOrientationAbsoluteEvent(event) ? pass() : fail();
+    }
+
+    function pass() {
+      document.getElementById('status').innerHTML = 'PASS';
+      document.location = '#pass';
+    }
+
+    function fail() {
+      document.location = '#fail';
+    }
+
+    window.addEventListener('deviceorientationabsolute', onOrientationAbsolute);
+  </script>
+</html>
diff --git a/content/test/data/device_sensors/device_orientation_absolute_test.html b/content/test/data/device_sensors/device_orientation_absolute_test.html
new file mode 100644
index 0000000..d35f18f
--- /dev/null
+++ b/content/test/data/device_sensors/device_orientation_absolute_test.html
@@ -0,0 +1,35 @@
+<html>
+  <head>
+    <title>DeviceOrientationAbsolute test</title>
+    <script type="text/javascript">
+      function checkOrientationAbsoluteEvent(event) {
+        // Return true iff the orientation is close enough to (4, 5, 6).
+        return Math.abs(event.alpha - 4) < 0.01 &&
+               Math.abs(event.beta  - 5) < 0.01 &&
+               Math.abs(event.gamma - 6) < 0.01 &&
+               event.absolute == true;
+      }
+
+      function onOrientationAbsolute(event) {
+        if (checkOrientationAbsoluteEvent(event)) {
+          window.removeEventListener('deviceorientationabsolute', onOrientationAbsolute);
+          pass();
+        } else {
+          fail();
+        }
+      }
+
+      function pass() {
+        document.getElementById('status').innerHTML = 'PASS';
+        document.location = '#pass';
+      }
+
+      function fail() {
+        document.location = '#fail';
+      }
+    </script>
+  </head>
+  <body onLoad="window.addEventListener('deviceorientationabsolute', onOrientationAbsolute)">
+    <div id="status">FAIL</div>
+  </body>
+</html>
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index b2f53d0..015debfd 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -1619,6 +1619,15 @@
         'disabled_instrumentation_types': ['tsan'],
       }
     ],
+    'disabled_tester_configs': [
+      {
+        # The Mac ASAN swarming runs on two different GPU types so we can't
+        # have one expected vendor ID / device ID
+        'names': [
+          'Mac GPU ASAN Release',
+        ],
+      },
+    ],
   },
   'maps_pixel_test': {
     'target_name': 'maps',
@@ -1728,6 +1737,7 @@
         # Run this on the FYI waterfall and optional tryservers.
         'predicate': Predicates.FYI_AND_OPTIONAL,
         'os_types': ['win'],
+        'disabled_instrumentation_types': ['tsan'],
       }
     ],
     'disabled_tester_configs': [
@@ -1749,6 +1759,7 @@
         # Run this on the FYI waterfall and optional tryservers.
         'predicate': Predicates.FYI_AND_OPTIONAL,
         'os_types': ['win'],
+        'disabled_instrumentation_types': ['tsan'],
       }
     ],
     'disabled_tester_configs': [
@@ -1818,6 +1829,7 @@
         # Run this on the FYI waterfall and optional tryservers.
         'predicate': Predicates.FYI_AND_OPTIONAL,
         'os_types': ['win'],
+        'disabled_instrumentation_types': ['tsan'],
       }
     ],
     'disabled_tester_configs': [
@@ -1846,6 +1858,7 @@
         # Run this on the FYI waterfall and optional tryservers.
         'predicate': Predicates.FYI_AND_OPTIONAL,
         'os_types': ['linux'],
+        'disabled_instrumentation_types': ['tsan'],
       }
     ],
     'disabled_tester_configs': [
@@ -1967,6 +1980,7 @@
             'os': 'Windows-2008ServerR2-SP1'
           },
         ],
+        'disabled_instrumentation_types': ['tsan'],
       },
     ],
     'disabled_tester_configs': [
diff --git a/device/bluetooth/README.md b/device/bluetooth/README.md
index 7ccda1f..f3c0ed89 100644
--- a/device/bluetooth/README.md
+++ b/device/bluetooth/README.md
@@ -1,5 +1,4 @@
-Bluetooth
-=========
+# Bluetooth
 
 `device/bluetooth` abstracts
 [Bluetooth Classic](https://en.wikipedia.org/wiki/Bluetooth) and
@@ -20,9 +19,12 @@
 
 Chrome OS and Linux are supported via BlueZ, see `*_bluez` files.
 
+[Mojo](https://www.chromium.org/developers/design-documents/mojo)
+interfaces in [public/interfaces](public/interfaces) have been started
+but are *not* ready for production use.
 
-Maintainer History
---------------------------------------------------------------------------------
+
+## Maintainer History
 
 Initial implementation OWNERS were youngki@chromium.org, keybuk@chromium.org,
 armansito@chromium.org, and rpaquay@chromium.org. They no longer contribute to
@@ -42,8 +44,7 @@
 [Refactoring meta issue](https://crbug.com/580406).
 
 
-Testing
---------------------------------------------------------------------------------
+## Testing
 
 Implementation of the Bluetooth component is tested via unittests. Client code
 uses Mock Bluetooth objects:
@@ -93,8 +94,7 @@
 https://chromium.googlesource.com/chromiumos/third_party/autotest/+/master/client/cros/bluetooth/
 
 
-Android
---------------------------------------------------------------------------------
+## Android
 
 The android implementation requires crossing from C++ to Java using
 [__JNI__](https://www.chromium.org/developers/design-documents/android-jni).
@@ -130,8 +130,8 @@
 
 [Class]: https://sites.google.com/a/chromium.org/dev/developers/design-documents/bluetooth-design-docs/web-bluetooth-through-bluetooth-android-class-diagram
 
-Design Documents
---------------------------------------------------------------------------------
+
+## Design Documents
 
 * [Bluetooth Notifications](https://docs.google.com/document/d/1guBtAnQUP8ZoZre4VQGrjR5uX0ZYxfK-lwKNeqY0-z4/edit?usp=sharing) 2016-08-26
     * Web Bluetooth through Android implementation details, class diagram and
diff --git a/device/bluetooth/public/interfaces/README.md b/device/bluetooth/public/interfaces/README.md
new file mode 100644
index 0000000..cd9758c
--- /dev/null
+++ b/device/bluetooth/public/interfaces/README.md
@@ -0,0 +1,15 @@
+# Bluetooth
+
+Interfaces providing cross platform abstraction of [Bluetooth](../..).
+
+## Note
+
+These interfaces are NOT yet ready for production use by
+other components. They are a start at a large task of producing
+a service for device/bluetooth. Work was scoped to the miniumum
+required to enable
+[chrome://bluetooth-internals page][InternalsDesignDoc], and
+long term design and testing were minimized to accomplish that.
+
+[InternalsDesignDoc]: https://docs.google.com/document/d/1wa96bCrB2Iw7tTI-fWsKmhLB7_ffF12frGIjRvhaj9E/edit#heading=h.2j0b11w2a292
+
diff --git a/extensions/browser/api/extensions_api_client.cc b/extensions/browser/api/extensions_api_client.cc
index b9cb075..1d183bd 100644
--- a/extensions/browser/api/extensions_api_client.cc
+++ b/extensions/browser/api/extensions_api_client.cc
@@ -103,6 +103,11 @@
   return nullptr;
 }
 
+NetworkingCastPrivateDelegate*
+ExtensionsAPIClient::GetNetworkingCastPrivateDelegate() {
+  return nullptr;
+}
+
 #if defined(OS_CHROMEOS)
 NonNativeFileSystemDelegate*
 ExtensionsAPIClient::GetNonNativeFileSystemDelegate() {
diff --git a/extensions/browser/api/extensions_api_client.h b/extensions/browser/api/extensions_api_client.h
index be47c88..e61cc0c 100644
--- a/extensions/browser/api/extensions_api_client.h
+++ b/extensions/browser/api/extensions_api_client.h
@@ -38,6 +38,7 @@
 class MetricsPrivateDelegate;
 class MimeHandlerViewGuest;
 class MimeHandlerViewGuestDelegate;
+class NetworkingCastPrivateDelegate;
 class NonNativeFileSystemDelegate;
 class RulesCacheDelegate;
 class SettingsObserver;
@@ -132,6 +133,9 @@
   // MetricsPrivateAPI behavior.
   virtual MetricsPrivateDelegate* GetMetricsPrivateDelegate();
 
+  // Creates a delegate for networking.castPrivate's API behavior.
+  virtual NetworkingCastPrivateDelegate* GetNetworkingCastPrivateDelegate();
+
 #if defined(OS_CHROMEOS)
   // If supported by the embedder, returns a delegate for querying non-native
   // file systems.
diff --git a/extensions/browser/api/networking_private/BUILD.gn b/extensions/browser/api/networking_private/BUILD.gn
index b2b5f73..a362879 100644
--- a/extensions/browser/api/networking_private/BUILD.gn
+++ b/extensions/browser/api/networking_private/BUILD.gn
@@ -6,6 +6,7 @@
 
 source_set("networking_private") {
   sources = [
+    "networking_cast_delegate.h",
     "networking_private_api.cc",
     "networking_private_api.h",
     "networking_private_chromeos.cc",
diff --git a/extensions/browser/api/networking_private/networking_cast_private_delegate.h b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
new file mode 100644
index 0000000..a7704ac
--- /dev/null
+++ b/extensions/browser/api/networking_private/networking_cast_private_delegate.h
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_NETWORKING_PRIVATE_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+#define EXTENSIONS_BROWSER_API_NETWORKING_PRIVATE_NETWORKING_CAST_PRIVATE_DELEGATE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "extensions/common/api/networking_private.h"
+
+namespace extensions {
+
+// Delegate interface that provides crypto methods needed to verify cast
+// certificates and encrypt data using public key derived from the verified
+// certificate.
+// TODO(tbarzic): This is to be used during migration of
+//     networkingPrivate.verify* methods to networking.castPrivate API to share
+//     verification logic shared between networkingPrivate and
+//     networking.castPrivate API. When the deprecated networkingPrivate methods
+//     are removed, this interface should be removed, too.
+class NetworkingCastPrivateDelegate {
+ public:
+  virtual ~NetworkingCastPrivateDelegate() {}
+
+  using FailureCallback = base::Callback<void(const std::string& error)>;
+  using VerifiedCallback = base::Callback<void(bool is_valid)>;
+  using DataCallback = base::Callback<void(const std::string& encrypted_data)>;
+
+  // Verifies that data provided in |properties| authenticates a cast device.
+  virtual void VerifyDestination(
+      const api::networking_private::VerificationProperties& properties,
+      const VerifiedCallback& success_callback,
+      const FailureCallback& failure_callback) = 0;
+
+  // Verifies that data provided in |properties| authenticates a cast device.
+  // If the device is verified as a cast device, it fetches credentials of the
+  // network identified with |network_guid| and returns the network credentials
+  // encrypted with a public key derived from |properties|.
+  virtual void VerifyAndEncryptCredentials(
+      const std::string& network_guid,
+      const api::networking_private::VerificationProperties& properties,
+      const DataCallback& encrypted_credetials_callback,
+      const FailureCallback& failure_callback) = 0;
+
+  // Verifies that data provided in |properties| authenticates a cast device.
+  // If the device is verified as a cast device, it returns |data| encrypted
+  // with a public key derived from |properties|.
+  virtual void VerifyAndEncryptData(
+      const std::string& data,
+      const api::networking_private::VerificationProperties& properties,
+      const DataCallback& enrypted_data_callback,
+      const FailureCallback& failure_callback) = 0;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_NETWORKING_PRIVATE_NETWORKING_CAST_PRIVATE_DELEGATE_H_
diff --git a/extensions/browser/api/networking_private/networking_private_delegate.h b/extensions/browser/api/networking_private/networking_private_delegate.h
index a682742..66b1f12 100644
--- a/extensions/browser/api/networking_private/networking_private_delegate.h
+++ b/extensions/browser/api/networking_private/networking_private_delegate.h
@@ -19,13 +19,6 @@
 
 class NetworkingPrivateDelegateObserver;
 
-namespace api {
-namespace networking_private {
-struct DeviceStateProperties;
-struct VerificationProperties;
-}  // networking_private
-}  // api
-
 // Base class for platform dependent networkingPrivate API implementations.
 // All inputs and results for this class use ONC values. See
 // networking_private.idl for descriptions of the expected inputs and results.
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index fd51439..3d5bc42 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1222,6 +1222,11 @@
   AUDIO_SETMUTE,
   AUDIO_GETDEVICES,
   VIRTUALKEYBOARD_RESTRICTFEATURES,
+  NETWORKINGCASTPRIVATE_VERIFYDESTINATION,
+  NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTCREDENTIALS,
+  NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTDATA,
+  NETWORKINGCASTPRIVATE_SETWIFITDLSENABLEDSTATE,
+  NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl
index 6bbe086..3cd81883 100644
--- a/extensions/common/api/networking_private.idl
+++ b/extensions/common/api/networking_private.idl
@@ -961,6 +961,7 @@
     //     is a trusted device.
     // |callback|: A callback function that indicates whether or not the device
     //     is a trusted device.
+    [nodoc, deprecated = "Use networking.castPrivate API."]
     static void verifyDestination(VerificationProperties properties,
                                   BooleanCallback callback);
 
@@ -971,6 +972,7 @@
     // |networkGuid|: The GUID of the Cellular network to activate.
     // |callback|: A callback function that receives base64-encoded encrypted
     //     credential data to send to a trusted device.
+    [nodoc, deprecated = "Use networking.castPrivate API."]
     static void verifyAndEncryptCredentials(VerificationProperties properties,
                                             DOMString networkGuid,
                                             StringCallback callback);
@@ -982,6 +984,7 @@
     // |data|: A string containing the base64-encoded data to encrypt.
     // |callback|: A callback function that receives base64-encoded encrypted
     //     data to send to a trusted device.
+    [nodoc, deprecated = "Use networking.castPrivate API."]
     static void verifyAndEncryptData(VerificationProperties properties,
                                      DOMString data,
                                      StringCallback callback);
@@ -995,6 +998,7 @@
     //     (e.g. MAC address lookup failed). 'Timeout' indicates that the lookup
     //     timed out. Otherwise a valid status is returned (see
     //     $(ref:getWifiTDLSStatus)).
+    [nodoc, deprecated = "Use networking.castPrivate API."]
     static void setWifiTDLSEnabledState(DOMString ip_or_mac_address,
                                         boolean enabled,
                                         optional StringCallback callback);
@@ -1004,6 +1008,7 @@
     // |callback|: A callback function that receives a string with the current
     //     TDLS status which can be 'Connected', 'Disabled', 'Disconnected',
     //     'Nonexistent', or 'Unknown'.
+    [nodoc, deprecated = "Use networking.castPrivate API."]
     static void getWifiTDLSStatus(DOMString ip_or_mac_address,
                                   StringCallback callback);
 
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index 5c6f069..267ad25 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -243,6 +243,7 @@
     kClipboard,
     kNetworkingOnc,
     kVirtualKeyboard,
+    kNetworkingCastPrivate,
     // Last entry: Add new entries above and ensure to update the
     // "ExtensionPermission3" enum in tools/metrics/histograms/histograms.xml
     // (by running update_extension_permission.py).
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
index 02577800..ae1102c 100644
--- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
+++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
@@ -18,8 +18,8 @@
 #import "ios/chrome/browser/passwords/password_generation_utils.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/web/public/url_scheme_util.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
 #include "ios/web/public/web_state/web_state.h"
 #include "url/gurl.h"
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller.mm b/ios/chrome/browser/autofill/form_suggestion_controller.mm
index 343c368..3e96631 100644
--- a/ios/chrome/browser/autofill/form_suggestion_controller.mm
+++ b/ios/chrome/browser/autofill/form_suggestion_controller.mm
@@ -21,8 +21,8 @@
 #import "ios/chrome/browser/passwords/password_generation_utils.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/web/public/url_scheme_util.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/web_state.h"
 
 namespace {
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm b/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm
index 3d09d21..e65903e 100644
--- a/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm
+++ b/ios/chrome/browser/autofill/form_suggestion_controller_unittest.mm
@@ -16,7 +16,7 @@
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/web/chrome_web_test.h"
 #include "ios/chrome/test/base/scoped_block_swizzler.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 #import "testing/gtest_mac.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
diff --git a/ios/chrome/browser/context_menu/context_menu_egtest.mm b/ios/chrome/browser/context_menu/context_menu_egtest.mm
index 3e021534..3d29a73b1 100644
--- a/ios/chrome/browser/context_menu/context_menu_egtest.mm
+++ b/ios/chrome/browser/context_menu/context_menu_egtest.mm
@@ -189,9 +189,7 @@
 // Tests "Open in New Tab" on context menu  on a link that requires scrolling
 // on the page to verify that context menu can be properly triggered in the
 // current screen view.
-// TODO(crbug.com/701104): This test is flaky because sometimes it doesn't
-// scroll down far enough for the link to be visible.
-- (void)FLAKY_testContextMenuOpenInNewTabFromTallPage {
+- (void)testContextMenuOpenInNewTabFromTallPage {
   // Set up test simple http server.
   std::map<GURL, std::string> responses;
   GURL initialURL =
@@ -211,10 +209,20 @@
   chrome_test_util::AssertMainTabCount(1U);
 
   // Scroll down on the web view to make the link visible.
+  // grey_swipeFastInDirecton will quickly scroll towards the bottom, and then
+  // grey_scrollToContentEdge guarantees the content edge is reached. Two
+  // methods are used because the first one is much faster, but doesn't
+  // guarantee the link becomes visible.
+  // TODO(crbug.com/702272): Try to replace this with one EarlGrey method call.
   [[EarlGrey
       selectElementWithMatcher:WebViewScrollView(
                                    chrome_test_util::GetCurrentWebState())]
       performAction:grey_swipeFastInDirection(kGREYDirectionUp)];
+  [[EarlGrey
+      selectElementWithMatcher:WebViewScrollView(
+                                   chrome_test_util::GetCurrentWebState())]
+      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
+
   [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewContainingText(
                                           kDestinationLinkID)]
       assertWithMatcher:grey_notNil()];
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index 5b019f4..b3b4af4d8 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -76,9 +76,6 @@
 // Whether the Payment Request API is enabled or not.
 bool IsPaymentRequestEnabled();
 
-// Whether the back-forward navigation uses pending index.
-bool IsPendingIndexNavigationEnabled();
-
 // Whether the Physical Web feature is enabled.
 bool IsPhysicalWebEnabled();
 
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index 83cd531..6d6ef708 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -41,8 +41,6 @@
     @"HeuristicsForPasswordGeneration";
 NSString* const kMDMIntegrationDisabled = @"MDMIntegrationDisabled";
 NSString* const kOriginServerHost = @"AlternateOriginServerHost";
-NSString* const kPendingIndexNavigationDisabled =
-    @"PendingIndexNavigationDisabled";
 NSString* const kSafariVCSignInDisabled = @"SafariVCSignInDisabled";
 NSString* const kWhatsNewPromoStatus = @"WhatsNewPromoStatus";
 
@@ -201,11 +199,6 @@
                           base::CompareCase::INSENSITIVE_ASCII);
 }
 
-bool IsPendingIndexNavigationEnabled() {
-  return ![[NSUserDefaults standardUserDefaults]
-      boolForKey:kPendingIndexNavigationDisabled];
-}
-
 bool IsPhysicalWebEnabled() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (command_line->HasSwitch(switches::kEnableIOSPhysicalWeb)) {
diff --git a/ios/chrome/browser/find_in_page/find_in_page_controller.mm b/ios/chrome/browser/find_in_page/find_in_page_controller.mm
index 692d7f6e..18ac00f4 100644
--- a/ios/chrome/browser/find_in_page/find_in_page_controller.mm
+++ b/ios/chrome/browser/find_in_page/find_in_page_controller.mm
@@ -14,9 +14,9 @@
 #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
 #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h"
 #import "ios/chrome/browser/web/dom_altering_lock.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 
diff --git a/ios/chrome/browser/find_in_page/find_in_page_js_unittest.mm b/ios/chrome/browser/find_in_page/find_in_page_js_unittest.mm
index 38cd267..06398da8 100644
--- a/ios/chrome/browser/find_in_page/find_in_page_js_unittest.mm
+++ b/ios/chrome/browser/find_in_page/find_in_page_js_unittest.mm
@@ -10,8 +10,8 @@
 #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
 #import "ios/chrome/browser/find_in_page/js_findinpage_manager.h"
 #import "ios/chrome/browser/web/chrome_web_test.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/web_state.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
diff --git a/ios/chrome/browser/payments/payment_request.h b/ios/chrome/browser/payments/payment_request.h
index bfcec31..1ab57eb 100644
--- a/ios/chrome/browser/payments/payment_request.h
+++ b/ios/chrome/browser/payments/payment_request.h
@@ -94,6 +94,13 @@
     return shipping_profiles_;
   }
 
+  const std::vector<std::string>& supported_card_networks() const {
+    return supported_card_networks_;
+  }
+
+  // Adds |credit_card| to the list of cached credit cards.
+  void AddCreditCard(std::unique_ptr<autofill::CreditCard> credit_card);
+
   // Returns the available autofill credit cards for this user that match a
   // supported type specified in |web_payment_request_|.
   const std::vector<autofill::CreditCard*>& credit_cards() const {
@@ -167,6 +174,9 @@
   std::vector<autofill::CreditCard*> credit_cards_;
   autofill::CreditCard* selected_credit_card_;
 
+  // A vector of supported basic card networks.
+  std::vector<std::string> supported_card_networks_;
+
   // A vector of pointers to the shipping options in |web_payment_request_|.
   std::vector<web::PaymentShippingOption*> shipping_options_;
   web::PaymentShippingOption* selected_shipping_option_;
diff --git a/ios/chrome/browser/payments/payment_request.mm b/ios/chrome/browser/payments/payment_request.mm
index 68e0830..9d2109b 100644
--- a/ios/chrome/browser/payments/payment_request.mm
+++ b/ios/chrome/browser/payments/payment_request.mm
@@ -4,8 +4,7 @@
 
 #include "ios/chrome/browser/payments/payment_request.h"
 
-#include <unordered_set>
-
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
@@ -53,6 +52,12 @@
   return currency_formatter_.get();
 }
 
+void PaymentRequest::AddCreditCard(
+    std::unique_ptr<autofill::CreditCard> credit_card) {
+  credit_card_cache_.insert(credit_card_cache_.begin(), std::move(credit_card));
+  credit_cards_.insert(credit_cards_.begin(), credit_card_cache_.front().get());
+}
+
 void PaymentRequest::PopulateProfileCache() {
   for (const auto* profile : personal_data_manager_->GetProfilesToSuggest()) {
     profile_cache_.push_back(
@@ -73,10 +78,14 @@
 
 void PaymentRequest::PopulateCreditCardCache() {
   DCHECK(web_payment_request_);
-  std::unordered_set<base::string16> supported_method_types;
   for (const auto& method_data : web_payment_request_->method_data) {
-    for (const auto& supported_method : method_data.supported_methods)
-      supported_method_types.insert(supported_method);
+    for (const auto& supported_method : method_data.supported_methods) {
+      // Reject non-ASCII supported methods.
+      if (base::IsStringASCII(supported_method)) {
+        supported_card_networks_.push_back(
+            base::UTF16ToASCII(supported_method));
+      }
+    }
   }
 
   std::vector<autofill::CreditCard*> credit_cards =
@@ -91,8 +100,9 @@
     std::string spec_card_type =
         autofill::data_util::GetPaymentRequestData(credit_card->type())
             .basic_card_payment_type;
-    if (supported_method_types.find(base::ASCIIToUTF16(spec_card_type)) !=
-        supported_method_types.end()) {
+    if (std::find(supported_card_networks_.begin(),
+                  supported_card_networks_.end(),
+                  spec_card_type) != supported_card_networks_.end()) {
       credit_card_cache_.push_back(
           base::MakeUnique<autofill::CreditCard>(*credit_card));
       credit_cards_.push_back(credit_card_cache_.back().get());
diff --git a/ios/chrome/browser/payments/payment_request_manager.mm b/ios/chrome/browser/payments/payment_request_manager.mm
index 95359fd..2b5f6c2 100644
--- a/ios/chrome/browser/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/payments/payment_request_manager.mm
@@ -27,8 +27,8 @@
 #include "ios/web/public/payments/payment_request.h"
 #include "ios/web/public/ssl_status.h"
 #import "ios/web/public/url_scheme_util.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
 #include "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
diff --git a/ios/chrome/browser/payments/payment_request_unittest.mm b/ios/chrome/browser/payments/payment_request_unittest.mm
index 3e3470f..651404b 100644
--- a/ios/chrome/browser/payments/payment_request_unittest.mm
+++ b/ios/chrome/browser/payments/payment_request_unittest.mm
@@ -8,6 +8,7 @@
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/payments/core/currency_formatter.h"
 #include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/payments/payment_request_test_util.h"
 #include "ios/web/public/payments/payment_request.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,36 +21,71 @@
 TEST(PaymentRequestTest, CreatesCurrencyFormatterCorrectly) {
   ASSERT_EQ("en", GetApplicationContext()->GetApplicationLocale());
 
+  web::PaymentRequest web_payment_request;
   autofill::TestPersonalDataManager personal_data_manager;
 
-  std::unique_ptr<web::PaymentRequest> web_payment_request =
-      base::MakeUnique<web::PaymentRequest>();
-  web_payment_request->details.total.amount.currency =
-      base::ASCIIToUTF16("USD");
-  PaymentRequest payment_request1(std::move(web_payment_request),
-                                  &personal_data_manager);
+  web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("USD");
+  PaymentRequest payment_request1(
+      base::MakeUnique<web::PaymentRequest>(web_payment_request),
+      &personal_data_manager);
   payments::CurrencyFormatter* currency_formatter =
       payment_request1.GetOrCreateCurrencyFormatter();
-  ASSERT_EQ(base::UTF8ToUTF16("$55.00"), currency_formatter->Format("55.00"));
-  ASSERT_EQ("USD", currency_formatter->formatted_currency_code());
+  EXPECT_EQ(base::UTF8ToUTF16("$55.00"), currency_formatter->Format("55.00"));
+  EXPECT_EQ("USD", currency_formatter->formatted_currency_code());
 
-  web_payment_request = base::MakeUnique<web::PaymentRequest>();
-  web_payment_request->details.total.amount.currency =
-      base::ASCIIToUTF16("JPY");
-  PaymentRequest payment_request2(std::move(web_payment_request),
-                                  &personal_data_manager);
+  web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("JPY");
+  PaymentRequest payment_request2(
+      base::MakeUnique<web::PaymentRequest>(web_payment_request),
+      &personal_data_manager);
   currency_formatter = payment_request2.GetOrCreateCurrencyFormatter();
-  ASSERT_EQ(base::UTF8ToUTF16("¥55"), currency_formatter->Format("55.00"));
-  ASSERT_EQ("JPY", currency_formatter->formatted_currency_code());
+  EXPECT_EQ(base::UTF8ToUTF16("¥55"), currency_formatter->Format("55.00"));
+  EXPECT_EQ("JPY", currency_formatter->formatted_currency_code());
 
-  web_payment_request = base::MakeUnique<web::PaymentRequest>();
-  web_payment_request->details.total.amount.currency_system =
+  web_payment_request.details.total.amount.currency_system =
       base::ASCIIToUTF16("NOT_ISO4217");
-  web_payment_request->details.total.amount.currency =
-      base::ASCIIToUTF16("USD");
-  PaymentRequest payment_request3(std::move(web_payment_request),
-                                  &personal_data_manager);
+  web_payment_request.details.total.amount.currency = base::ASCIIToUTF16("USD");
+  PaymentRequest payment_request3(
+      base::MakeUnique<web::PaymentRequest>(web_payment_request),
+      &personal_data_manager);
   currency_formatter = payment_request3.GetOrCreateCurrencyFormatter();
-  ASSERT_EQ(base::UTF8ToUTF16("55.00"), currency_formatter->Format("55.00"));
-  ASSERT_EQ("USD", currency_formatter->formatted_currency_code());
+  EXPECT_EQ(base::UTF8ToUTF16("55.00"), currency_formatter->Format("55.00"));
+  EXPECT_EQ("USD", currency_formatter->formatted_currency_code());
+}
+
+// Tests that the accepted card networks are identified correctly.
+TEST(PaymentRequestTest, AcceptedPaymentNetworks) {
+  web::PaymentRequest web_payment_request;
+  autofill::TestPersonalDataManager personal_data_manager;
+
+  web::PaymentMethodData method_datum1;
+  method_datum1.supported_methods.push_back(base::ASCIIToUTF16("visa"));
+  web_payment_request.method_data.push_back(method_datum1);
+  web::PaymentMethodData method_datum2;
+  method_datum2.supported_methods.push_back(base::ASCIIToUTF16("mastercard"));
+  web_payment_request.method_data.push_back(method_datum2);
+
+  PaymentRequest payment_request(
+      base::MakeUnique<web::PaymentRequest>(web_payment_request),
+      &personal_data_manager);
+  ASSERT_EQ(2U, payment_request.supported_card_networks().size());
+  EXPECT_EQ("visa", payment_request.supported_card_networks()[0]);
+  EXPECT_EQ("mastercard", payment_request.supported_card_networks()[1]);
+}
+
+// Tests that credit cards can be added to the list of cached credit cards.
+TEST(PaymentRequestTest, AddCreditCard) {
+  web::PaymentRequest web_payment_request;
+  autofill::TestPersonalDataManager personal_data_manager;
+
+  PaymentRequest payment_request(
+      base::MakeUnique<web::PaymentRequest>(web_payment_request),
+      &personal_data_manager);
+  EXPECT_EQ(0U, payment_request.credit_cards().size());
+
+  std::unique_ptr<autofill::CreditCard> credit_card =
+      payment_request_test_util::CreateTestCreditCard();
+  const autofill::CreditCard* added_credit_card = credit_card.get();
+  payment_request.AddCreditCard(std::move(credit_card));
+  ASSERT_EQ(1U, payment_request.credit_cards().size());
+  EXPECT_EQ(added_credit_card, payment_request.credit_cards()[0]);
 }
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index 21aaa2e..6207de6 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -6,16 +6,6 @@
 	<array>
 		<dict>
 			<key>Type</key>
-			<string>PSToggleSwitchSpecifier</string>
-			<key>Title</key>
-			<string>Disable pending index navigation</string>
-			<key>Key</key>
-			<string>PendingIndexNavigationDisabled</string>
-			<key>DefaultValue</key>
-			<false/>
-		</dict>
-		<dict>
-			<key>Type</key>
 			<string>PSMultiValueSpecifier</string>
 			<key>Title</key>
 			<string>Enable SnapshotLRUCache</string>
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 7cbcff3..ee076d83 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -1319,10 +1319,6 @@
   return NO;
 }
 
-- (void)webWillFinishHistoryNavigation {
-  [parentTabModel_ notifyTabChanged:self];
-}
-
 - (void)webState:(web::WebState*)webState
     didFinishNavigation:(web::NavigationContext*)navigation {
   if (navigation->IsSameDocument()) {
diff --git a/ios/chrome/browser/ui/DEPS b/ios/chrome/browser/ui/DEPS
index 0a1586ac..1362209 100644
--- a/ios/chrome/browser/ui/DEPS
+++ b/ios/chrome/browser/ui/DEPS
@@ -24,13 +24,13 @@
 
   # TODO(crbug.com/620143): Remove these exceptions.
   "^fullscreen_controller_unittest\.mm$": [
-    "+ios/web/web_state/crw_web_view_proxy_impl.h",
+    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
     "+ios/web/web_state/ui/crw_web_controller.h",
   ],
 
   # TODO(crbug.com/620139): Remove these exceptions.
   "^fullscreen_controller_unittest\.mm$": [
-    "+ios/web/web_state/crw_web_view_proxy_impl.h",
+    "+ios/web/web_state/ui/crw_web_view_proxy_impl.h",
     "+ios/web/web_state/ui/crw_web_controller.h",
   ],
 
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 976ed05..7bb68675 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -183,8 +183,8 @@
 #include "ios/web/public/user_agent.h"
 #include "ios/web/public/web_client.h"
 #import "ios/web/public/web_state/context_menu_params.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/ui/crw_native_content_provider.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #include "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_delegate_bridge.h"
 #include "ios/web/public/web_thread.h"
diff --git a/ios/chrome/browser/ui/contextual_search/contextual_search_controller.mm b/ios/chrome/browser/ui/contextual_search/contextual_search_controller.mm
index 39bc9d8..cc6aacd 100644
--- a/ios/chrome/browser/ui/contextual_search/contextual_search_controller.mm
+++ b/ios/chrome/browser/ui/contextual_search/contextual_search_controller.mm
@@ -50,9 +50,9 @@
 #include "ios/web/public/browser_state.h"
 #include "ios/web/public/load_committed_details.h"
 #include "ios/web/public/referrer.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #include "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/web_state/web_state_observer.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ios/chrome/browser/ui/contextual_search/contextual_search_results_view.mm b/ios/chrome/browser/ui/contextual_search/contextual_search_results_view.mm
index f9145f5..f669e27 100644
--- a/ios/chrome/browser/ui/contextual_search/contextual_search_results_view.mm
+++ b/ios/chrome/browser/ui/contextual_search/contextual_search_results_view.mm
@@ -14,9 +14,9 @@
 #import "ios/chrome/browser/ui/contextual_search/contextual_search_web_state_observer.h"
 #import "ios/chrome/common/material_timing.h"
 #include "ios/web/public/load_committed_details.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/ui/crw_native_content_provider.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 
 namespace {
diff --git a/ios/chrome/browser/ui/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen_controller.h
index 14dbd25c..33c65bce 100644
--- a/ios/chrome/browser/ui/fullscreen_controller.h
+++ b/ios/chrome/browser/ui/fullscreen_controller.h
@@ -8,7 +8,7 @@
 #import <UIKit/UIKit.h>
 
 #import "ios/web/public/web_state/crw_web_controller_observer.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 
 namespace ios_internal {
 // Duration of the toolbar animation.
diff --git a/ios/chrome/browser/ui/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen_controller.mm
index cf4902f..2d37826 100644
--- a/ios/chrome/browser/ui/fullscreen_controller.mm
+++ b/ios/chrome/browser/ui/fullscreen_controller.mm
@@ -17,7 +17,7 @@
 #include "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
 #include "ios/web/public/ssl_status.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 
 NSString* const kSetupForTestingWillCloseAllTabsNotification =
diff --git a/ios/chrome/browser/ui/fullscreen_controller_unittest.mm b/ios/chrome/browser/ui/fullscreen_controller_unittest.mm
index 0e3aec6..854a15bd 100644
--- a/ios/chrome/browser/ui/fullscreen_controller_unittest.mm
+++ b/ios/chrome/browser/ui/fullscreen_controller_unittest.mm
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/ui/fullscreen_controller.h"
+
+#include "base/mac/scoped_nsobject.h"
 #import "ios/web/public/test/fakes/test_web_view_content_view.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 #include "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "third_party/ocmock/ocmock_extensions.h"
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
index 1715bd3..825d261 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h
@@ -10,7 +10,7 @@
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_view.h"
 #import "ios/chrome/browser/ui/util/relaxed_bounds_constraints_hittest.h"
 #import "ios/web/public/web_state/crw_web_controller_observer.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 
 @class OverscrollActionsController;
 
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index 2016efe8..fbec30a 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -18,7 +18,7 @@
 #import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
 #include "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/voice/voice_search_notification_names.h"
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 
 namespace {
 // This enum is used to record the overscroll actions performed by the user on
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm
index f14423f..364fb65 100644
--- a/ios/chrome/browser/web/visible_url_egtest.mm
+++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -7,14 +7,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/browser/experimental_flags.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/testing/earl_grey/disabled_test_macros.h"
 #import "ios/web/public/test/http_server.h"
 #include "ios/web/public/test/http_server_util.h"
 #include "ios/web/public/test/response_providers/html_response_provider.h"
@@ -175,10 +173,6 @@
 // Tests that visible URL is always the same as last committed URL during
 // pending back and forward navigations.
 - (void)testBackForwardNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -225,10 +219,6 @@
 // Tests that visible URL is always the same as last committed URL during
 // pending navigations initialted from back history popover.
 - (void)testHistoryNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -258,10 +248,6 @@
 // Tests that stopping a pending Back navigation and reloading reloads committed
 // URL, not pending URL.
 - (void)testStoppingPendingBackNavigationAndReload {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -295,10 +281,6 @@
 // Tests that visible URL is always the same as last committed URL during
 // back forward navigations initiated with JS.
 - (void)testJSBackForwardNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -344,10 +326,6 @@
 // Tests that visible URL is always the same as last committed URL during go
 // navigations initiated with JS.
 - (void)testJSGoNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -394,10 +372,6 @@
 // Tests that visible URL is always the same as last committed URL during go
 // back navigation started with pending reload in progress.
 - (void)testBackNavigationWithPendingReload {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -436,10 +410,6 @@
 // back navigation initiated with pending renderer-initiated navigation in
 // progress.
 - (void)testBackNavigationWithPendingRendererInitiatedNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -470,10 +440,6 @@
 // renderer-initiated navigation started with pending back navigation in
 // progress.
 - (void)testRendererInitiatedNavigationWithPendingBackNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Purge web view caches and pause the server to make sure that tests can
   // verify omnibox state before server starts responding.
   PurgeCachedWebViewPages();
@@ -504,10 +470,6 @@
 // Tests that visible URL is always the same as last committed URL if user
 // issues 2 go back commands.
 - (void)testDoubleBackNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Create 3rd entry in the history, to be able to go back twice.
   [ChromeEarlGrey loadURL:_testURL3];
 
@@ -539,10 +501,6 @@
 // Tests that visible URL is always the same as last committed URL if page calls
 // window.history.back() twice.
 - (void)testDoubleBackJSNavigation {
-  if (!experimental_flags::IsPendingIndexNavigationEnabled()) {
-    EARL_GREY_TEST_SKIPPED(@"Pending Index Navigation experiment is disabled");
-  }
-
   // Create 3rd entry in the history, to be able to go back twice.
   [ChromeEarlGrey loadURL:_testURL3];
 
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 2c904e9..58b9936 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -144,8 +144,6 @@
     "public/web_state/context_menu_params.h",
     "public/web_state/credential.h",
     "public/web_state/crw_web_controller_observer.h",
-    "public/web_state/crw_web_view_proxy.h",
-    "public/web_state/crw_web_view_scroll_view_proxy.h",
     "public/web_state/global_web_state_observer.h",
     "public/web_state/js/credential_util.h",
     "public/web_state/js/crw_js_injection_evaluator.h",
@@ -161,6 +159,8 @@
     "public/web_state/ui/crw_native_content_provider.h",
     "public/web_state/ui/crw_web_delegate.h",
     "public/web_state/ui/crw_web_view_content_view.h",
+    "public/web_state/ui/crw_web_view_proxy.h",
+    "public/web_state/ui/crw_web_view_scroll_view_proxy.h",
     "public/web_state/url_verification_constants.h",
     "public/web_state/web_state.h",
     "public/web_state/web_state_delegate.h",
@@ -188,9 +188,6 @@
     "web_state/credential.cc",
     "web_state/crw_pass_kit_downloader.h",
     "web_state/crw_pass_kit_downloader.mm",
-    "web_state/crw_web_view_proxy_impl.h",
-    "web_state/crw_web_view_proxy_impl.mm",
-    "web_state/crw_web_view_scroll_view_proxy.mm",
     "web_state/error_translation_util.h",
     "web_state/error_translation_util.mm",
     "web_state/global_web_state_event_tracker.h",
@@ -217,6 +214,9 @@
     "web_state/ui/crw_swipe_recognizer_provider.h",
     "web_state/ui/crw_touch_tracking_recognizer.h",
     "web_state/ui/crw_touch_tracking_recognizer.mm",
+    "web_state/ui/crw_web_view_proxy_impl.h",
+    "web_state/ui/crw_web_view_proxy_impl.mm",
+    "web_state/ui/crw_web_view_scroll_view_proxy.mm",
     "web_state/ui/crw_wk_navigation_states.h",
     "web_state/ui/crw_wk_navigation_states.mm",
     "web_thread_impl.cc",
@@ -566,7 +566,6 @@
     "url_util_unittest.cc",
     "web_state/context_menu_params_utils_unittest.mm",
     "web_state/crw_pass_kit_downloader_unittest.mm",
-    "web_state/crw_web_view_scroll_view_proxy_unittest.mm",
     "web_state/error_translation_util_unittest.mm",
     "web_state/js/common_js_unittest.mm",
     "web_state/js/core_js_unittest.mm",
@@ -580,6 +579,7 @@
     "web_state/ui/crw_web_controller_container_view_unittest.mm",
     "web_state/ui/crw_web_controller_observer_unittest.mm",
     "web_state/ui/crw_web_controller_unittest.mm",
+    "web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm",
     "web_state/ui/crw_wk_navigation_states_unittest.mm",
     "web_state/ui/crw_wk_script_message_router_unittest.mm",
     "web_state/ui/web_view_js_utils_unittest.mm",
diff --git a/ios/web/interstitials/web_interstitial_impl.mm b/ios/web/interstitials/web_interstitial_impl.mm
index 30698e6..1a9febb4 100644
--- a/ios/web/interstitials/web_interstitial_impl.mm
+++ b/ios/web/interstitials/web_interstitial_impl.mm
@@ -84,19 +84,12 @@
 
   // Clear the pending entry, since that's the page that's not being
   // proceeded to.
-  NavigationManager* nav_manager = GetWebStateImpl()->GetNavigationManager();
-  nav_manager->DiscardNonCommittedItems();
+  GetWebStateImpl()->GetNavigationManager()->DiscardNonCommittedItems();
 
   Hide();
 
   GetDelegate()->OnDontProceed();
 
-  NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
-  if (![user_defaults boolForKey:@"PendingIndexNavigationDisabled"]) {
-    // Reload last committed entry.
-    nav_manager->Reload(ReloadType::NORMAL, true /* check_for_repost */);
-  }
-
   delete this;
 }
 
diff --git a/ios/web/public/test/web_view_interaction_test_util.mm b/ios/web/public/test/web_view_interaction_test_util.mm
index aa1baf60..f29ee56 100644
--- a/ios/web/public/test/web_view_interaction_test_util.mm
+++ b/ios/web/public/test/web_view_interaction_test_util.mm
@@ -9,9 +9,9 @@
 #include "base/strings/utf_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #import "ios/testing/wait_util.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 #import "ios/web/web_state/web_state_impl.h"
 
 using web::NavigationManager;
diff --git a/ios/web/public/web_state/ui/crw_web_delegate.h b/ios/web/public/web_state/ui/crw_web_delegate.h
index 2be85fc96..9fe0df2b 100644
--- a/ios/web/public/web_state/ui/crw_web_delegate.h
+++ b/ios/web/public/web_state/ui/crw_web_delegate.h
@@ -58,9 +58,6 @@
 - (void)webDidUpdateSessionForLoadWithParams:
             (const web::NavigationManager::WebLoadParams&)params
                         wasInitialNavigation:(BOOL)initialNavigation;
-// Called from finishHistoryNavigationFromEntry.
-// TODO(crbug.com/692331): Remove this method and use |DidFinishNavigation|.
-- (void)webWillFinishHistoryNavigation;
 
 @optional
 
diff --git a/ios/web/public/web_state/crw_web_view_proxy.h b/ios/web/public/web_state/ui/crw_web_view_proxy.h
similarity index 93%
rename from ios/web/public/web_state/crw_web_view_proxy.h
rename to ios/web/public/web_state/ui/crw_web_view_proxy.h
index 81125e7..7a5768c7 100644
--- a/ios/web/public/web_state/crw_web_view_proxy.h
+++ b/ios/web/public/web_state/ui/crw_web_view_proxy.h
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_PROXY_H_
-#define IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_PROXY_H_
+#ifndef IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_H_
+#define IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_H_
 
 #import <UIKit/UIKit.h>
 
-
 @class CRWWebViewScrollViewProxy;
 
 // Provides an interface for embedders to access the WebState's web view in a
@@ -74,4 +73,4 @@
 
 @end
 
-#endif  // IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_PROXY_H_
+#endif  // IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_H_
diff --git a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h b/ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h
similarity index 85%
rename from ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
rename to ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h
index 89f432f..93032cc 100644
--- a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
+++ b/ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
-#define IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
+#ifndef IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
+#define IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
 
 #import <UIKit/UIKit.h>
 
@@ -58,9 +58,9 @@
 @protocol CRWWebViewScrollViewObserver<NSObject>
 @optional
 - (void)webViewScrollViewDidScroll:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (void)webViewScrollViewWillBeginDragging:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (void)webViewScrollViewWillEndDragging:
             (CRWWebViewScrollViewProxy*)webViewScrollViewProxy
                             withVelocity:(CGPoint)velocity
@@ -69,13 +69,13 @@
             (CRWWebViewScrollViewProxy*)webViewScrollViewProxy
                          willDecelerate:(BOOL)decelerate;
 - (void)webViewScrollViewDidEndScrollingAnimation:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (void)webViewScrollViewDidEndDecelerating:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (BOOL)webViewScrollViewShouldScrollToTop:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (void)webViewScrollViewDidZoom:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 - (void)webViewScrollViewDidResetContentSize:
     (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 @end
@@ -88,7 +88,7 @@
 @optional
 // Called when the underlying scrollview of the proxy is set.
 - (void)webViewScrollViewProxyDidSetScrollView:
-        (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
+    (CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
 @end
 
-#endif  // IOS_WEB_PUBLIC_WEB_STATE_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
+#endif  // IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_SCROLL_VIEW_PROXY_H_
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 199b341..4d638b3 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -64,7 +64,6 @@
 #import "ios/web/public/web_state/context_menu_params.h"
 #include "ios/web/public/web_state/credential.h"
 #import "ios/web/public/web_state/crw_web_controller_observer.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #include "ios/web/public/web_state/js/credential_util.h"
 #import "ios/web/public/web_state/js/crw_js_injection_manager.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
@@ -74,11 +73,11 @@
 #import "ios/web/public/web_state/ui/crw_native_content.h"
 #import "ios/web/public/web_state/ui/crw_native_content_provider.h"
 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
 #import "ios/web/public/web_state/web_state.h"
 #include "ios/web/public/webui/web_ui_ios.h"
 #import "ios/web/web_state/crw_pass_kit_downloader.h"
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
 #import "ios/web/web_state/error_translation_util.h"
 #import "ios/web/web_state/js/crw_js_plugin_placeholder_manager.h"
 #import "ios/web/web_state/js/crw_js_post_request_loader.h"
@@ -88,6 +87,7 @@
 #import "ios/web/web_state/ui/crw_swipe_recognizer_provider.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 #import "ios/web/web_state/ui/crw_web_controller_container_view.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 #import "ios/web/web_state/ui/crw_wk_navigation_states.h"
 #import "ios/web/web_state/ui/crw_wk_script_message_router.h"
 #import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h"
@@ -476,11 +476,6 @@
 // unless the request was a POST.
 @property(nonatomic, readonly) NSDictionary* currentHTTPHeaders;
 
-// TODO(crbug.com/684098): Remove these methods and inline their content.
-// Called before finishing a history navigation from a page with the given
-// UserAgentType.
-- (void)webWillFinishHistoryNavigationWithPreviousUserAgentType:
-    (web::UserAgentType)userAgentType;
 // Requires page reconstruction if |item| has a non-NONE UserAgentType and it
 // differs from that of |fromItem|.
 - (void)updateDesktopUserAgentForItem:(web::NavigationItem*)item
@@ -603,13 +598,6 @@
 // bounds. Reloads if delta is 0.
 // TODO(crbug.com/661316): Move this method to NavigationManager.
 - (void)goDelta:(int)delta;
-// Loads a new URL if the current entry is not from a pushState() navigation.
-// |fromURL| is the URL of the previous NavigationItem, |fromUserAgentType| is
-// that item's UserAgentType, and |sameDocument| is YES if the navigation is
-// between two pages with the same document.
-- (void)finishHistoryNavigationFromURL:(const GURL&)fromURL
-                         userAgentType:(web::UserAgentType)fromUserAgentType
-                          sameDocument:(BOOL)sameDocument;
 // Informs the native controller if web usage is allowed or not.
 - (void)setNativeControllerWebUsageEnabled:(BOOL)webUsageEnabled;
 // Called when web controller receives a new message from the web page.
@@ -718,11 +706,6 @@
 // Returns YES if the given WKBackForwardListItem is valid to use for
 // navigation.
 - (BOOL)isBackForwardListItemValid:(WKBackForwardListItem*)item;
-// Compares the two URLs being navigated between during a history navigation to
-// determine if a # needs to be appended to the URL of |toItem| to trigger a
-// hashchange event. If so, also saves the modified URL into |toItem|.
-- (GURL)URLForHistoryNavigationToItem:(web::NavigationItem*)toItem
-                          previousURL:(const GURL&)previousURL;
 // Finds all the scrollviews in the view hierarchy and makes sure they do not
 // interfere with scroll to top when tapping the statusbar.
 - (void)optOutScrollsToTopForSubviews;
@@ -1407,40 +1390,6 @@
          [list.backList indexOfObject:item] != NSNotFound;
 }
 
-- (GURL)URLForHistoryNavigationToItem:(web::NavigationItem*)toItem
-                          previousURL:(const GURL&)previousURL {
-  // If navigating with native API, i.e. using a back forward list item,
-  // hashchange events will be triggered automatically, so no URL tampering is
-  // required.
-  web::WKBackForwardListItemHolder* holder =
-      web::WKBackForwardListItemHolder::FromNavigationItem(toItem);
-  if (holder->back_forward_list_item()) {
-    return toItem->GetURL();
-  }
-
-  const GURL& URL = toItem->GetURL();
-
-  // Check the state of the fragments on both URLs (aka, is there a '#' in the
-  // url or not).
-  if (!previousURL.has_ref() || URL.has_ref()) {
-    return URL;
-  }
-
-  // startURL contains a fragment and endURL doesn't. Remove the fragment from
-  // startURL and compare the resulting string to endURL. If they are equal, add
-  // # to endURL to cause a hashchange event.
-  GURL hashless = web::GURLByRemovingRefFromGURL(previousURL);
-
-  if (hashless != URL)
-    return URL;
-
-  url::StringPieceReplacements<std::string> emptyRef;
-  emptyRef.SetRefStr("");
-  GURL newEndURL = URL.ReplaceComponents(emptyRef);
-  toItem->SetURL(newEndURL);
-  return newEndURL;
-}
-
 - (void)injectWindowID {
   // Default value for shouldSuppressDialogs is NO, so updating them only
   // when necessary is a good optimization.
@@ -1846,56 +1795,42 @@
   NavigationManager::WebLoadParams params(originalParams);
 
   // Initiating a navigation from the UI, record the current page state before
-  // the new page loads. Don't record for back/forward, as the current entry
-  // has already been moved to the next entry in the history. Do, however,
-  // record it for general reload.
-  // TODO(jimblackler): consider a single unified call to record state whenever
-  // the page is about to be changed. This cannot currently be done after
-  // addPendingItem is called.
+  // the new page loads.
 
   [_delegate webWillInitiateLoadWithParams:params];
 
   GURL navUrl = params.url;
   ui::PageTransition transition = params.transition_type;
+  DCHECK(!(transition & ui::PAGE_TRANSITION_FORWARD_BACK));
+  DCHECK(!(transition & ui::PAGE_TRANSITION_RELOAD));
 
   BOOL initialNavigation = NO;
-  BOOL forwardBack =
-      PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD) &&
-      (transition & ui::PAGE_TRANSITION_FORWARD_BACK);
-  if (forwardBack) {
-    // Setting these for back/forward is not supported.
-    DCHECK(!params.extra_headers);
-    DCHECK(!params.post_data);
-  } else {
-    // Clear transient view before making any changes to history and navigation
-    // manager. TODO(stuartmorgan): Drive Transient Item clearing from
-    // navigation system, rather than from WebController.
-    [self clearTransientContentView];
+  // Clear transient view before making any changes to history and navigation
+  // manager. TODO(stuartmorgan): Drive Transient Item clearing from
+  // navigation system, rather than from WebController.
+  [self clearTransientContentView];
 
-    // TODO(stuartmorgan): Why doesn't recordStateInHistory get called for
-    // forward/back transitions?
-    [self recordStateInHistory];
+  [self recordStateInHistory];
 
-    if (!self.currentNavItem)
-      initialNavigation = YES;
+  if (!self.currentNavItem)
+    initialNavigation = YES;
 
-    web::NavigationInitiationType navigationInitiationType =
-        params.is_renderer_initiated
-            ? web::NavigationInitiationType::RENDERER_INITIATED
-            : web::NavigationInitiationType::USER_INITIATED;
-    self.navigationManagerImpl->AddPendingItem(
-        navUrl, params.referrer, transition, navigationInitiationType);
+  web::NavigationInitiationType navigationInitiationType =
+      params.is_renderer_initiated
+          ? web::NavigationInitiationType::RENDERER_INITIATED
+          : web::NavigationInitiationType::USER_INITIATED;
+  self.navigationManagerImpl->AddPendingItem(
+      navUrl, params.referrer, transition, navigationInitiationType);
 
-    web::NavigationItemImpl* addedItem = self.currentNavItem;
-    DCHECK(addedItem);
-    if (params.extra_headers)
-      addedItem->AddHttpRequestHeaders(params.extra_headers);
-    if (params.post_data) {
-      DCHECK([addedItem->GetHttpRequestHeaders() objectForKey:@"Content-Type"])
-          << "Post data should have an associated content type";
-      addedItem->SetPostData(params.post_data);
-      addedItem->SetShouldSkipRepostFormConfirmation(true);
-    }
+  web::NavigationItemImpl* addedItem = self.currentNavItem;
+  DCHECK(addedItem);
+  if (params.extra_headers)
+    addedItem->AddHttpRequestHeaders(params.extra_headers);
+  if (params.post_data) {
+    DCHECK([addedItem->GetHttpRequestHeaders() objectForKey:@"Content-Type"])
+        << "Post data should have an associated content type";
+    addedItem->SetPostData(params.post_data);
+    addedItem->SetShouldSkipRepostFormConfirmation(true);
   }
 
   [_delegate webDidUpdateSessionForLoadWithParams:params
@@ -2099,44 +2034,32 @@
   if (!_webStateImpl->IsShowingWebInterstitial())
     [self recordStateInHistory];
 
+  [self clearTransientContentView];
+
+  // Update the user agent before attempting the navigation.
+  web::NavigationItem* toItem = items[index].get();
   web::NavigationItem* previousItem = sessionController.currentItem;
-  GURL previousURL = previousItem ? previousItem->GetURL() : GURL::EmptyGURL();
   web::UserAgentType previousUserAgentType =
       previousItem ? previousItem->GetUserAgentType()
                    : web::UserAgentType::NONE;
-  web::NavigationItem* toItem = items[index].get();
+  [self updateDesktopUserAgentForItem:toItem
+                previousUserAgentType:previousUserAgentType];
+
   BOOL sameDocumentNavigation =
       [sessionController isSameDocumentNavigationBetweenItem:previousItem
                                                      andItem:toItem];
-
-  NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
-  if (![userDefaults boolForKey:@"PendingIndexNavigationDisabled"]) {
-    [self clearTransientContentView];
-
-    // Update the user agent before attempting the navigation.
-    [self updateDesktopUserAgentForItem:toItem
-                  previousUserAgentType:previousUserAgentType];
-
-    if (sameDocumentNavigation) {
-      [sessionController goToItemAtIndex:index];
-      [self updateHTML5HistoryState];
-    } else {
-      [sessionController discardNonCommittedItems];
-      [sessionController setPendingItemIndex:index];
-
-      web::NavigationItemImpl* pendingItem = sessionController.pendingItem;
-      pendingItem->SetTransitionType(ui::PageTransitionFromInt(
-          pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
-
-      [self loadCurrentURL];
-    }
-  } else {
+  if (sameDocumentNavigation) {
     [sessionController goToItemAtIndex:index];
-    if (previousURL.is_valid()) {
-      [self finishHistoryNavigationFromURL:previousURL
-                             userAgentType:previousUserAgentType
-                              sameDocument:sameDocumentNavigation];
-    }
+    [self updateHTML5HistoryState];
+  } else {
+    [sessionController discardNonCommittedItems];
+    [sessionController setPendingItemIndex:index];
+
+    web::NavigationItemImpl* pendingItem = sessionController.pendingItem;
+    pendingItem->SetTransitionType(ui::PageTransitionFromInt(
+        pendingItem->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
+
+    [self loadCurrentURL];
   }
 }
 
@@ -2230,38 +2153,6 @@
   }
 }
 
-- (void)finishHistoryNavigationFromURL:(const GURL&)fromURL
-                         userAgentType:(web::UserAgentType)fromUserAgentType
-                          sameDocument:(BOOL)sameDocument {
-  [self webWillFinishHistoryNavigationWithPreviousUserAgentType:
-            fromUserAgentType];
-
-  // Only load the new URL if it has a different document than |fromEntry| to
-  // prevent extra page loads from NavigationItems created by hash changes or
-  // calls to window.history.pushState().
-  web::NavigationItem* currentItem = self.currentNavItem;
-  GURL endURL =
-      [self URLForHistoryNavigationToItem:currentItem previousURL:fromURL];
-  if (!sameDocument) {
-    ui::PageTransition transition = ui::PageTransitionFromInt(
-        ui::PAGE_TRANSITION_RELOAD | ui::PAGE_TRANSITION_FORWARD_BACK);
-
-    NavigationManager::WebLoadParams params(endURL);
-    if (currentItem) {
-      params.referrer = currentItem->GetReferrer();
-    }
-    params.transition_type = transition;
-    [self loadWithParams:params];
-  }
-  // If this is a same-document navigation, update the HTML5 history state
-  // immediately.  For cross-document navigations, the history state will be
-  // updated after the navigation is committed, as attempting to replace the URL
-  // here will result in a JavaScript SecurityError due to the URLs having
-  // different origins.
-  if (sameDocument)
-    [self updateHTML5HistoryState];
-}
-
 - (void)addGestureRecognizerToWebView:(UIGestureRecognizer*)recognizer {
   if ([_gestureRecognizers containsObject:recognizer])
     return;
@@ -2351,13 +2242,6 @@
   return _passKitDownloader.get();
 }
 
-- (void)webWillFinishHistoryNavigationWithPreviousUserAgentType:
-    (web::UserAgentType)userAgentType {
-  [self updateDesktopUserAgentForItem:self.currentNavItem
-                previousUserAgentType:userAgentType];
-  [_delegate webWillFinishHistoryNavigation];
-}
-
 - (void)updateDesktopUserAgentForItem:(web::NavigationItem*)item
                 previousUserAgentType:(web::UserAgentType)userAgentType {
   if (!item)
diff --git a/ios/web/web_state/ui/crw_web_controller_container_view.mm b/ios/web/web_state/ui/crw_web_controller_container_view.mm
index 6db54ac..9c7ae37 100644
--- a/ios/web/web_state/ui/crw_web_controller_container_view.mm
+++ b/ios/web/web_state/ui/crw_web_controller_container_view.mm
@@ -10,7 +10,7 @@
 #import "ios/web/public/web_state/ui/crw_content_view.h"
 #import "ios/web/public/web_state/ui/crw_native_content.h"
 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 
 #pragma mark - CRWToolbarContainerView
 
diff --git a/ios/web/web_state/ui/crw_web_controller_container_view_unittest.mm b/ios/web/web_state/ui/crw_web_controller_container_view_unittest.mm
index fa4f0af..207b0ba 100644
--- a/ios/web/web_state/ui/crw_web_controller_container_view_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_container_view_unittest.mm
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "base/mac/scoped_nsobject.h"
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
 #import "ios/web/web_state/ui/crw_web_controller_container_view.h"
+
+#import "base/mac/scoped_nsobject.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
-#include "third_party/ocmock/gtest_support.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
 
 namespace {
 // The frame of CRWWebControllerContainerViewTest's |container_view_|.
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 8e78518..41998a4 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -50,8 +50,6 @@
 
 @interface CRWWebController (PrivateAPI)
 @property(nonatomic, readwrite) web::PageDisplayState pageDisplayState;
-- (GURL)URLForHistoryNavigationToItem:(web::NavigationItem*)toItem
-                          previousURL:(const GURL&)previousURL;
 @end
 
 @interface CountingObserver : NSObject<CRWWebControllerObserver>
@@ -170,72 +168,6 @@
   base::scoped_nsobject<id> mock_web_view_;
 };
 
-#define MAKE_URL(url_string) GURL([url_string UTF8String])
-
-TEST_F(CRWWebControllerTest, UrlForHistoryNavigation) {
-  NSArray* urls_without_fragments = @[
-    @"http://one.com", @"http://two.com/", @"http://three.com/bar",
-    @"http://four.com/bar/", @"five", @"/six", @"/seven/", @""
-  ];
-
-  NSArray* fragments = @[ @"#", @"#bar" ];
-  NSMutableArray* urls_with_fragments = [NSMutableArray array];
-  for (NSString* url in urls_without_fragments) {
-    for (NSString* fragment in fragments) {
-      [urls_with_fragments addObject:[url stringByAppendingString:fragment]];
-    }
-  }
-
-  GURL previous_url;
-  web::NavigationItemImpl to_item;
-
-  // No start fragment: the end url is never changed.
-  for (NSString* start in urls_without_fragments) {
-    for (NSString* end in urls_with_fragments) {
-      previous_url = MAKE_URL(start);
-      to_item.SetURL(MAKE_URL(end));
-      EXPECT_EQ(MAKE_URL(end),
-                [web_controller() URLForHistoryNavigationToItem:&to_item
-                                                    previousURL:previous_url]);
-    }
-  }
-  // Both contain fragments: the end url is never changed.
-  for (NSString* start in urls_with_fragments) {
-    for (NSString* end in urls_with_fragments) {
-      previous_url = MAKE_URL(start);
-      to_item.SetURL(MAKE_URL(end));
-      EXPECT_EQ(MAKE_URL(end),
-                [web_controller() URLForHistoryNavigationToItem:&to_item
-                                                    previousURL:previous_url]);
-    }
-  }
-  for (unsigned start_index = 0; start_index < urls_with_fragments.count;
-       ++start_index) {
-    NSString* start = urls_with_fragments[start_index];
-    for (unsigned end_index = 0; end_index < urls_without_fragments.count;
-         ++end_index) {
-      NSString* end = urls_without_fragments[end_index];
-      previous_url = MAKE_URL(start);
-      if (start_index / 2 != end_index) {
-        // The URLs have nothing in common, they are left untouched.
-        to_item.SetURL(MAKE_URL(end));
-        EXPECT_EQ(
-            MAKE_URL(end),
-            [web_controller() URLForHistoryNavigationToItem:&to_item
-                                                previousURL:previous_url]);
-      } else {
-        // Start contains a fragment and matches end: An empty fragment is
-        // added.
-        to_item.SetURL(MAKE_URL(end));
-        EXPECT_EQ(
-            MAKE_URL([end stringByAppendingString:@"#"]),
-            [web_controller() URLForHistoryNavigationToItem:&to_item
-                                                previousURL:previous_url]);
-      }
-    }
-  }
-}
-
 // Tests that AllowCertificateError is called with correct arguments if
 // WKWebView fails to load a page with bad SSL cert.
 TEST_F(CRWWebControllerTest, SslCertError) {
diff --git a/ios/web/web_state/crw_web_view_proxy_impl.h b/ios/web/web_state/ui/crw_web_view_proxy_impl.h
similarity index 77%
rename from ios/web/web_state/crw_web_view_proxy_impl.h
rename to ios/web/web_state/ui/crw_web_view_proxy_impl.h
index 53074406..98fe0ee 100644
--- a/ios/web/web_state/crw_web_view_proxy_impl.h
+++ b/ios/web/web_state/ui/crw_web_view_proxy_impl.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_WEB_WEB_STATE_CRW_WEB_VIEW_PROXY_IMPL_H_
-#define IOS_WEB_WEB_STATE_CRW_WEB_VIEW_PROXY_IMPL_H_
+#ifndef IOS_WEB_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_IMPL_H_
+#define IOS_WEB_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_IMPL_H_
 
 #import <UIKit/UIKit.h>
 
-#import "ios/web/public/web_state/crw_web_view_proxy.h"
 #import "ios/web/public/web_state/ui/crw_content_view.h"
+#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
 
 @class CRWWebController;
 
@@ -25,4 +25,4 @@
 
 @end
 
-#endif  // IOS_WEB_WEB_STATE_CRW_WEB_VIEW_PROXY_IMPL_H_
+#endif  // IOS_WEB_WEB_STATE_UI_CRW_WEB_VIEW_PROXY_IMPL_H_
diff --git a/ios/web/web_state/crw_web_view_proxy_impl.mm b/ios/web/web_state/ui/crw_web_view_proxy_impl.mm
similarity index 97%
rename from ios/web/web_state/crw_web_view_proxy_impl.mm
rename to ios/web/web_state/ui/crw_web_view_proxy_impl.mm
index 357ed97..bc81d69 100644
--- a/ios/web/web_state/crw_web_view_proxy_impl.mm
+++ b/ios/web/web_state/ui/crw_web_view_proxy_impl.mm
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/web_state/crw_web_view_proxy_impl.h"
+#import "ios/web/web_state/ui/crw_web_view_proxy_impl.h"
 
 #import "base/mac/scoped_nsobject.h"
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/public/web_state/ui/crw_content_view.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/web/web_state/crw_web_view_scroll_view_proxy.mm b/ios/web/web_state/ui/crw_web_view_scroll_view_proxy.mm
similarity index 95%
rename from ios/web/web_state/crw_web_view_scroll_view_proxy.mm
rename to ios/web/web_state/ui/crw_web_view_scroll_view_proxy.mm
index 291f409..3c5b54e 100644
--- a/ios/web/web_state/crw_web_view_scroll_view_proxy.mm
+++ b/ios/web/web_state/ui/crw_web_view_scroll_view_proxy.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 
 #import <objc/runtime.h>
 
@@ -191,11 +191,11 @@
   DCHECK_EQ(_scrollView, scrollView);
   __block BOOL shouldScrollToTop = YES;
   [_observers executeOnObservers:^(id observer) {
-      if ([observer respondsToSelector:@selector(
-          webViewScrollViewShouldScrollToTop:)]) {
-        shouldScrollToTop = shouldScrollToTop &&
-            [observer webViewScrollViewShouldScrollToTop:self];
-      }
+    if ([observer respondsToSelector:@selector
+                  (webViewScrollViewShouldScrollToTop:)]) {
+      shouldScrollToTop = shouldScrollToTop &&
+                          [observer webViewScrollViewShouldScrollToTop:self];
+    }
   }];
   return shouldScrollToTop;
 }
diff --git a/ios/web/web_state/crw_web_view_scroll_view_proxy_unittest.mm b/ios/web/web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm
similarity index 74%
rename from ios/web/web_state/crw_web_view_scroll_view_proxy_unittest.mm
rename to ios/web/web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm
index 04a0428..2f3581b8 100644
--- a/ios/web/web_state/crw_web_view_scroll_view_proxy_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/web/public/web_state/crw_web_view_scroll_view_proxy.h"
+#import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h"
 
 #import <UIKit/UIKit.h>
 
@@ -68,38 +68,39 @@
 
   // Arbitrary point.
   const CGPoint point = CGPointMake(10, 10);
-  [[[mockScrollView_ stub]
-      andReturnValue:[NSValue valueWithCGPoint:point]] contentOffset];
-  EXPECT_TRUE(CGPointEqualToPoint(point,
-                                  [webViewScrollViewProxy_ contentOffset]));
+  [[[mockScrollView_ stub] andReturnValue:[NSValue valueWithCGPoint:point]]
+      contentOffset];
+  EXPECT_TRUE(
+      CGPointEqualToPoint(point, [webViewScrollViewProxy_ contentOffset]));
 
   // Arbitrary inset.
   const UIEdgeInsets contentInset = UIEdgeInsetsMake(10, 10, 10, 10);
-  [[[mockScrollView_ stub] andReturnValue:
-      [NSValue valueWithUIEdgeInsets:contentInset]] contentInset];
-  EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(contentInset,
-      [webViewScrollViewProxy_ contentInset]));
+  [[[mockScrollView_ stub]
+      andReturnValue:[NSValue valueWithUIEdgeInsets:contentInset]]
+      contentInset];
+  EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(
+      contentInset, [webViewScrollViewProxy_ contentInset]));
 
   // Arbitrary inset.
   const UIEdgeInsets scrollIndicatorInsets = UIEdgeInsetsMake(20, 20, 20, 20);
-  [[[mockScrollView_ stub] andReturnValue:[NSValue
-      valueWithUIEdgeInsets:scrollIndicatorInsets]] scrollIndicatorInsets];
-  EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(scrollIndicatorInsets,
-      [webViewScrollViewProxy_ scrollIndicatorInsets]));
+  [[[mockScrollView_ stub]
+      andReturnValue:[NSValue valueWithUIEdgeInsets:scrollIndicatorInsets]]
+      scrollIndicatorInsets];
+  EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(
+      scrollIndicatorInsets, [webViewScrollViewProxy_ scrollIndicatorInsets]));
 
   // Arbitrary size.
   const CGSize contentSize = CGSizeMake(19, 19);
-  [[[mockScrollView_ stub] andReturnValue:
-      [NSValue valueWithCGSize:contentSize]] contentSize];
-  EXPECT_TRUE(CGSizeEqualToSize(contentSize,
-                                [webViewScrollViewProxy_ contentSize]));
+  [[[mockScrollView_ stub] andReturnValue:[NSValue valueWithCGSize:contentSize]]
+      contentSize];
+  EXPECT_TRUE(
+      CGSizeEqualToSize(contentSize, [webViewScrollViewProxy_ contentSize]));
 
   // Arbitrary rect.
   const CGRect frame = CGRectMake(2, 4, 5, 1);
-  [[[mockScrollView_ stub] andReturnValue:
-      [NSValue valueWithCGRect:frame]] frame];
-  EXPECT_TRUE(CGRectEqualToRect(frame,
-                                [webViewScrollViewProxy_ frame]));
+  [[[mockScrollView_ stub] andReturnValue:[NSValue valueWithCGRect:frame]]
+      frame];
+  EXPECT_TRUE(CGRectEqualToRect(frame, [webViewScrollViewProxy_ frame]));
 }
 
 // Tests that CRWWebViewScrollViewProxy returns the correct property values when
@@ -113,10 +114,9 @@
       UIEdgeInsetsZero, [webViewScrollViewProxy_ contentInset]));
   EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(
       UIEdgeInsetsZero, [webViewScrollViewProxy_ scrollIndicatorInsets]));
-  EXPECT_TRUE(CGSizeEqualToSize(CGSizeZero,
-                                [webViewScrollViewProxy_ contentSize]));
-  EXPECT_TRUE(CGRectEqualToRect(CGRectZero,
-                                [webViewScrollViewProxy_ frame]));
+  EXPECT_TRUE(
+      CGSizeEqualToSize(CGSizeZero, [webViewScrollViewProxy_ contentSize]));
+  EXPECT_TRUE(CGRectEqualToRect(CGRectZero, [webViewScrollViewProxy_ frame]));
 
   // Make sure setting the properties is fine too.
   // Arbitrary point.
@@ -152,15 +152,14 @@
 
   // Arbitrary point.
   const CGPoint point = CGPointMake(10, 10);
-  [[[mockScrollView_ stub]
-      andReturnValue:[NSValue valueWithCGPoint:point]] contentOffset];
-  EXPECT_TRUE(CGPointEqualToPoint(point,
-                                  [webViewScrollViewProxy_ contentOffset]));
-  EXPECT_TRUE(CGPointEqualToPoint(point,
-                                  [webViewScrollViewProxy1 contentOffset]));
-  EXPECT_TRUE(CGPointEqualToPoint(point,
-                                  [webViewScrollViewProxy2 contentOffset]));
+  [[[mockScrollView_ stub] andReturnValue:[NSValue valueWithCGPoint:point]]
+      contentOffset];
+  EXPECT_TRUE(
+      CGPointEqualToPoint(point, [webViewScrollViewProxy_ contentOffset]));
+  EXPECT_TRUE(
+      CGPointEqualToPoint(point, [webViewScrollViewProxy1 contentOffset]));
+  EXPECT_TRUE(
+      CGPointEqualToPoint(point, [webViewScrollViewProxy2 contentOffset]));
 }
 
 }  // namespace
-
diff --git a/ios/web_view/internal/web_view_web_main_delegate.mm b/ios/web_view/internal/web_view_web_main_delegate.mm
index 47983b4..83188ce8 100644
--- a/ios/web_view/internal/web_view_web_main_delegate.mm
+++ b/ios/web_view/internal/web_view_web_main_delegate.mm
@@ -4,9 +4,11 @@
 
 #import "ios/web_view/internal/web_view_web_main_delegate.h"
 
+#import "base/mac/bundle_locations.h"
 #include "base/memory/ptr_util.h"
 #import "ios/web_view/internal/web_view_web_client.h"
 #import "ios/web_view/public/cwv_delegate.h"
+#import "ios/web_view/public/cwv_web_view.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -20,6 +22,8 @@
 WebViewWebMainDelegate::~WebViewWebMainDelegate() = default;
 
 void WebViewWebMainDelegate::BasicStartupComplete() {
+  base::mac::SetOverrideFrameworkBundle(
+      [NSBundle bundleForClass:[CWVWebView class]]);
   web_client_ = base::MakeUnique<WebViewWebClient>(delegate_);
   web::SetWebClient(web_client_.get());
 }
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm
index 651d357..7cb74eb 100644
--- a/ios/web_view/internal/web_view_web_main_parts.mm
+++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -7,13 +7,11 @@
 #import <Foundation/Foundation.h>
 
 #include "base/base_paths.h"
-#import "base/mac/bundle_locations.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "components/translate/core/browser/translate_download_manager.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
 #import "ios/web_view/public/cwv_delegate.h"
-#import "ios/web_view/public/cwv_web_view.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/resource/resource_bundle.h"
 
@@ -30,9 +28,6 @@
 WebViewWebMainParts::~WebViewWebMainParts() = default;
 
 void WebViewWebMainParts::PreMainMessageLoopRun() {
-  base::mac::SetOverrideFrameworkBundle(
-      [NSBundle bundleForClass:[CWVWebView class]]);
-
   // Initialize resources.
   l10n_util::OverrideLocaleWithCocoaLocale();
   ui::ResourceBundle::InitSharedInstanceWithLocale(
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 6e719b3..ea11b54a 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -802,6 +802,53 @@
   return s.str();
 }
 
+int VideoFrame::BitsPerChannel(VideoPixelFormat format) {
+  int bits_per_channel = 0;
+  switch (format) {
+    case media::PIXEL_FORMAT_UNKNOWN:
+      NOTREACHED();
+    // Fall through!
+    case media::PIXEL_FORMAT_I420:
+    case media::PIXEL_FORMAT_YV12:
+    case media::PIXEL_FORMAT_YV16:
+    case media::PIXEL_FORMAT_YV12A:
+    case media::PIXEL_FORMAT_YV24:
+    case media::PIXEL_FORMAT_NV12:
+    case media::PIXEL_FORMAT_NV21:
+    case media::PIXEL_FORMAT_UYVY:
+    case media::PIXEL_FORMAT_YUY2:
+    case media::PIXEL_FORMAT_ARGB:
+    case media::PIXEL_FORMAT_XRGB:
+    case media::PIXEL_FORMAT_RGB24:
+    case media::PIXEL_FORMAT_RGB32:
+    case media::PIXEL_FORMAT_MJPEG:
+    case media::PIXEL_FORMAT_MT21:
+    case media::PIXEL_FORMAT_Y8:
+    case media::PIXEL_FORMAT_I422:
+      bits_per_channel = 8;
+      break;
+    case media::PIXEL_FORMAT_YUV420P9:
+    case media::PIXEL_FORMAT_YUV422P9:
+    case media::PIXEL_FORMAT_YUV444P9:
+      bits_per_channel = 9;
+      break;
+    case media::PIXEL_FORMAT_YUV420P10:
+    case media::PIXEL_FORMAT_YUV422P10:
+    case media::PIXEL_FORMAT_YUV444P10:
+      bits_per_channel = 10;
+      break;
+    case media::PIXEL_FORMAT_YUV420P12:
+    case media::PIXEL_FORMAT_YUV422P12:
+    case media::PIXEL_FORMAT_YUV444P12:
+      bits_per_channel = 12;
+      break;
+    case media::PIXEL_FORMAT_Y16:
+      bits_per_channel = 16;
+      break;
+  }
+  return bits_per_channel;
+}
+
 // static
 scoped_refptr<VideoFrame> VideoFrame::WrapExternalStorage(
     VideoPixelFormat format,
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 3139f7a..0ae2d70 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -402,6 +402,9 @@
   // guaranteed to be unique within a single process.
   int unique_id() const { return unique_id_; }
 
+  // Returns the number of bits per channel for given |format|.
+  int BitsPerChannel(VideoPixelFormat format);
+
  protected:
   friend class base::RefCountedThreadSafe<VideoFrame>;
 
diff --git a/media/media_options.gni b/media/media_options.gni
index 2f757021..00709d3 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -60,6 +60,9 @@
   # Enabled by default on the cast desktop implementation to allow unit tests of
   # MP2TS parsing support.
   enable_hls_sample_aes = proprietary_codecs && is_cast_desktop_build
+
+  # If true, use cast CMA backend instead of default chromium media pipeline.
+  is_cast_using_cma_backend = is_cast_audio_only || !is_android
 }
 
 # enable_hls_sample_aes can only be true if enable_mse_mpeg2ts_stream_parser is.
@@ -149,18 +152,19 @@
   # Can be overridden by gn build arguments from the --args command line flag
   # for local testing.
   if (enable_mojo_media) {
-    if (is_android) {
-      mojo_media_services = [
-        "cdm",
-        "audio_decoder",
-      ]
-      mojo_media_host = "gpu"
-    } else if (is_chromecast) {
+    if (is_chromecast && is_cast_using_cma_backend) {
       mojo_media_services = [
         "cdm",
         "renderer",
       ]
       mojo_media_host = "browser"
+    } else if (is_android) {
+      # Both chrome for Android and cast for ATV belongs to this case
+      mojo_media_services = [
+        "cdm",
+        "audio_decoder",
+      ]
+      mojo_media_host = "gpu"
     } else {
       mojo_media_services = [ "video_decoder" ]
       mojo_media_host = "gpu"
diff --git a/media/mojo/interfaces/media_types.typemap b/media/mojo/interfaces/media_types.typemap
index db421145..a10cdf6 100644
--- a/media/mojo/interfaces/media_types.typemap
+++ b/media/mojo/interfaces/media_types.typemap
@@ -19,8 +19,11 @@
 
 traits_headers = [ "//media/base/ipc/media_param_traits_macros.h" ]
 
-deps = [
+public_deps = [
   "//media",
+]
+
+deps = [
   "//media/base/ipc",
 ]
 
diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc
index 218a350f..ae96faa 100644
--- a/mojo/public/cpp/system/simple_watcher.cc
+++ b/mojo/public/cpp/system/simple_watcher.cc
@@ -26,8 +26,10 @@
       WatcherHandle watcher_handle,
       Handle handle,
       MojoHandleSignals signals,
+      int watch_id,
       MojoResult* watch_result) {
-    scoped_refptr<Context> context = new Context(watcher, task_runner);
+    scoped_refptr<Context> context =
+        new Context(watcher, task_runner, watch_id);
 
     // If MojoWatch succeeds, it assumes ownership of a reference to |context|.
     // In that case, this reference is balanced in CallNotify() when |result| is
@@ -69,8 +71,11 @@
   friend class base::RefCountedThreadSafe<Context>;
 
   Context(base::WeakPtr<SimpleWatcher> weak_watcher,
-          scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-      : weak_watcher_(weak_watcher), task_runner_(task_runner) {}
+          scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+          int watch_id)
+      : weak_watcher_(weak_watcher),
+        task_runner_(task_runner),
+        watch_id_(watch_id) {}
   ~Context() {}
 
   void Notify(MojoResult result,
@@ -95,16 +100,17 @@
       // System notifications will trigger from the task runner passed to
       // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the
       // default task runner for the IO thread.
-      weak_watcher_->OnHandleReady(make_scoped_refptr(this), result);
+      weak_watcher_->OnHandleReady(watch_id_, result);
     } else {
       task_runner_->PostTask(
           FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, weak_watcher_,
-                                make_scoped_refptr(this), result));
+                                watch_id_, result));
     }
   }
 
   const base::WeakPtr<SimpleWatcher> weak_watcher_;
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  const int watch_id_;
 
   base::Lock lock_;
   bool enable_cancellation_notifications_ = true;
@@ -145,11 +151,12 @@
 
   callback_ = callback;
   handle_ = handle;
+  watch_id_ += 1;
 
   MojoResult watch_result = MOJO_RESULT_UNKNOWN;
-  context_ =
-      Context::Create(weak_factory_.GetWeakPtr(), task_runner_,
-                      watcher_handle_.get(), handle_, signals, &watch_result);
+  context_ = Context::Create(weak_factory_.GetWeakPtr(), task_runner_,
+                             watcher_handle_.get(), handle_, signals, watch_id_,
+                             &watch_result);
   if (!context_) {
     handle_.set_value(kInvalidHandleValue);
     callback_.Reset();
@@ -227,16 +234,15 @@
   DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
   task_runner_->PostTask(FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady,
                                                weak_factory_.GetWeakPtr(),
-                                               context_, ready_result));
+                                               watch_id_, ready_result));
 }
 
-void SimpleWatcher::OnHandleReady(scoped_refptr<const Context> context,
-                                  MojoResult result) {
+void SimpleWatcher::OnHandleReady(int watch_id, MojoResult result) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   // This notification may be for a previously watched context, in which case
   // we just ignore it.
-  if (context != context_)
+  if (watch_id != watch_id_)
     return;
 
   ReadyCallback callback = callback_;
diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h
index 5e5a7ea3..9001884 100644
--- a/mojo/public/cpp/system/simple_watcher.h
+++ b/mojo/public/cpp/system/simple_watcher.h
@@ -164,7 +164,7 @@
  private:
   class Context;
 
-  void OnHandleReady(scoped_refptr<const Context> context, MojoResult result);
+  void OnHandleReady(int watch_id, MojoResult result);
 
   base::ThreadChecker thread_checker_;
 
@@ -190,6 +190,10 @@
   // The handle currently under watch. Not owned.
   Handle handle_;
 
+  // A simple counter to disambiguate notifications from multiple watch contexts
+  // in the event that this SimpleWatcher cancels and watches multiple times.
+  int watch_id_ = 0;
+
   // The callback to call when the handle is signaled.
   ReadyCallback callback_;
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 2cf5735b..4ff5d00b 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1470,8 +1470,6 @@
       "spdy/hpack/hpack_constants.h",
       "spdy/hpack/hpack_decoder.cc",
       "spdy/hpack/hpack_decoder.h",
-      "spdy/hpack/hpack_decoder2.cc",
-      "spdy/hpack/hpack_decoder2.h",
       "spdy/hpack/hpack_decoder3.cc",
       "spdy/hpack/hpack_decoder3.h",
       "spdy/hpack/hpack_decoder_interface.h",
@@ -4611,7 +4609,6 @@
     "spdy/buffered_spdy_framer_unittest.cc",
     "spdy/fuzzing/hpack_fuzz_util_test.cc",
     "spdy/header_coalescer_test.cc",
-    "spdy/hpack/hpack_decoder2_test.cc",
     "spdy/hpack/hpack_decoder3_test.cc",
     "spdy/hpack/hpack_decoder_test.cc",
     "spdy/hpack/hpack_encoder_test.cc",
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc
index 8a784bf..056f34b 100644
--- a/net/quic/core/quic_headers_stream_test.cc
+++ b/net/quic/core/quic_headers_stream_test.cc
@@ -150,13 +150,11 @@
   return os;
 }
 
-enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER2, HPACK_DECODER3 };
+enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER3 };
 std::ostream& operator<<(std::ostream& os, HpackDecoderChoice v) {
   switch (v) {
     case HPACK_DECODER_SPDY:
       return os << "SPDY";
-    case HPACK_DECODER2:
-      return os << "HPACK_DECODER2";
     case HPACK_DECODER3:
       return os << "HPACK_DECODER3";
   }
@@ -191,15 +189,9 @@
     }
     switch (hpack_decoder) {
       case HPACK_DECODER_SPDY:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
-        break;
-      case HPACK_DECODER2:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = true;
         FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
         break;
       case HPACK_DECODER3:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
         FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
         break;
     }
@@ -407,13 +399,13 @@
 INSTANTIATE_TEST_CASE_P(
     Tests,
     QuicHeadersStreamTest,
-    ::testing::Combine(
-        ::testing::ValuesIn(AllSupportedVersions()),
-        ::testing::Values(Perspective::IS_CLIENT, Perspective::IS_SERVER),
-        ::testing::Values(HTTP2_DECODER_SPDY,
-                          HTTP2_DECODER_NESTED_SPDY,
-                          HTTP2_DECODER_NEW),
-        ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER2, HPACK_DECODER3)));
+    ::testing::Combine(::testing::ValuesIn(AllSupportedVersions()),
+                       ::testing::Values(Perspective::IS_CLIENT,
+                                         Perspective::IS_SERVER),
+                       ::testing::Values(HTTP2_DECODER_SPDY,
+                                         HTTP2_DECODER_NESTED_SPDY,
+                                         HTTP2_DECODER_NEW),
+                       ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER3)));
 
 TEST_P(QuicHeadersStreamTest, StreamId) {
   EXPECT_EQ(3u, headers_stream_->id());
@@ -755,9 +747,8 @@
   stream_frame_.data_buffer = frame.data();
   stream_frame_.data_length = frame.size();
   headers_stream_->OnStreamFrame(stream_frame_);
-  EXPECT_EQ(kTestHeaderTableSize,
-            QuicSpdySessionPeer::GetSpdyFramer(&session_)
-                .header_encoder_table_size());
+  EXPECT_EQ(kTestHeaderTableSize, QuicSpdySessionPeer::GetSpdyFramer(&session_)
+                                      .header_encoder_table_size());
 }
 
 TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
diff --git a/net/spdy/hpack/hpack_decoder2.cc b/net/spdy/hpack/hpack_decoder2.cc
deleted file mode 100644
index 14ff94e990f..0000000
--- a/net/spdy/hpack/hpack_decoder2.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/spdy/hpack/hpack_decoder2.h"
-
-#include <list>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "net/http2/decoder/decode_buffer.h"
-#include "net/http2/decoder/decode_status.h"
-#include "net/spdy/hpack/hpack_entry.h"
-#include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
-
-using base::StringPiece;
-
-namespace net {
-
-HpackDecoder2::HpackDecoder2() : hpack_block_decoder_(this) {
-  Reset();
-}
-
-HpackDecoder2::~HpackDecoder2() {}
-
-void HpackDecoder2::Reset() {
-  DVLOG(2) << "HpackDecoder2::Reset";
-  handler_ = nullptr;
-
-  hpack_block_decoder_.Reset();
-  hpack_block_decoder_.set_listener(this);
-
-  total_hpack_bytes_ = 0;
-  total_header_bytes_ = 0;
-  size_update_count_ = 0;
-  header_seen_ = false;
-  in_progress_ = false;
-  error_detected_ = false;
-  header_block_started_ = false;
-
-  name_.Reset();
-  value_.Reset();
-}
-
-void HpackDecoder2::SetErrorDetected() {
-  if (!error_detected_) {
-    DVLOG(2) << "HpackDecoder2::SetErrorDetected";
-    hpack_block_decoder_.set_listener(&no_op_listener_);
-    error_detected_ = true;
-  }
-}
-
-void HpackDecoder2::ApplyHeaderTableSizeSetting(size_t size_setting) {
-  DVLOG(2) << "HpackDecoder2::ApplyHeaderTableSizeSetting";
-  header_table_.SetSettingsHeaderTableSize(size_setting);
-}
-
-// If a SpdyHeadersHandlerInterface is provided, the decoder will emit
-// headers to it rather than accumulating them in a SpdyHeaderBlock.
-void HpackDecoder2::HandleControlFrameHeadersStart(
-    SpdyHeadersHandlerInterface* handler) {
-  DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersStart";
-  DCHECK(!header_block_started_);
-  handler_ = handler;
-}
-
-// Called as HPACK block fragments arrive. Returns false
-// if an error occurred while decoding the block.
-bool HpackDecoder2::HandleControlFrameHeadersData(const char* headers_data,
-                                                  size_t headers_data_length) {
-  DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersData: len="
-           << headers_data_length;
-  if (!header_block_started_) {
-    DCHECK_EQ(total_hpack_bytes_, 0u);
-    // Clear the SpdyHeaderBlock here rather than in Reset so that it is NOT
-    // cleared in HandleControlFrameHeadersComplete, which would be before it
-    // could be used.
-    decoded_block_.clear();
-    header_block_started_ = true;
-    if (handler_ != nullptr) {
-      handler_->OnHeaderBlockStart();
-    }
-  }
-
-  // Sometimes we get a call with headers_data==nullptr and
-  // headers_data_length==0, in which case we need to avoid creating
-  // a DecodeBuffer, which would otherwise complain.
-  if (headers_data_length > 0) {
-    DCHECK_NE(headers_data, nullptr);
-    total_hpack_bytes_ += headers_data_length;
-    DecodeBuffer db(headers_data, headers_data_length);
-    DecodeStatus status = hpack_block_decoder_.Decode(&db);
-    switch (status) {
-      case DecodeStatus::kDecodeDone:
-        // We've completed the decoding of headers_data, and it ended at the
-        // boundary between two HPACK block entries, so name_ and value_ are
-        // currently reset.
-        DCHECK_EQ(0u, db.Remaining());
-        in_progress_ = false;
-        break;
-
-      case DecodeStatus::kDecodeInProgress:
-        DCHECK_EQ(0u, db.Remaining());
-        in_progress_ = true;
-        if (!error_detected_) {
-          name_.BufferStringIfUnbuffered();
-          value_.BufferStringIfUnbuffered();
-          EnforceMaxDecodeBufferSize();
-        }
-        break;
-
-      case DecodeStatus::kDecodeError:
-        SetErrorDetected();
-        break;
-    }
-  }
-  return !error_detected_;
-}
-
-// Called after a HPACK block has been completely delivered via
-// HandleControlFrameHeadersData(). Returns false if an error occurred.
-// |compressed_len| if non-null will be set to the size of the encoded
-// buffered block that was accumulated in HandleControlFrameHeadersData(),
-// to support subsequent calculation of compression percentage.
-// Discards the handler supplied at the start of decoding the block.
-// TODO(jamessynge): Determine if compressed_len is needed; it is used to
-// produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for
-// SPDY3, not HTTP2.
-bool HpackDecoder2::HandleControlFrameHeadersComplete(size_t* compressed_len) {
-  DVLOG(2) << "HpackDecoder2::HandleControlFrameHeadersComplete";
-  if (error_detected_ || in_progress_) {
-    DVLOG(2) << "error_detected_=" << error_detected_
-             << ", in_progress_=" << in_progress_;
-    return false;
-  }
-  if (compressed_len != nullptr) {
-    *compressed_len = total_hpack_bytes_;
-  }
-  if (handler_ != nullptr) {
-    handler_->OnHeaderBlockEnd(total_header_bytes_);
-  }
-  Reset();
-  return true;
-}
-
-const SpdyHeaderBlock& HpackDecoder2::decoded_block() const {
-  return decoded_block_;
-}
-
-void HpackDecoder2::SetHeaderTableDebugVisitor(
-    std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
-  DVLOG(2) << "HpackDecoder2::SetHeaderTableDebugVisitor";
-  header_table_.set_debug_visitor(std::move(visitor));
-}
-
-void HpackDecoder2::set_max_decode_buffer_size_bytes(
-    size_t max_decode_buffer_size_bytes) {
-  DVLOG(2) << "HpackDecoder2::set_max_decode_buffer_size_bytes";
-  max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes;
-}
-
-size_t HpackDecoder2::EstimateMemoryUsage() const {
-  return SpdyEstimateMemoryUsage(header_table_) +
-         SpdyEstimateMemoryUsage(decoded_block_) +
-         SpdyEstimateMemoryUsage(name_) + SpdyEstimateMemoryUsage(value_);
-}
-
-void HpackDecoder2::OnIndexedHeader(size_t index) {
-  DVLOG(2) << "HpackDecoder2::OnIndexedHeader: index=" << index;
-  DCHECK(!error_detected_);
-  const HpackEntry* entry = header_table_.GetByIndex(index);
-  if (entry == nullptr) {
-    SetErrorDetected();
-    return;
-  }
-  HandleHeaderRepresentation(entry->name(), entry->value());
-}
-
-void HpackDecoder2::OnStartLiteralHeader(HpackEntryType entry_type,
-                                         size_t maybe_name_index) {
-  DVLOG(2) << "HpackDecoder2::OnStartLiteralHeader: entry_type=" << entry_type
-           << ",  maybe_name_index=" << maybe_name_index;
-  DCHECK(!error_detected_);
-  entry_type_ = entry_type;
-  if (maybe_name_index > 0) {
-    const HpackEntry* entry = header_table_.GetByIndex(maybe_name_index);
-    if (entry == nullptr) {
-      SetErrorDetected();
-      return;
-    } else {
-      // Non-static entries could be evicted, leaving us with a dangling
-      // pointer, so we preemptively copy. This could be avoided if
-      // TryAddEntry would copy the strings prior to performing eviction.
-      name_.Set(entry->name(), entry->IsStatic());
-      name_.BufferStringIfUnbuffered();
-    }
-  }
-}
-
-void HpackDecoder2::OnNameStart(bool huffman_encoded, size_t len) {
-  DVLOG(2) << "HpackDecoder2::OnNameStart: huffman_encoded="
-           << (huffman_encoded ? "true" : "false") << ",  len=" << len;
-  if (len > max_decode_buffer_size_bytes_) {
-    DVLOG(1) << "Name length (" << len << ") is longer than permitted ("
-             << max_decode_buffer_size_bytes_ << ")";
-    SetErrorDetected();
-    return;
-  }
-  name_.OnStart(huffman_encoded, len);
-}
-
-void HpackDecoder2::OnNameData(const char* data, size_t len) {
-  DVLOG(2) << "HpackDecoder2::OnNameData: len=" << len
-           << "\n data: " << StringPiece(data, len);
-  if (error_detected_) {
-    return;
-  }
-  if (!name_.OnData(data, len)) {
-    SetErrorDetected();
-  }
-}
-
-void HpackDecoder2::OnNameEnd() {
-  DVLOG(2) << "HpackDecoder2::OnNameEnd";
-  if (error_detected_) {
-    return;
-  }
-  if (!name_.OnEnd()) {
-    SetErrorDetected();
-  }
-}
-
-void HpackDecoder2::OnValueStart(bool huffman_encoded, size_t len) {
-  DVLOG(2) << "HpackDecoder2::OnValueStart: huffman_encoded="
-           << (huffman_encoded ? "true" : "false") << ",  len=" << len;
-  if (len > max_decode_buffer_size_bytes_) {
-    DVLOG(1) << "Value length (" << len << ") is longer than permitted ("
-             << max_decode_buffer_size_bytes_ << ")";
-    SetErrorDetected();
-    return;
-  }
-  value_.OnStart(huffman_encoded, len);
-}
-
-void HpackDecoder2::OnValueData(const char* data, size_t len) {
-  DVLOG(2) << "HpackDecoder2::OnValueData: len=" << len
-           << "\n data: " << StringPiece(data, len);
-  if (error_detected_) {
-    return;
-  }
-  if (!value_.OnData(data, len)) {
-    SetErrorDetected();
-  }
-}
-
-void HpackDecoder2::OnValueEnd() {
-  DVLOG(2) << "HpackDecoder2::OnValueEnd";
-  if (error_detected_) {
-    return;
-  }
-  if (!value_.OnEnd()) {
-    SetErrorDetected();
-    return;
-  }
-  if (EnforceMaxDecodeBufferSize()) {
-    // All is well.
-    HandleHeaderRepresentation(name_.str(), value_.str());
-    if (entry_type_ == HpackEntryType::kIndexedLiteralHeader) {
-      header_table_.TryAddEntry(name_.str(), value_.str());
-    }
-    name_.Reset();
-    value_.Reset();
-  }
-}
-
-void HpackDecoder2::OnDynamicTableSizeUpdate(size_t size) {
-  DVLOG(2) << "HpackDecoder2::OnDynamicTableSizeUpdate: size=" << size;
-  if (error_detected_) {
-    return;
-  }
-  if (size > header_table_.settings_size_bound()) {
-    DVLOG(1) << "Dynamic Table Size Update with too large a size: " << size
-             << " > " << header_table_.settings_size_bound();
-    SetErrorDetected();
-    return;
-  }
-  if (header_seen_) {
-    DVLOG(1) << "Dynamic Table Size Update seen after a Header";
-    SetErrorDetected();
-    return;
-  }
-  ++size_update_count_;
-  if (size_update_count_ > 2) {
-    DVLOG(1) << "Too many (" << size_update_count_
-             << ") Dynamic Table Size Updates";
-    SetErrorDetected();
-    return;
-  }
-  header_table_.SetMaxSize(size);
-  return;
-}
-
-bool HpackDecoder2::EnforceMaxDecodeBufferSize() {
-  if (!error_detected_) {
-    size_t buffered_length = name_.BufferedLength() + value_.BufferedLength();
-    DVLOG(2) << "buffered_length=" << buffered_length
-             << "; max=" << max_decode_buffer_size_bytes_;
-    if (buffered_length > max_decode_buffer_size_bytes_) {
-      DVLOG(1) << "Header length (" << buffered_length
-               << ") is longer than permitted ("
-               << max_decode_buffer_size_bytes_ << ")";
-      SetErrorDetected();
-    }
-  }
-  return !error_detected_;
-}
-
-void HpackDecoder2::HandleHeaderRepresentation(StringPiece name,
-                                               StringPiece value) {
-  DVLOG(2) << "HpackDecoder2::HandleHeaderRepresentation:\n name: " << name
-           << "\n value: " << value;
-  total_header_bytes_ += name.size() + value.size();
-  header_seen_ = true;
-  if (handler_ == nullptr) {
-    DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
-             << "adding to decoded_block";
-    decoded_block_.AppendValueOrAddHeader(name, value);
-  } else {
-    DVLOG(3) << "HpackDecoder2::HandleHeaderRepresentation "
-             << "passing to handler";
-    DCHECK(decoded_block_.empty());
-    handler_->OnHeader(name, value);
-  }
-}
-
-}  // namespace net
diff --git a/net/spdy/hpack/hpack_decoder2.h b/net/spdy/hpack/hpack_decoder2.h
deleted file mode 100644
index 614ac01..0000000
--- a/net/spdy/hpack/hpack_decoder2.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SPDY_HPACK_HPACK_DECODER2_H_
-#define NET_SPDY_HPACK_HPACK_DECODER2_H_
-
-// HpackDecoder2
-
-// An HpackDecoder decodes header sets as outlined in
-// http://tools.ietf.org/html/rfc7541. This implementation uses the
-// new HpackBlockDecoder in //net/http2/hpack/
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-#include "net/http2/hpack/decoder/hpack_block_decoder.h"
-#include "net/http2/hpack/decoder/hpack_decoder_string_buffer.h"
-#include "net/http2/hpack/decoder/hpack_entry_decoder_listener.h"
-#include "net/http2/hpack/http2_hpack_constants.h"
-#include "net/http2/hpack/huffman/http2_hpack_huffman_decoder.h"
-#include "net/spdy/hpack/hpack_constants.h"
-#include "net/spdy/hpack/hpack_decoder_interface.h"
-#include "net/spdy/hpack/hpack_header_table.h"
-#include "net/spdy/spdy_header_block.h"
-#include "net/spdy/spdy_headers_handler_interface.h"
-
-namespace net {
-namespace test {
-class HpackDecoder2Peer;
-}  // namespace test
-
-class NET_EXPORT_PRIVATE HpackDecoder2 : public HpackDecoderInterface,
-                                         HpackEntryDecoderListener {
- public:
-  friend test::HpackDecoder2Peer;
-  HpackDecoder2();
-  ~HpackDecoder2() override;
-
-  // Override the interface methods:
-
-  void ApplyHeaderTableSizeSetting(size_t size_setting) override;
-  void HandleControlFrameHeadersStart(
-      SpdyHeadersHandlerInterface* handler) override;
-  bool HandleControlFrameHeadersData(const char* headers_data,
-                                     size_t headers_data_length) override;
-  bool HandleControlFrameHeadersComplete(size_t* compressed_len) override;
-  const SpdyHeaderBlock& decoded_block() const override;
-  void SetHeaderTableDebugVisitor(
-      std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor)
-      override;
-  void set_max_decode_buffer_size_bytes(
-      size_t max_decode_buffer_size_bytes) override;
-  size_t EstimateMemoryUsage() const override;
-
- protected:
-  // Override the HpackEntryDecoderListener methods:
-
-  void OnIndexedHeader(size_t index) override;
-  void OnStartLiteralHeader(HpackEntryType entry_type,
-                            size_t maybe_name_index) override;
-  void OnNameStart(bool huffman_encoded, size_t len) override;
-  void OnNameData(const char* data, size_t len) override;
-  void OnNameEnd() override;
-  void OnValueStart(bool huffman_encoded, size_t len) override;
-  void OnValueData(const char* data, size_t len) override;
-  void OnValueEnd() override;
-  void OnDynamicTableSizeUpdate(size_t size) override;
-
- private:
-  // Called when a complete header entry has been decoded, with the name and
-  // value of the entry. If check_header_order_ is true, confirms that
-  // pseudo-headers don't appear after normal headers, else it treats the
-  // headers as malformed, as per sections 8.1.2.3. of the HTTP2 specification.
-  // Calls handler_->OnHeader() if there is a handler, else adds the header
-  // to decoded_block_.
-  void HandleHeaderRepresentation(base::StringPiece name,
-                                  base::StringPiece value);
-
-  // Reset state in preparation for decoding a new HPACK block. Does not reset
-  // the dynamic table.
-  void Reset();
-
-  // Called when an error is detected while decoding. Replaces the listener
-  // in the HpackBlockDecoder with the no-op listener.
-  void SetErrorDetected();
-
-  // Enforce the limit on the maximum size of strings that can be buffered.
-  // It happens that this test is made after the strings have been buffered,
-  // but that isn't a problem because we don't pass enormous buffers into
-  // HandleControlFrameHeadersData.
-  bool EnforceMaxDecodeBufferSize();
-
-  HpackHeaderTable header_table_;
-  SpdyHeaderBlock decoded_block_;
-
-  // Scratch space for storing decoded literals.
-  HpackDecoderStringBuffer name_, value_;
-
-  // If non-NULL, handles decoded headers.
-  SpdyHeadersHandlerInterface* handler_;
-
-  HpackEntryDecoderNoOpListener no_op_listener_;
-
-  // Total bytes that have been received as input (i.e. HPACK encoded).
-  size_t total_hpack_bytes_;
-
-  // Total bytes of the name and value strings in the current HPACK block.
-  size_t total_header_bytes_;
-
-  // How much encoded data this decoder is willing to buffer.
-  size_t max_decode_buffer_size_bytes_ = 32 * 1024;  // 32 KB
-
-  HpackBlockDecoder hpack_block_decoder_;
-
-  // Count of Dynamic Table Size Updates seen in the current HPACK block.
-  uint32_t size_update_count_;
-
-  // The type of the current header entry (with literals) that is being decoded.
-  HpackEntryType entry_type_;
-
-  // Has a header been seen in the current HPACK block?
-  bool header_seen_;
-
-  // Did the HpackBlockDecoder stop in the middle of an entry?
-  bool in_progress_;
-
-  // Has an error been detected while decoding the HPACK block?
-  bool error_detected_;
-
-  // Flag to keep track of having seen the header block start. Needed at the
-  // moment because HandleControlFrameHeadersStart won't be called if a handler
-  // is not being provided by the caller.
-  // TODO(jamessynge): Consider collapsing several of these bools into a single
-  // enum representing the state of the decoding process.
-  bool header_block_started_;
-
-  DISALLOW_COPY_AND_ASSIGN(HpackDecoder2);
-};
-
-}  // namespace net
-#endif  // NET_SPDY_HPACK_HPACK_DECODER2_H_
diff --git a/net/spdy/hpack/hpack_decoder2_test.cc b/net/spdy/hpack/hpack_decoder2_test.cc
deleted file mode 100644
index 8c70051..0000000
--- a/net/spdy/hpack/hpack_decoder2_test.cc
+++ /dev/null
@@ -1,959 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/spdy/hpack/hpack_decoder2.h"
-
-// Tests of HpackDecoder2.
-
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "net/http2/hpack/tools/hpack_block_builder.h"
-#include "net/http2/tools/http2_random.h"
-#include "net/spdy/hpack/hpack_encoder.h"
-#include "net/spdy/hpack/hpack_entry.h"
-#include "net/spdy/hpack/hpack_huffman_table.h"
-#include "net/spdy/hpack/hpack_output_stream.h"
-#include "net/spdy/spdy_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::StringPiece;
-using std::string;
-
-namespace net {
-namespace test {
-
-class HpackDecoder2Peer {
- public:
-  explicit HpackDecoder2Peer(HpackDecoder2* decoder) : decoder_(decoder) {}
-
-  void HandleHeaderRepresentation(StringPiece name, StringPiece value) {
-    decoder_->HandleHeaderRepresentation(name, value);
-  }
-  HpackHeaderTable* header_table() { return &decoder_->header_table_; }
-
- private:
-  HpackDecoder2* decoder_;
-};
-
-namespace {
-
-using testing::ElementsAre;
-using testing::Pair;
-
-// Is HandleControlFrameHeadersStart to be called, and with what value?
-enum StartChoice { START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START };
-
-class HpackDecoder2Test
-    : public ::testing::TestWithParam<std::tuple<StartChoice, bool>> {
- protected:
-  HpackDecoder2Test() : decoder_(), decoder_peer_(&decoder_) {}
-
-  void SetUp() override {
-    std::tie(start_choice_, randomly_split_input_buffer_) = GetParam();
-  }
-
-  void HandleControlFrameHeadersStart() {
-    switch (start_choice_) {
-      case START_WITH_HANDLER:
-        decoder_.HandleControlFrameHeadersStart(&handler_);
-        break;
-      case START_WITHOUT_HANDLER:
-        decoder_.HandleControlFrameHeadersStart(nullptr);
-        break;
-      case NO_START:
-        break;
-    }
-  }
-
-  bool HandleControlFrameHeadersData(StringPiece str) {
-    return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
-  }
-
-  bool HandleControlFrameHeadersComplete(size_t* size) {
-    return decoder_.HandleControlFrameHeadersComplete(size);
-  }
-
-  bool DecodeHeaderBlock(StringPiece str) {
-    // Don't call this again if HandleControlFrameHeadersData failed previously.
-    EXPECT_FALSE(decode_has_failed_);
-    HandleControlFrameHeadersStart();
-    if (randomly_split_input_buffer_) {
-      do {
-        // Decode some fragment of the remaining bytes.
-        size_t bytes = str.length();
-        if (!str.empty()) {
-          bytes = (random_.Rand8() % str.length()) + 1;
-        }
-        EXPECT_LE(bytes, str.length());
-        if (!HandleControlFrameHeadersData(str.substr(0, bytes))) {
-          decode_has_failed_ = true;
-          return false;
-        }
-        str.remove_prefix(bytes);
-      } while (!str.empty());
-    } else if (!HandleControlFrameHeadersData(str)) {
-      decode_has_failed_ = true;
-      return false;
-    }
-    if (!HandleControlFrameHeadersComplete(nullptr)) {
-      decode_has_failed_ = true;
-      return false;
-    }
-    return true;
-  }
-
-  const SpdyHeaderBlock& decoded_block() const {
-    if (start_choice_ == START_WITH_HANDLER) {
-      return handler_.decoded_block();
-    } else {
-      return decoder_.decoded_block();
-    }
-  }
-
-  const SpdyHeaderBlock& DecodeBlockExpectingSuccess(StringPiece str) {
-    EXPECT_TRUE(DecodeHeaderBlock(str));
-    return decoded_block();
-  }
-
-  void expectEntry(size_t index,
-                   size_t size,
-                   const string& name,
-                   const string& value) {
-    const HpackEntry* entry = decoder_peer_.header_table()->GetByIndex(index);
-    EXPECT_EQ(name, entry->name()) << "index " << index;
-    EXPECT_EQ(value, entry->value());
-    EXPECT_EQ(size, entry->Size());
-    EXPECT_EQ(index, decoder_peer_.header_table()->IndexOf(entry));
-  }
-
-  SpdyHeaderBlock MakeHeaderBlock(
-      const std::vector<std::pair<string, string>>& headers) {
-    SpdyHeaderBlock result;
-    for (const auto& kv : headers) {
-      result.AppendValueOrAddHeader(kv.first, kv.second);
-    }
-    return result;
-  }
-
-  Http2Random random_;
-  HpackDecoder2 decoder_;
-  test::HpackDecoder2Peer decoder_peer_;
-  TestHeadersHandler handler_;
-  StartChoice start_choice_;
-  bool randomly_split_input_buffer_;
-  bool decode_has_failed_ = false;
-};
-
-INSTANTIATE_TEST_CASE_P(
-    StartChoiceAndRandomlySplitChoice,
-    HpackDecoder2Test,
-    ::testing::Combine(
-        ::testing::Values(START_WITH_HANDLER, START_WITHOUT_HANDLER, NO_START),
-        ::testing::Bool()));
-
-TEST_P(HpackDecoder2Test, AddHeaderDataWithHandleControlFrameHeadersData) {
-  // The hpack decode buffer size is limited in size. This test verifies that
-  // adding encoded data under that limit is accepted, and data that exceeds the
-  // limit is rejected.
-  HandleControlFrameHeadersStart();
-  const size_t kMaxBufferSizeBytes = 50;
-  const string a_value = string(49, 'x');
-  decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
-  {
-    HpackBlockBuilder hbb;
-    hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
-                                  false, "a", false, a_value);
-    const auto& s = hbb.buffer();
-    EXPECT_TRUE(decoder_.HandleControlFrameHeadersData(s.data(), s.size()));
-  }
-  {
-    HpackBlockBuilder hbb;
-    hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
-                                  false, "b", false, string(51, 'x'));
-    const auto& s = hbb.buffer();
-    EXPECT_FALSE(decoder_.HandleControlFrameHeadersData(s.data(), s.size()));
-  }
-
-  SpdyHeaderBlock expected_block = MakeHeaderBlock({{"a", a_value}});
-  EXPECT_EQ(expected_block, decoded_block());
-}
-
-TEST_P(HpackDecoder2Test, NameTooLong) {
-  // Verify that a name longer than the allowed size generates an error.
-  const size_t kMaxBufferSizeBytes = 50;
-  const string name = string(2 * kMaxBufferSizeBytes, 'x');
-  const string value = "abc";
-
-  decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
-
-  HpackBlockBuilder hbb;
-  hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
-                                false, name, false, value);
-
-  const size_t fragment_size = (3 * kMaxBufferSizeBytes) / 2;
-  const string fragment = hbb.buffer().substr(0, fragment_size);
-
-  HandleControlFrameHeadersStart();
-  EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
-}
-
-TEST_P(HpackDecoder2Test, HeaderTooLongToBuffer) {
-  // Verify that a header longer than the allowed size generates an error if
-  // it isn't all in one input buffer.
-  const string name = "some-key";
-  const string value = "some-value";
-  const size_t kMaxBufferSizeBytes = name.size() + value.size() - 2;
-  decoder_.set_max_decode_buffer_size_bytes(kMaxBufferSizeBytes);
-
-  HpackBlockBuilder hbb;
-  hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader,
-                                false, name, false, value);
-  const size_t fragment_size = hbb.size() - 1;
-  const string fragment = hbb.buffer().substr(0, fragment_size);
-
-  HandleControlFrameHeadersStart();
-  EXPECT_FALSE(HandleControlFrameHeadersData(fragment));
-}
-
-// Decode with incomplete data in buffer.
-TEST_P(HpackDecoder2Test, DecodeWithIncompleteData) {
-  HandleControlFrameHeadersStart();
-
-  // No need to wait for more data.
-  EXPECT_TRUE(HandleControlFrameHeadersData("\x82\x85\x82"));
-  std::vector<std::pair<string, string>> expected_headers = {
-      {":method", "GET"}, {":path", "/index.html"}, {":method", "GET"}};
-
-  SpdyHeaderBlock expected_block1 = MakeHeaderBlock(expected_headers);
-  EXPECT_EQ(expected_block1, decoded_block());
-
-  // Full and partial headers, won't add partial to the headers.
-  EXPECT_TRUE(
-      HandleControlFrameHeadersData("\x40\x03goo"
-                                    "\x03gar\xbe\x40\x04spam"));
-  expected_headers.push_back({"goo", "gar"});
-  expected_headers.push_back({"goo", "gar"});
-
-  SpdyHeaderBlock expected_block2 = MakeHeaderBlock(expected_headers);
-  EXPECT_EQ(expected_block2, decoded_block());
-
-  // Add the needed data.
-  EXPECT_TRUE(HandleControlFrameHeadersData("\x04gggs"));
-
-  size_t size = 0;
-  EXPECT_TRUE(HandleControlFrameHeadersComplete(&size));
-  EXPECT_EQ(24u, size);
-
-  expected_headers.push_back({"spam", "gggs"});
-
-  SpdyHeaderBlock expected_block3 = MakeHeaderBlock(expected_headers);
-  EXPECT_EQ(expected_block3, decoded_block());
-}
-
-TEST_P(HpackDecoder2Test, HandleHeaderRepresentation) {
-  // Make sure the decoder is properly initialized.
-  HandleControlFrameHeadersStart();
-  HandleControlFrameHeadersData("");
-
-  // All cookie crumbs are joined.
-  decoder_peer_.HandleHeaderRepresentation("cookie", " part 1");
-  decoder_peer_.HandleHeaderRepresentation("cookie", "part 2 ");
-  decoder_peer_.HandleHeaderRepresentation("cookie", "part3");
-
-  // Already-delimited headers are passed through.
-  decoder_peer_.HandleHeaderRepresentation("passed-through",
-                                           string("foo\0baz", 7));
-
-  // Other headers are joined on \0. Case matters.
-  decoder_peer_.HandleHeaderRepresentation("joined", "not joined");
-  decoder_peer_.HandleHeaderRepresentation("joineD", "value 1");
-  decoder_peer_.HandleHeaderRepresentation("joineD", "value 2");
-
-  // Empty headers remain empty.
-  decoder_peer_.HandleHeaderRepresentation("empty", "");
-
-  // Joined empty headers work as expected.
-  decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
-  decoder_peer_.HandleHeaderRepresentation("empty-joined", "foo");
-  decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
-  decoder_peer_.HandleHeaderRepresentation("empty-joined", "");
-
-  // Non-contiguous cookie crumb.
-  decoder_peer_.HandleHeaderRepresentation("cookie", " fin!");
-
-  // Finish and emit all headers.
-  decoder_.HandleControlFrameHeadersComplete(nullptr);
-
-  // Resulting decoded headers are in the same order as the inputs.
-  EXPECT_THAT(decoded_block(),
-              ElementsAre(Pair("cookie", " part 1; part 2 ; part3;  fin!"),
-                          Pair("passed-through", StringPiece("foo\0baz", 7)),
-                          Pair("joined", "not joined"),
-                          Pair("joineD", StringPiece("value 1\0value 2", 15)),
-                          Pair("empty", ""),
-                          Pair("empty-joined", StringPiece("\0foo\0\0", 6))));
-}
-
-// Decoding indexed static table field should work.
-TEST_P(HpackDecoder2Test, IndexedHeaderStatic) {
-  // Reference static table entries #2 and #5.
-  const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess("\x82\x85");
-  SpdyHeaderBlock expected_header_set1;
-  expected_header_set1[":method"] = "GET";
-  expected_header_set1[":path"] = "/index.html";
-  EXPECT_EQ(expected_header_set1, header_set1);
-
-  // Reference static table entry #2.
-  const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess("\x82");
-  SpdyHeaderBlock expected_header_set2;
-  expected_header_set2[":method"] = "GET";
-  EXPECT_EQ(expected_header_set2, header_set2);
-}
-
-TEST_P(HpackDecoder2Test, IndexedHeaderDynamic) {
-  // First header block: add an entry to header table.
-  const SpdyHeaderBlock& header_set1 = DecodeBlockExpectingSuccess(
-      "\x40\x03"
-      "foo"
-      "\x03"
-      "bar");
-  SpdyHeaderBlock expected_header_set1;
-  expected_header_set1["foo"] = "bar";
-  EXPECT_EQ(expected_header_set1, header_set1);
-
-  // Second header block: add another entry to header table.
-  const SpdyHeaderBlock& header_set2 = DecodeBlockExpectingSuccess(
-      "\xbe\x40\x04"
-      "spam"
-      "\x04"
-      "eggs");
-  SpdyHeaderBlock expected_header_set2;
-  expected_header_set2["foo"] = "bar";
-  expected_header_set2["spam"] = "eggs";
-  EXPECT_EQ(expected_header_set2, header_set2);
-
-  // Third header block: refer to most recently added entry.
-  const SpdyHeaderBlock& header_set3 = DecodeBlockExpectingSuccess("\xbe");
-  SpdyHeaderBlock expected_header_set3;
-  expected_header_set3["spam"] = "eggs";
-  EXPECT_EQ(expected_header_set3, header_set3);
-}
-
-// Test a too-large indexed header.
-TEST_P(HpackDecoder2Test, InvalidIndexedHeader) {
-  // High-bit set, and a prefix of one more than the number of static entries.
-  EXPECT_FALSE(DecodeHeaderBlock("\xbe"));
-}
-
-TEST_P(HpackDecoder2Test, ContextUpdateMaximumSize) {
-  EXPECT_EQ(kDefaultHeaderTableSizeSetting,
-            decoder_peer_.header_table()->max_size());
-  string input;
-  {
-    // Maximum-size update with size 126. Succeeds.
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(126);
-
-    output_stream.TakeString(&input);
-    EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(126u, decoder_peer_.header_table()->max_size());
-  }
-  {
-    // Maximum-size update with kDefaultHeaderTableSizeSetting. Succeeds.
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(kDefaultHeaderTableSizeSetting);
-
-    output_stream.TakeString(&input);
-    EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(kDefaultHeaderTableSizeSetting,
-              decoder_peer_.header_table()->max_size());
-  }
-  {
-    // Maximum-size update with kDefaultHeaderTableSizeSetting + 1. Fails.
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(kDefaultHeaderTableSizeSetting + 1);
-
-    output_stream.TakeString(&input);
-    EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(kDefaultHeaderTableSizeSetting,
-              decoder_peer_.header_table()->max_size());
-  }
-}
-
-// Two HeaderTableSizeUpdates may appear at the beginning of the block
-TEST_P(HpackDecoder2Test, TwoTableSizeUpdates) {
-  string input;
-  {
-    // Should accept two table size updates, update to second one
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(0);
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(122);
-
-    output_stream.TakeString(&input);
-    EXPECT_TRUE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(122u, decoder_peer_.header_table()->max_size());
-  }
-}
-
-// Three HeaderTableSizeUpdates should result in an error
-TEST_P(HpackDecoder2Test, ThreeTableSizeUpdatesError) {
-  string input;
-  {
-    // Should reject three table size updates, update to second one
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(5);
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(10);
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(15);
-
-    output_stream.TakeString(&input);
-
-    EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(10u, decoder_peer_.header_table()->max_size());
-  }
-}
-
-// HeaderTableSizeUpdates may only appear at the beginning of the block
-// Any other updates should result in an error
-TEST_P(HpackDecoder2Test, TableSizeUpdateSecondError) {
-  string input;
-  {
-    // Should reject a table size update appearing after a different entry
-    // The table size should remain as the default
-    HpackOutputStream output_stream;
-    output_stream.AppendBytes("\x82\x85");
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(123);
-
-    output_stream.TakeString(&input);
-
-    EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(kDefaultHeaderTableSizeSetting,
-              decoder_peer_.header_table()->max_size());
-  }
-}
-
-// HeaderTableSizeUpdates may only appear at the beginning of the block
-// Any other updates should result in an error
-TEST_P(HpackDecoder2Test, TableSizeUpdateFirstThirdError) {
-  string input;
-  {
-    // Should reject the second table size update
-    // if a different entry appears after the first update
-    // The table size should update to the first but not the second
-    HpackOutputStream output_stream;
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(60);
-    output_stream.AppendBytes("\x82\x85");
-    output_stream.AppendPrefix(kHeaderTableSizeUpdateOpcode);
-    output_stream.AppendUint32(125);
-
-    output_stream.TakeString(&input);
-
-    EXPECT_FALSE(DecodeHeaderBlock(StringPiece(input)));
-    EXPECT_EQ(60u, decoder_peer_.header_table()->max_size());
-  }
-}
-
-// Decoding two valid encoded literal headers with no indexing should
-// work.
-TEST_P(HpackDecoder2Test, LiteralHeaderNoIndexing) {
-  // First header with indexed name, second header with string literal
-  // name.
-  const char input[] = "\x04\x0c/sample/path\x00\x06:path2\x0e/sample/path/2";
-  const SpdyHeaderBlock& header_set =
-      DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
-
-  SpdyHeaderBlock expected_header_set;
-  expected_header_set[":path"] = "/sample/path";
-  expected_header_set[":path2"] = "/sample/path/2";
-  EXPECT_EQ(expected_header_set, header_set);
-}
-
-// Decoding two valid encoded literal headers with incremental
-// indexing and string literal names should work.
-TEST_P(HpackDecoder2Test, LiteralHeaderIncrementalIndexing) {
-  const char input[] = "\x44\x0c/sample/path\x40\x06:path2\x0e/sample/path/2";
-  const SpdyHeaderBlock& header_set =
-      DecodeBlockExpectingSuccess(StringPiece(input, arraysize(input) - 1));
-
-  SpdyHeaderBlock expected_header_set;
-  expected_header_set[":path"] = "/sample/path";
-  expected_header_set[":path2"] = "/sample/path/2";
-  EXPECT_EQ(expected_header_set, header_set);
-}
-
-TEST_P(HpackDecoder2Test, LiteralHeaderWithIndexingInvalidNameIndex) {
-  decoder_.ApplyHeaderTableSizeSetting(0);
-
-  // Name is the last static index. Works.
-  EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x7d\x03ooo")));
-  // Name is one beyond the last static index. Fails.
-  EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x7e\x03ooo")));
-}
-
-TEST_P(HpackDecoder2Test, LiteralHeaderNoIndexingInvalidNameIndex) {
-  // Name is the last static index. Works.
-  EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x0f\x2e\x03ooo")));
-  // Name is one beyond the last static index. Fails.
-  EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x0f\x2f\x03ooo")));
-}
-
-TEST_P(HpackDecoder2Test, LiteralHeaderNeverIndexedInvalidNameIndex) {
-  // Name is the last static index. Works.
-  EXPECT_TRUE(DecodeHeaderBlock(StringPiece("\x1f\x2e\x03ooo")));
-  // Name is one beyond the last static index. Fails.
-  EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\x1f\x2f\x03ooo")));
-}
-
-TEST_P(HpackDecoder2Test, TruncatedIndex) {
-  // Indexed Header, varint for index requires multiple bytes,
-  // but only one provided.
-  EXPECT_FALSE(DecodeHeaderBlock(StringPiece("\xff", 1)));
-}
-
-TEST_P(HpackDecoder2Test, TruncatedHuffmanLiteral) {
-  // Literal value, Huffman encoded, but with the last byte missing (i.e.
-  // drop the final ff shown below).
-  //
-  // 41                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 1)
-  //                                         |     :authority
-  // 8c                                      |   Literal value (len = 12)
-  //                                         |     Huffman encoded:
-  // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
-  //                                         |     Decoded:
-  //                                         | www.example.com
-  //                                         | -> :authority: www.example.com
-
-  string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
-  EXPECT_TRUE(DecodeHeaderBlock(first));
-  first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4");
-  EXPECT_FALSE(DecodeHeaderBlock(first));
-}
-
-TEST_P(HpackDecoder2Test, HuffmanEOSError) {
-  // Literal value, Huffman encoded, but with an additional ff byte at the end
-  // of the string, i.e. an EOS that is longer than permitted.
-  //
-  // 41                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 1)
-  //                                         |     :authority
-  // 8d                                      |   Literal value (len = 13)
-  //                                         |     Huffman encoded:
-  // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
-  //                                         |     Decoded:
-  //                                         | www.example.com
-  //                                         | -> :authority: www.example.com
-
-  string first = a2b_hex("418cf1e3c2e5f23a6ba0ab90f4ff");
-  EXPECT_TRUE(DecodeHeaderBlock(first));
-  first = a2b_hex("418df1e3c2e5f23a6ba0ab90f4ffff");
-  EXPECT_FALSE(DecodeHeaderBlock(first));
-}
-
-// Round-tripping the header set from RFC 7541 C.3.1 should work.
-// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
-TEST_P(HpackDecoder2Test, BasicC31) {
-  HpackEncoder encoder(ObtainHpackHuffmanTable());
-
-  SpdyHeaderBlock expected_header_set;
-  expected_header_set[":method"] = "GET";
-  expected_header_set[":scheme"] = "http";
-  expected_header_set[":path"] = "/";
-  expected_header_set[":authority"] = "www.example.com";
-
-  string encoded_header_set;
-  EXPECT_TRUE(
-      encoder.EncodeHeaderSet(expected_header_set, &encoded_header_set));
-
-  EXPECT_TRUE(DecodeHeaderBlock(encoded_header_set));
-  EXPECT_EQ(expected_header_set, decoded_block());
-}
-
-// RFC 7541, Section C.4: Request Examples with Huffman Coding
-// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
-TEST_P(HpackDecoder2Test, SectionC4RequestHuffmanExamples) {
-  // TODO(jamessynge): Use net/http2/hpack/tools/hpack_example.h to parse the
-  // example directly, instead of having it as a comment.
-  // 82                                      | == Indexed - Add ==
-  //                                         |   idx = 2
-  //                                         | -> :method: GET
-  // 86                                      | == Indexed - Add ==
-  //                                         |   idx = 6
-  //                                         | -> :scheme: http
-  // 84                                      | == Indexed - Add ==
-  //                                         |   idx = 4
-  //                                         | -> :path: /
-  // 41                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 1)
-  //                                         |     :authority
-  // 8c                                      |   Literal value (len = 12)
-  //                                         |     Huffman encoded:
-  // f1e3 c2e5 f23a 6ba0 ab90 f4ff           | .....:k.....
-  //                                         |     Decoded:
-  //                                         | www.example.com
-  //                                         | -> :authority: www.example.com
-  string first = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4ff");
-  const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
-
-  EXPECT_THAT(first_header_set,
-              ElementsAre(
-                  // clang-format off
-      Pair(":method", "GET"),
-      Pair(":scheme", "http"),
-      Pair(":path", "/"),
-      Pair(":authority", "www.example.com")));
-  // clang-format on
-
-  expectEntry(62, 57, ":authority", "www.example.com");
-  EXPECT_EQ(57u, decoder_peer_.header_table()->size());
-
-  // 82                                      | == Indexed - Add ==
-  //                                         |   idx = 2
-  //                                         | -> :method: GET
-  // 86                                      | == Indexed - Add ==
-  //                                         |   idx = 6
-  //                                         | -> :scheme: http
-  // 84                                      | == Indexed - Add ==
-  //                                         |   idx = 4
-  //                                         | -> :path: /
-  // be                                      | == Indexed - Add ==
-  //                                         |   idx = 62
-  //                                         | -> :authority: www.example.com
-  // 58                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 24)
-  //                                         |     cache-control
-  // 86                                      |   Literal value (len = 8)
-  //                                         |     Huffman encoded:
-  // a8eb 1064 9cbf                          | ...d..
-  //                                         |     Decoded:
-  //                                         | no-cache
-  //                                         | -> cache-control: no-cache
-
-  string second = a2b_hex("828684be5886a8eb10649cbf");
-  const SpdyHeaderBlock& second_header_set =
-      DecodeBlockExpectingSuccess(second);
-
-  EXPECT_THAT(second_header_set,
-              ElementsAre(
-                  // clang-format off
-      Pair(":method", "GET"),
-      Pair(":scheme", "http"),
-      Pair(":path", "/"),
-      Pair(":authority", "www.example.com"),
-      Pair("cache-control", "no-cache")));
-  // clang-format on
-
-  expectEntry(62, 53, "cache-control", "no-cache");
-  expectEntry(63, 57, ":authority", "www.example.com");
-  EXPECT_EQ(110u, decoder_peer_.header_table()->size());
-
-  // 82                                      | == Indexed - Add ==
-  //                                         |   idx = 2
-  //                                         | -> :method: GET
-  // 87                                      | == Indexed - Add ==
-  //                                         |   idx = 7
-  //                                         | -> :scheme: https
-  // 85                                      | == Indexed - Add ==
-  //                                         |   idx = 5
-  //                                         | -> :path: /index.html
-  // bf                                      | == Indexed - Add ==
-  //                                         |   idx = 63
-  //                                         | -> :authority: www.example.com
-  // 40                                      | == Literal indexed ==
-  // 88                                      |   Literal name (len = 10)
-  //                                         |     Huffman encoded:
-  // 25a8 49e9 5ba9 7d7f                     | %.I.[.}.
-  //                                         |     Decoded:
-  //                                         | custom-key
-  // 89                                      |   Literal value (len = 12)
-  //                                         |     Huffman encoded:
-  // 25a8 49e9 5bb8 e8b4 bf                  | %.I.[....
-  //                                         |     Decoded:
-  //                                         | custom-value
-  //                                         | -> custom-key: custom-value
-  string third = a2b_hex("828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf");
-  const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
-
-  EXPECT_THAT(
-      third_header_set,
-      ElementsAre(
-          // clang-format off
-      Pair(":method", "GET"),
-      Pair(":scheme", "https"),
-      Pair(":path", "/index.html"),
-      Pair(":authority", "www.example.com"),
-      Pair("custom-key", "custom-value")));
-  // clang-format on
-
-  expectEntry(62, 54, "custom-key", "custom-value");
-  expectEntry(63, 53, "cache-control", "no-cache");
-  expectEntry(64, 57, ":authority", "www.example.com");
-  EXPECT_EQ(164u, decoder_peer_.header_table()->size());
-}
-
-// RFC 7541, Section C.6: Response Examples with Huffman Coding
-// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6
-TEST_P(HpackDecoder2Test, SectionC6ResponseHuffmanExamples) {
-  decoder_.ApplyHeaderTableSizeSetting(256);
-
-  // 48                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 8)
-  //                                         |     :status
-  // 82                                      |   Literal value (len = 3)
-  //                                         |     Huffman encoded:
-  // 6402                                    | d.
-  //                                         |     Decoded:
-  //                                         | 302
-  //                                         | -> :status: 302
-  // 58                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 24)
-  //                                         |     cache-control
-  // 85                                      |   Literal value (len = 7)
-  //                                         |     Huffman encoded:
-  // aec3 771a 4b                            | ..w.K
-  //                                         |     Decoded:
-  //                                         | private
-  //                                         | -> cache-control: private
-  // 61                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 33)
-  //                                         |     date
-  // 96                                      |   Literal value (len = 29)
-  //                                         |     Huffman encoded:
-  // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
-  // e082 a62d 1bff                          | ...-..
-  //                                         |     Decoded:
-  //                                         | Mon, 21 Oct 2013 20:13:21
-  //                                         | GMT
-  //                                         | -> date: Mon, 21 Oct 2013
-  //                                         |   20:13:21 GMT
-  // 6e                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 46)
-  //                                         |     location
-  // 91                                      |   Literal value (len = 23)
-  //                                         |     Huffman encoded:
-  // 9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 | .)...c.........C
-  // d3                                      | .
-  //                                         |     Decoded:
-  //                                         | https://www.example.com
-  //                                         | -> location: https://www.e
-  //                                         |    xample.com
-
-  string first = a2b_hex(
-      "488264025885aec3771a4b6196d07abe"
-      "941054d444a8200595040b8166e082a6"
-      "2d1bff6e919d29ad171863c78f0b97c8"
-      "e9ae82ae43d3");
-  const SpdyHeaderBlock& first_header_set = DecodeBlockExpectingSuccess(first);
-
-  EXPECT_THAT(first_header_set,
-              ElementsAre(
-                  // clang-format off
-      Pair(":status", "302"),
-      Pair("cache-control", "private"),
-      Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-      Pair("location", "https://www.example.com")));
-  // clang-format on
-
-  expectEntry(62, 63, "location", "https://www.example.com");
-  expectEntry(63, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
-  expectEntry(64, 52, "cache-control", "private");
-  expectEntry(65, 42, ":status", "302");
-  EXPECT_EQ(222u, decoder_peer_.header_table()->size());
-
-  // 48                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 8)
-  //                                         |     :status
-  // 83                                      |   Literal value (len = 3)
-  //                                         |     Huffman encoded:
-  // 640e ff                                 | d..
-  //                                         |     Decoded:
-  //                                         | 307
-  //                                         | - evict: :status: 302
-  //                                         | -> :status: 307
-  // c1                                      | == Indexed - Add ==
-  //                                         |   idx = 65
-  //                                         | -> cache-control: private
-  // c0                                      | == Indexed - Add ==
-  //                                         |   idx = 64
-  //                                         | -> date: Mon, 21 Oct 2013
-  //                                         |   20:13:21 GMT
-  // bf                                      | == Indexed - Add ==
-  //                                         |   idx = 63
-  //                                         | -> location:
-  //                                         |   https://www.example.com
-  string second = a2b_hex("4883640effc1c0bf");
-  const SpdyHeaderBlock& second_header_set =
-      DecodeBlockExpectingSuccess(second);
-
-  EXPECT_THAT(second_header_set,
-              ElementsAre(
-                  // clang-format off
-      Pair(":status", "307"),
-      Pair("cache-control", "private"),
-      Pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
-      Pair("location", "https://www.example.com")));
-  // clang-format on
-
-  expectEntry(62, 42, ":status", "307");
-  expectEntry(63, 63, "location", "https://www.example.com");
-  expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:21 GMT");
-  expectEntry(65, 52, "cache-control", "private");
-  EXPECT_EQ(222u, decoder_peer_.header_table()->size());
-
-  // 88                                      | == Indexed - Add ==
-  //                                         |   idx = 8
-  //                                         | -> :status: 200
-  // c1                                      | == Indexed - Add ==
-  //                                         |   idx = 65
-  //                                         | -> cache-control: private
-  // 61                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 33)
-  //                                         |     date
-  // 96                                      |   Literal value (len = 22)
-  //                                         |     Huffman encoded:
-  // d07a be94 1054 d444 a820 0595 040b 8166 | .z...T.D. .....f
-  // e084 a62d 1bff                          | ...-..
-  //                                         |     Decoded:
-  //                                         | Mon, 21 Oct 2013 20:13:22
-  //                                         | GMT
-  //                                         | - evict: cache-control:
-  //                                         |   private
-  //                                         | -> date: Mon, 21 Oct 2013
-  //                                         |   20:13:22 GMT
-  // c0                                      | == Indexed - Add ==
-  //                                         |   idx = 64
-  //                                         | -> location:
-  //                                         |    https://www.example.com
-  // 5a                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 26)
-  //                                         |     content-encoding
-  // 83                                      |   Literal value (len = 3)
-  //                                         |     Huffman encoded:
-  // 9bd9 ab                                 | ...
-  //                                         |     Decoded:
-  //                                         | gzip
-  //                                         | - evict: date: Mon, 21 Oct
-  //                                         |    2013 20:13:21 GMT
-  //                                         | -> content-encoding: gzip
-  // 77                                      | == Literal indexed ==
-  //                                         |   Indexed name (idx = 55)
-  //                                         |     set-cookie
-  // ad                                      |   Literal value (len = 45)
-  //                                         |     Huffman encoded:
-  // 94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 | .........5...[9`
-  // d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 | ..'..6r..'..)...
-  // 3160 65c0 03ed 4ee5 b106 3d50 07        | 1`e...N...=P.
-  //                                         |     Decoded:
-  //                                         | foo=ASDJKHQKBZXOQWEOPIUAXQ
-  //                                         | WEOIU; max-age=3600; versi
-  //                                         | on=1
-  //                                         | - evict: location:
-  //                                         |   https://www.example.com
-  //                                         | - evict: :status: 307
-  //                                         | -> set-cookie: foo=ASDJKHQ
-  //                                         |   KBZXOQWEOPIUAXQWEOIU;
-  //                                         |   max-age=3600; version=1
-  string third = a2b_hex(
-      "88c16196d07abe941054d444a8200595"
-      "040b8166e084a62d1bffc05a839bd9ab"
-      "77ad94e7821dd7f2e6c7b335dfdfcd5b"
-      "3960d5af27087f3672c1ab270fb5291f"
-      "9587316065c003ed4ee5b1063d5007");
-  const SpdyHeaderBlock& third_header_set = DecodeBlockExpectingSuccess(third);
-
-  EXPECT_THAT(third_header_set,
-              ElementsAre(
-                  // clang-format off
-      Pair(":status", "200"),
-      Pair("cache-control", "private"),
-      Pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
-      Pair("location", "https://www.example.com"),
-      Pair("content-encoding", "gzip"),
-      Pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
-           " max-age=3600; version=1")));
-  // clang-format on
-
-  expectEntry(62, 98, "set-cookie",
-              "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU;"
-              " max-age=3600; version=1");
-  expectEntry(63, 52, "content-encoding", "gzip");
-  expectEntry(64, 65, "date", "Mon, 21 Oct 2013 20:13:22 GMT");
-  EXPECT_EQ(215u, decoder_peer_.header_table()->size());
-}
-
-// Regression test: Found that entries with dynamic indexed names and literal
-// values caused "use after free" MSAN failures if the name was evicted as it
-// was being re-used.
-TEST_P(HpackDecoder2Test, ReuseNameOfEvictedEntry) {
-  // Each entry is measured as 32 bytes plus the sum of the lengths of the name
-  // and the value. Set the size big enough for at most one entry, and a fairly
-  // small one at that (31 ASCII characters).
-  decoder_.ApplyHeaderTableSizeSetting(63);
-
-  HpackBlockBuilder hbb;
-
-  const StringPiece name("some-name");
-  const StringPiece value1("some-value");
-  const StringPiece value2("another-value");
-  const StringPiece value3("yet-another-value");
-
-  // Add an entry that will become the first in the dynamic table, entry 62.
-  hbb.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, false,
-                                name, false, value1);
-
-  // Confirm that entry has been added by re-using it.
-  hbb.AppendIndexedHeader(62);
-
-  // Add another entry referring to the name of the first. This will evict the
-  // first.
-  hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
-                                     false, value2);
-
-  // Confirm that entry has been added by re-using it.
-  hbb.AppendIndexedHeader(62);
-
-  // Add another entry referring to the name of the second. This will evict the
-  // second.
-  hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 62,
-                                     false, value3);
-
-  // Confirm that entry has been added by re-using it.
-  hbb.AppendIndexedHeader(62);
-
-  EXPECT_TRUE(DecodeHeaderBlock(hbb.buffer()));
-
-  SpdyHeaderBlock expected_header_set;
-  expected_header_set.AppendValueOrAddHeader(name, value1);
-  expected_header_set.AppendValueOrAddHeader(name, value1);
-  expected_header_set.AppendValueOrAddHeader(name, value2);
-  expected_header_set.AppendValueOrAddHeader(name, value2);
-  expected_header_set.AppendValueOrAddHeader(name, value3);
-  expected_header_set.AppendValueOrAddHeader(name, value3);
-
-  // SpdyHeaderBlock stores these 6 strings as '\0' separated values.
-  // Make sure that is what happened.
-  string joined_values = expected_header_set[name].as_string();
-  EXPECT_EQ(joined_values.size(),
-            2 * value1.size() + 2 * value2.size() + 2 * value3.size() + 5);
-
-  EXPECT_EQ(expected_header_set, decoded_block());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace net
diff --git a/net/spdy/spdy_flags.cc b/net/spdy/spdy_flags.cc
index e074527..23956d6 100644
--- a/net/spdy/spdy_flags.cc
+++ b/net/spdy/spdy_flags.cc
@@ -12,9 +12,6 @@
 // If true, remove use of SpdyFrameBuilder::OverwriteLength().
 bool FLAGS_chromium_http2_flag_remove_rewritelength = true;
 
-// Use //net/http2/hpack/decoder as HPACK entry decoder.
-bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
-
 // Use //net/http2/hpack/decoder as complete HPACK decoder.
 bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
 
diff --git a/net/spdy/spdy_flags.h b/net/spdy/spdy_flags.h
index a660235b..de706f2e 100644
--- a/net/spdy/spdy_flags.h
+++ b/net/spdy/spdy_flags.h
@@ -12,8 +12,6 @@
 NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_log_compressed_size;
 NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_remove_rewritelength;
 NET_EXPORT_PRIVATE extern bool
-    FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2;
-NET_EXPORT_PRIVATE extern bool
     FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3;
 NET_EXPORT_PRIVATE extern bool FLAGS_use_http2_frame_decoder_adapter;
 NET_EXPORT_PRIVATE extern bool FLAGS_use_nested_spdy_framer_decoder;
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index c8471bf59..1483962 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -25,7 +25,6 @@
 #include "net/quic/core/quic_flags.h"
 #include "net/spdy/hpack/hpack_constants.h"
 #include "net/spdy/hpack/hpack_decoder.h"
-#include "net/spdy/hpack/hpack_decoder2.h"
 #include "net/spdy/hpack/hpack_decoder3.h"
 #include "net/spdy/http2_frame_decoder_adapter.h"
 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
@@ -2403,11 +2402,7 @@
 HpackDecoderInterface* SpdyFramer::GetHpackDecoder() {
   if (hpack_decoder_.get() == nullptr) {
     if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3) {
-      SPDY_BUG_IF(FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2)
-          << "Both alternate decoders are enabled.";
       hpack_decoder_.reset(new HpackDecoder3());
-    } else if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2) {
-      hpack_decoder_.reset(new HpackDecoder2());
     } else {
       hpack_decoder_.reset(new HpackDecoder());
     }
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 5072e92..0552ba8 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -636,7 +636,7 @@
 }
 
 enum DecoderChoice { DECODER_SELF, DECODER_NESTED, DECODER_HTTP2 };
-enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_2, HPACK_DECODER_3 };
+enum HpackChoice { HPACK_DECODER_1, HPACK_DECODER_3 };
 
 class SpdyFramerTest
     : public ::testing::TestWithParam<std::tuple<DecoderChoice, HpackChoice>> {
@@ -659,15 +659,9 @@
     }
     switch (std::get<1>(param)) {
       case HPACK_DECODER_1:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
-        break;
-      case HPACK_DECODER_2:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = true;
         FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = false;
         break;
       case HPACK_DECODER_3:
-        FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
         FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3 = true;
         break;
     }
@@ -695,12 +689,13 @@
   }
 };
 
-INSTANTIATE_TEST_CASE_P(
-    SpdyFramerTests,
-    SpdyFramerTest,
-    ::testing::Combine(
-        ::testing::Values(DECODER_SELF, DECODER_NESTED, DECODER_HTTP2),
-        ::testing::Values(HPACK_DECODER_1, HPACK_DECODER_2, HPACK_DECODER_3)));
+INSTANTIATE_TEST_CASE_P(SpdyFramerTests,
+                        SpdyFramerTest,
+                        ::testing::Combine(::testing::Values(DECODER_SELF,
+                                                             DECODER_NESTED,
+                                                             DECODER_HTTP2),
+                                           ::testing::Values(HPACK_DECODER_1,
+                                                             HPACK_DECODER_3)));
 
 // Test that we can encode and decode a SpdyHeaderBlock in serialized form.
 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 906ddb2..4376bd9 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -3717,29 +3717,6 @@
             }
           ]
         }
-      },
-      {
-        "args": [
-          "webgl_conformance",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-passthrough-cmd-decoder"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "webgl_conformance_gl_passthrough_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:104a",
-              "os": "Ubuntu"
-            }
-          ]
-        }
       }
     ]
   },
@@ -8135,38 +8112,6 @@
       },
       {
         "args": [
-          "info_collection",
-          "--show-stdout",
-          "--browser=release",
-          "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
-          "--expected-vendor-id",
-          "8086",
-          "--expected-device-id",
-          "0a2e"
-        ],
-        "isolate_name": "telemetry_gpu_integration_test",
-        "name": "info_collection_tests",
-        "override_compile_targets": [
-          "telemetry_gpu_integration_test_run"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0a2e",
-              "os": "Mac-10.12"
-            },
-            {
-              "gpu": "1002:6821",
-              "hidpi": "1",
-              "os": "Mac"
-            }
-          ]
-        }
-      },
-      {
-        "args": [
           "maps",
           "--show-stdout",
           "--browser=release",
diff --git a/third_party/OWNERS b/third_party/OWNERS
index c79ad1b..65d14c4a 100644
--- a/third_party/OWNERS
+++ b/third_party/OWNERS
@@ -19,3 +19,5 @@
 klobag@chromium.org
 sky@chromium.org
 thakis@chromium.org
+
+per-file .gitignore=*
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4a689f97..bae83cf 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -158,9 +158,6 @@
 
 # ====== Paint team owned tests to here ======
 
-crbug.com/702148 http/tests/images/gif-animated-partial-load.html [ NeedsRebaseline ]
-crbug.com/702148 virtual/mojo-loading/http/tests/images/gif-animated-partial-load.html [ NeedsRebaseline ]
-
 # ====== LayoutNG-only failures from here ======
 # LayoutNG - is a new layout system for Blink.
 
@@ -2828,7 +2825,7 @@
 crbug.com/698521 external/wpt/preload/preload-with-type.html [ Failure Pass ]
 
 # Sheriff failures 2017-03-10
-crbug.com/402805 [ Mac10.10 Mac10.11 Mac10.12 ] inspector-protocol/input/emulateTouchFromMouseEvent.html [ Timeout ]
+crbug.com/402805 [ Mac10.10 Mac10.11 Mac10.12 Win10 ] inspector-protocol/input/emulateTouchFromMouseEvent.html [ Timeout ]
 crbug.com/700374 [ Win ] virtual/mojo-loading/http/tests/inspector/workers-on-navigation.html [ Failure Pass ]
 crbug.com/700374 [ Win ] http/tests/inspector/workers-on-navigation.html [ Failure Pass ]
 crbug.com/700387 [ Win7 ] external/wpt/fullscreen/api/document-exit-fullscreen-nested-in-iframe-manual.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.png b/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.png
new file mode 100644
index 0000000..23d531b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.txt b/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/images/gif-animated-partial-load-expected.txt
@@ -0,0 +1 @@
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-navigation.html b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-navigation.html
index 4052d5b..167da48 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-navigation.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-navigation.html
@@ -24,7 +24,7 @@
 
 function test()
 {
-    for (var message of SDK.consoleModel.messages()) {
+    for (var message of ConsoleModel.consoleModel.messages()) {
         var args = (message.parameters || []).map((arg) => arg.type);
         InspectorTest.addResult("Message: \"" + message.messageText + "\", arguments: [" + args.join(", ") + "]");
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-remove.html b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-remove.html
index fb74a8a..3129a56 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-remove.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-enabled/console-clear-arguments-on-frame-remove.html
@@ -31,7 +31,7 @@
 
 function test()
 {
-    for (var message of SDK.consoleModel.messages()) {
+    for (var message of ConsoleModel.consoleModel.messages()) {
         var args = (message.parameters || []).map((arg) => arg.type);
         InspectorTest.addResult("Message: \"" + message.messageText + "\", arguments: [" + args.join(", ") + "]");
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js
index 40efec2..11e3d1f9 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js
@@ -93,7 +93,7 @@
 
 InspectorTest.dumpConsoleMessagesIntoArray = function(printOriginatingCommand, dumpClassNames, formatter)
 {
-    Common.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Verbose);
+    Common.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Verbose);
     formatter = formatter || InspectorTest.prepareConsoleMessageText;
     var result = [];
     InspectorTest.disableConsoleViewport();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console/console-links-on-messages-before-inspection.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console/console-links-on-messages-before-inspection.html
index 390ee4d0..336c5fc1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/console/console-links-on-messages-before-inspection.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console/console-links-on-messages-before-inspection.html
@@ -15,8 +15,8 @@
 {
     var mainTarget = SDK.targetManager.mainTarget();
     var debuggerModel = SDK.DebuggerModel.fromTarget(mainTarget);
-    var message = new SDK.ConsoleMessage(mainTarget, SDK.ConsoleMessage.MessageSource.JS, SDK.ConsoleMessage.MessageLevel.Info, "hello?", null, "http://127.0.0.1:8000/inspector/resources/source2.js");
-    SDK.consoleModel.addMessage(message);
+    var message = new ConsoleModel.ConsoleMessage(mainTarget, ConsoleModel.ConsoleMessage.MessageSource.JS, ConsoleModel.ConsoleMessage.MessageLevel.Info, "hello?", null, "http://127.0.0.1:8000/inspector/resources/source2.js");
+    ConsoleModel.consoleModel.addMessage(message);
     debuggerModel.addEventListener(SDK.DebuggerModel.Events.ParsedScriptSource, onScriptAdded);
 
     InspectorTest.dumpConsoleMessages();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
index b7a4b9c..49dae01 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -668,7 +668,7 @@
 
 InspectorTest.addConsoleSniffer = function(override, opt_sticky)
 {
-    InspectorTest.addSniffer(SDK.ConsoleModel.prototype, "addMessage", override, opt_sticky);
+    InspectorTest.addSniffer(ConsoleModel.ConsoleModel.prototype, "addMessage", override, opt_sticky);
 }
 
 InspectorTest.override = function(receiver, methodName, override, opt_sticky)
@@ -987,7 +987,7 @@
         InspectorTest.serviceWorkerManager = target.model(SDK.ServiceWorkerManager);
         InspectorTest.tracingManager = target.model(SDK.TracingManager);
         InspectorTest.mainTarget = target;
-        InspectorTest.consoleModel = SDK.consoleModel;
+        InspectorTest.consoleModel = ConsoleModel.consoleModel;
     },
 
     targetRemoved: function(target) { }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html
index 61d0ab08..c1908f82 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html
@@ -30,13 +30,13 @@
     function waitForConsoleMessage(regex)
     {
         return new Promise(function(resolve) {
-            SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, sniff);
+            ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, sniff);
 
             function sniff(e)
             {
                 if (e.data && regex.test(e.data.messageText)) {
                     resolve(e.data);
-                    SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, sniff);
+                    ConsoleModel.consoleModel.removeEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, sniff);
                 }
             }
         });
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-throw.html b/third_party/WebKit/LayoutTests/inspector/console/console-eval-throw.html
index fa8af2be..5f717e0 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-throw.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-throw.html
@@ -9,12 +9,12 @@
     {
         InspectorTest.dumpConsoleMessagesIgnoreErrorStackFrames();
 
-        InspectorTest.consoleModel.addEventListener(SDK.ConsoleModel.Events.ConsoleCleared, afterCleared);
+        InspectorTest.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.ConsoleCleared, afterCleared);
         Console.ConsoleView.clearConsole();
 
         function afterCleared()
         {
-            InspectorTest.consoleModel.removeEventListener(SDK.ConsoleModel.Events.ConsoleCleared, afterCleared);
+            InspectorTest.consoleModel.removeEventListener(ConsoleModel.ConsoleModel.Events.ConsoleCleared, afterCleared);
             next();
         }
     }
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-filter-level-test.html b/third_party/WebKit/LayoutTests/inspector/console/console-filter-level-test.html
index 1069b1c9b..4226eb51 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-filter-level-test.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-filter-level-test.html
@@ -45,35 +45,35 @@
 
         function verbose(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Verbose);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Verbose);
             dumpVisibleMessages();
             next();
         },
         
         function info(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Info);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Info);
             dumpVisibleMessages();
             next();
         },
 
         function warning(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Warning);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Warning);
             dumpVisibleMessages();
             next();
         },
               
         function error(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Error);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Error);
             dumpVisibleMessages();
             next();
         },
        
         function abcMessagePlain(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Verbose);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Verbose);
             Console.ConsoleView.instance()._filter._textFilterUI.setValue("abc");
             Console.ConsoleView.instance()._filter._textFilterChanged();
             dumpVisibleMessages();
@@ -90,7 +90,7 @@
 
         function abcMessageRegexWarning(next)
         {
-            Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Warning);
+            Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Warning);
             dumpVisibleMessages();
             next();
         }
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-preserve-log.html b/third_party/WebKit/LayoutTests/inspector/console/console-preserve-log.html
index 5e9cb3d..8d6bf217 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-preserve-log.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-preserve-log.html
@@ -5,7 +5,7 @@
 <script>
 function test()
 {
-    InspectorTest.consoleModel.addMessage(new SDK.ConsoleMessage(InspectorTest.mainTarget, SDK.ConsoleMessage.MessageSource.Other, SDK.ConsoleMessage.MessageLevel.Info, "PASS"));
+    InspectorTest.consoleModel.addMessage(new ConsoleModel.ConsoleMessage(InspectorTest.mainTarget, ConsoleModel.ConsoleMessage.MessageSource.Other, ConsoleModel.ConsoleMessage.MessageLevel.Info, "PASS"));
     Common.settingForTest("preserveConsoleLog").set(true);
     InspectorTest.reloadPage(function() {
         InspectorTest.dumpConsoleMessages();
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error-in-worker.html b/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error-in-worker.html
index 341c25c..afed3d41 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error-in-worker.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error-in-worker.html
@@ -18,8 +18,8 @@
 
 function test()
 {
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, InspectorTest.wrapListener(messageAdded));
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageUpdated, InspectorTest.wrapListener(messageUpdated));
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, InspectorTest.wrapListener(messageAdded));
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageUpdated, InspectorTest.wrapListener(messageUpdated));
 
     InspectorTest.addResult("Creating worker with promise");
     InspectorTest.evaluateInPageWithTimeout("createPromise()");
@@ -29,7 +29,7 @@
         InspectorTest.addResult("");
         InspectorTest.addResult("Message added: " + event.data.level + " " + event.data.type);
 
-        if (event.data.level === SDK.ConsoleMessage.MessageLevel.Error) {
+        if (event.data.level === ConsoleModel.ConsoleMessage.MessageLevel.Error) {
             InspectorTest.dumpConsoleCounters();
             InspectorTest.addResult("");
             InspectorTest.addResult("Handling promise");
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error.html b/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error.html
index a212edd..b437f7f 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-revoke-error.html
@@ -21,7 +21,7 @@
 function test()
 {
     var messageAddedListener = InspectorTest.wrapListener(messageAdded);
-    InspectorTest.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, messageAddedListener);
+    InspectorTest.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, messageAddedListener);
 
     InspectorTest.addResult("Creating promise");
     InspectorTest.evaluateInPageWithTimeout("createPromises()");
@@ -34,11 +34,11 @@
             return;
         messageNumber = 0;
 
-        InspectorTest.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, messageAddedListener);
+        InspectorTest.consoleModel.removeEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, messageAddedListener);
         InspectorTest.addResult("");
 
         // Process array as a batch.
-        InspectorTest.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageUpdated, InspectorTest.wrapListener(messageUpdated));
+        InspectorTest.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageUpdated, InspectorTest.wrapListener(messageUpdated));
         InspectorTest.dumpConsoleCounters();
         InspectorTest.addResult("");
         InspectorTest.addResult("Handling promise");
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-tests.html b/third_party/WebKit/LayoutTests/inspector/console/console-tests.html
index d4b1600..41f307f 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-tests.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-tests.html
@@ -42,7 +42,7 @@
 
 function test()
 {
-    Common.settings.settingForTest('messageLevelFilters2').set(SDK.ConsoleMessage.MessageLevel.Verbose);
+    Common.settings.settingForTest('messageLevelFilters2').set(ConsoleModel.ConsoleMessage.MessageLevel.Verbose);
     InspectorTest.dumpConsoleMessagesWithClasses();
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
index 1bc866e5..9d605a8d 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-timestamp.html
@@ -13,10 +13,10 @@
 
     function addMessageWithFixedTimestamp(messageText, timestamp)
     {
-        var message = new SDK.ConsoleMessage(
+        var message = new ConsoleModel.ConsoleMessage(
             InspectorTest.mainTarget,
-            SDK.ConsoleMessage.MessageSource.Other, // source
-            SDK.ConsoleMessage.MessageLevel.Info, // level
+            ConsoleModel.ConsoleMessage.MessageSource.Other, // source
+            ConsoleModel.ConsoleMessage.MessageLevel.Info, // level
             messageText,
             undefined, // type
             undefined, // url
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
index 4945678..cbcbb1a 100644
--- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
+++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html
@@ -64,11 +64,11 @@
         InspectorTest.disableConsoleViewport();
         InspectorTest.evaluateInPage("logMessage()");
         var wrappedConsoleMessageAdded = InspectorTest.safeWrap(consoleMessageAdded);
-        SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, wrappedConsoleMessageAdded);
+        ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, wrappedConsoleMessageAdded);
 
         function consoleMessageAdded()
         {
-            SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, wrappedConsoleMessageAdded);
+            ConsoleModel.consoleModel.removeEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, wrappedConsoleMessageAdded);
             Console.ConsoleView.instance()._viewportThrottler.flush();
             InspectorTest.deprecatedRunAfterPendingDispatches(clickOnMessage)
         }
diff --git a/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt b/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
index f8f32be0..2ab6cfd 100644
--- a/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/initial-modules-load-expected.txt
@@ -6,6 +6,7 @@
     bindings
     common
     components
+    console_model
     dom_extension
     emulation
     extensions
@@ -28,6 +29,7 @@
     color_picker
     common
     components
+    console_model
     dom_extension
     elements
     emulation
@@ -55,6 +57,7 @@
     color_picker
     common
     components
+    console_model
     cookie_table
     data_grid
     diff
@@ -90,6 +93,7 @@
     color_picker
     common
     components
+    console_model
     cookie_table
     data_grid
     diff
@@ -128,6 +132,7 @@
     color_picker
     common
     components
+    console_model
     cookie_table
     data_grid
     diff
diff --git a/third_party/WebKit/LayoutTests/inspector/input-event-warning.html b/third_party/WebKit/LayoutTests/inspector/input-event-warning.html
index 0822b324..c4b5531ef 100644
--- a/third_party/WebKit/LayoutTests/inspector/input-event-warning.html
+++ b/third_party/WebKit/LayoutTests/inspector/input-event-warning.html
@@ -62,7 +62,7 @@
 
 function test()
 {
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, InspectorTest.safeWrap(onConsoleMessage));
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, InspectorTest.safeWrap(onConsoleMessage));
     step1();
 
     function step1()
diff --git a/third_party/WebKit/LayoutTests/inspector/open-with-rendering-option-enabled-expected.txt b/third_party/WebKit/LayoutTests/inspector/open-with-rendering-option-enabled-expected.txt
index 94c946b..30b0d9df 100644
--- a/third_party/WebKit/LayoutTests/inspector/open-with-rendering-option-enabled-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/open-with-rendering-option-enabled-expected.txt
@@ -4,6 +4,7 @@
     bindings
     common
     components
+    console_model
     dom_extension
     emulation
     extensions
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/monitor-console-command.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/monitor-console-command.html
index bc73877..47f2eae2 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/monitor-console-command.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/monitor-console-command.html
@@ -68,7 +68,7 @@
 
         function didReceive(message)
         {
-            if (message.type === SDK.ConsoleMessage.MessageType.Result) {
+            if (message.type === ConsoleModel.ConsoleMessage.MessageType.Result) {
                 InspectorTest.waitUntilMessageReceived(didReceive);
                 return;
             }
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html
index 59e642c..fd0645c 100644
--- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html
+++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/show-function-definition.html
@@ -40,7 +40,7 @@
         function testDumpFunctionDefinition(next)
         {
             InspectorTest.addSniffer(ObjectUI.ObjectPropertiesSection, "formatObjectAsFunction", onConsoleMessagesReceived);
-            SDK.consoleModel.evaluateCommandInConsole(UI.context.flavor(SDK.ExecutionContext), "jumpToMe");
+            ConsoleModel.consoleModel.evaluateCommandInConsole(UI.context.flavor(SDK.ExecutionContext), "jumpToMe");
 
             function onConsoleMessagesReceived()
             {
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png
new file mode 100644
index 0000000..92dcd244
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png
new file mode 100644
index 0000000..92dcd244
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png b/third_party/WebKit/LayoutTests/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png
new file mode 100644
index 0000000..23d531b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/mojo-loading/http/tests/images/gif-animated-partial-load-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
index d8eb286..b7536970 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -50,6 +50,8 @@
   "$bindings_modules_v8_output_dir/RenderingContext.h",
   "$bindings_modules_v8_output_dir/RequestOrUSVString.cpp",
   "$bindings_modules_v8_output_dir/RequestOrUSVString.h",
+  "$bindings_modules_v8_output_dir/RequestOrUSVStringOrRequestOrUSVStringSequence.cpp",
+  "$bindings_modules_v8_output_dir/RequestOrUSVStringOrRequestOrUSVStringSequence.h",
   "$bindings_modules_v8_output_dir/StringOrArrayBufferOrNFCMessage.cpp",
   "$bindings_modules_v8_output_dir/StringOrArrayBufferOrNFCMessage.h",
   "$bindings_modules_v8_output_dir/StringOrCanvasGradientOrCanvasPattern.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
index 7887781..1ea5625 100644
--- a/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSGradientValue.cpp
@@ -124,6 +124,26 @@
   GradientStop() : offset(0), specified(false) {}
 };
 
+struct CSSGradientValue::GradientDesc {
+  STACK_ALLOCATED();
+
+  GradientDesc(const FloatPoint& p0,
+               const FloatPoint& p1,
+               GradientSpreadMethod spreadMethod)
+      : p0(p0), p1(p1), spreadMethod(spreadMethod) {}
+  GradientDesc(const FloatPoint& p0,
+               const FloatPoint& p1,
+               float r0,
+               float r1,
+               GradientSpreadMethod spreadMethod)
+      : p0(p0), p1(p1), r0(r0), r1(r1), spreadMethod(spreadMethod) {}
+
+  Vector<Gradient::ColorStop> stops;
+  FloatPoint p0, p1;
+  float r0 = 0, r1 = 0;
+  GradientSpreadMethod spreadMethod = SpreadMethodPad;
+};
+
 static void replaceColorHintsWithColorStops(
     Vector<GradientStop>& stops,
     const HeapVector<CSSGradientColorStop, 2>& cssGradientStops) {
@@ -223,7 +243,7 @@
       stopColor, object.resolveColor(CSSPropertyColor));
 }
 
-void CSSGradientValue::addDeprecatedStops(Gradient* gradient,
+void CSSGradientValue::addDeprecatedStops(GradientDesc& desc,
                                           const LayoutObject& object) {
   ASSERT(m_gradientType == CSSDeprecatedLinearGradient ||
          m_gradientType == CSSDeprecatedRadialGradient);
@@ -241,19 +261,19 @@
     else
       offset = stop.m_position->getFloatValue();
 
-    gradient->addColorStop(offset, resolveStopColor(*stop.m_color, object));
+    desc.stops.emplace_back(offset, resolveStopColor(*stop.m_color, object));
   }
 }
 
 static bool requiresStopsNormalization(const Vector<GradientStop>& stops,
-                                       const Gradient* gradient) {
+                                       CSSGradientValue::GradientDesc& desc) {
   // We need at least two stops to normalize
   if (stops.size() < 2)
     return false;
 
   // Repeating gradients are implemented using a normalized stop offset range
   // with the point/radius pairs aligned on the interval endpoints.
-  if (gradient->spreadMethod() == SpreadMethodRepeat)
+  if (desc.spreadMethod == SpreadMethodRepeat)
     return true;
 
   // Degenerate stops
@@ -266,7 +286,7 @@
 // Redistribute the stops such that they fully cover [0 , 1] and add them to the
 // gradient.
 static bool normalizeAndAddStops(const Vector<GradientStop>& stops,
-                                 Gradient* gradient) {
+                                 CSSGradientValue::GradientDesc& desc) {
   ASSERT(stops.size() > 1);
 
   const float firstOffset = stops.front().offset;
@@ -281,9 +301,9 @@
     // image with the color of the last color-stop in the rule.
     // For non-repeating gradients, both the first color and the last color can
     // be significant (padding on both sides of the offset).
-    if (gradient->spreadMethod() != SpreadMethodRepeat)
-      gradient->addColorStop(clampedOffset, stops.front().color);
-    gradient->addColorStop(clampedOffset, stops.back().color);
+    if (desc.spreadMethod != SpreadMethodRepeat)
+      desc.stops.emplace_back(clampedOffset, stops.front().color);
+    desc.stops.emplace_back(clampedOffset, stops.back().color);
 
     return false;
   }
@@ -298,7 +318,7 @@
     ASSERT(i == 0 ||
            normalizedOffset >= (stops[i - 1].offset - firstOffset) / span);
 
-    gradient->addColorStop(normalizedOffset, stops[i].color);
+    desc.stops.emplace_back(normalizedOffset, stops[i].color);
   }
 
   return true;
@@ -332,31 +352,31 @@
 }
 
 // Update the linear gradient points to align with the given offset range.
-static void adjustGradientPointsForOffsetRange(Gradient* gradient,
-                                               float firstOffset,
-                                               float lastOffset) {
-  ASSERT(!gradient->isRadial());
+static void adjustGradientPointsForOffsetRange(
+    CSSGradientValue::GradientDesc& desc,
+    float firstOffset,
+    float lastOffset) {
   ASSERT(firstOffset <= lastOffset);
 
-  const FloatPoint p0 = gradient->p0();
-  const FloatPoint p1 = gradient->p1();
+  const FloatPoint p0 = desc.p0;
+  const FloatPoint p1 = desc.p1;
   const FloatSize d(p1 - p0);
 
   // Linear offsets are relative to the [p0 , p1] segment.
-  gradient->setP0(p0 + d * firstOffset);
-  gradient->setP1(p0 + d * lastOffset);
+  desc.p0 = p0 + d * firstOffset;
+  desc.p1 = p0 + d * lastOffset;
 }
 
 // Update the radial gradient radii to align with the given offset range.
-static void adjustGradientRadiiForOffsetRange(Gradient* gradient,
-                                              float firstOffset,
-                                              float lastOffset) {
-  ASSERT(gradient->isRadial());
+static void adjustGradientRadiiForOffsetRange(
+    CSSGradientValue::GradientDesc& desc,
+    float firstOffset,
+    float lastOffset) {
   ASSERT(firstOffset <= lastOffset);
 
   // Radial offsets are relative to the [0 , endRadius] segment.
-  float adjustedR0 = gradient->endRadius() * firstOffset;
-  float adjustedR1 = gradient->endRadius() * lastOffset;
+  float adjustedR0 = desc.r1 * firstOffset;
+  float adjustedR1 = desc.r1 * lastOffset;
   ASSERT(adjustedR0 <= adjustedR1);
 
   // Unlike linear gradients (where we can adjust the points arbitrarily),
@@ -364,7 +384,7 @@
   if (adjustedR0 < 0) {
     // For the non-repeat case, this can never happen: clampNegativeOffsets()
     // ensures we don't have to deal with negative offsets at this point.
-    ASSERT(gradient->spreadMethod() == SpreadMethodRepeat);
+    DCHECK_EQ(desc.spreadMethod, SpreadMethodRepeat);
 
     // When in repeat mode, we deal with it by repositioning both radii in the
     // positive domain - shifting them by a multiple of the radius span (which
@@ -378,16 +398,16 @@
   ASSERT(adjustedR0 >= 0);
   ASSERT(adjustedR1 >= adjustedR0);
 
-  gradient->setStartRadius(adjustedR0);
-  gradient->setEndRadius(adjustedR1);
+  desc.r0 = adjustedR0;
+  desc.r1 = adjustedR1;
 }
 
-void CSSGradientValue::addStops(Gradient* gradient,
+void CSSGradientValue::addStops(CSSGradientValue::GradientDesc& desc,
                                 const CSSToLengthConversionData& conversionData,
                                 const LayoutObject& object) {
   if (m_gradientType == CSSDeprecatedLinearGradient ||
       m_gradientType == CSSDeprecatedRadialGradient) {
-    addDeprecatedStops(gradient, object);
+    addDeprecatedStops(desc, object);
     return;
   }
 
@@ -397,12 +417,12 @@
 
   bool hasHints = false;
 
-  FloatPoint gradientStart = gradient->p0();
+  FloatPoint gradientStart = desc.p0;
   FloatPoint gradientEnd;
   if (isLinearGradientValue())
-    gradientEnd = gradient->p1();
+    gradientEnd = desc.p1;
   else if (isRadialGradientValue())
-    gradientEnd = gradientStart + FloatSize(gradient->endRadius(), 0);
+    gradientEnd = gradientStart + FloatSize(desc.r1, 0);
   float gradientLength =
       FloatSize(gradientStart - gradientEnd).diagonalLength();
 
@@ -501,19 +521,19 @@
 
   // At this point we have a fully resolved set of stops. Time to perform
   // adjustments for repeat gradients and degenerate values if needed.
-  if (requiresStopsNormalization(stops, gradient)) {
+  if (requiresStopsNormalization(stops, desc)) {
     // Negative offsets are only an issue for non-repeating radial gradients:
     // linear gradient points can be repositioned arbitrarily, and for repeating
     // radial gradients we shift the radii into equivalent positive values.
     if (isRadialGradientValue() && !m_repeating)
       clampNegativeOffsets(stops);
 
-    if (normalizeAndAddStops(stops, gradient)) {
+    if (normalizeAndAddStops(stops, desc)) {
       if (isLinearGradientValue()) {
-        adjustGradientPointsForOffsetRange(gradient, stops.front().offset,
+        adjustGradientPointsForOffsetRange(desc, stops.front().offset,
                                            stops.back().offset);
       } else {
-        adjustGradientRadiiForOffsetRange(gradient, stops.front().offset,
+        adjustGradientRadiiForOffsetRange(desc, stops.front().offset,
                                           stops.back().offset);
       }
     } else {
@@ -522,7 +542,7 @@
   } else {
     // No normalization required, just add the current stops.
     for (const auto& stop : stops)
-      gradient->addColorStop(stop.offset, stop.color);
+      desc.stops.emplace_back(stop.offset, stop.color);
   }
 }
 
@@ -878,13 +898,16 @@
     }
   }
 
-  RefPtr<Gradient> gradient = Gradient::create(firstPoint, secondPoint);
+  GradientDesc desc(firstPoint, secondPoint,
+                    m_repeating ? SpreadMethodRepeat : SpreadMethodPad);
+  addStops(desc, conversionData, object);
 
-  gradient->setSpreadMethod(m_repeating ? SpreadMethodRepeat : SpreadMethodPad);
-  gradient->setDrawsInPMColorSpace(true);
+  RefPtr<Gradient> gradient =
+      Gradient::create(desc.p0, desc.p1, desc.spreadMethod,
+                       Gradient::ColorInterpolation::Premultiplied);
 
   // Now add the stops.
-  addStops(gradient.get(), conversionData, object);
+  gradient->addColorStops(desc.stops);
 
   return gradient.release();
 }
@@ -1244,16 +1267,18 @@
   DCHECK(std::isfinite(secondRadius.height()));
 
   bool isDegenerate = !secondRadius.width() || !secondRadius.height();
-  RefPtr<Gradient> gradient =
-      Gradient::create(firstPoint, firstRadius, secondPoint,
-                       isDegenerate ? 0 : secondRadius.width(),
-                       isDegenerate ? 1 : secondRadius.aspectRatio());
+  GradientDesc desc(firstPoint, secondPoint, firstRadius,
+                    isDegenerate ? 0 : secondRadius.width(),
+                    m_repeating ? SpreadMethodRepeat : SpreadMethodPad);
+  addStops(desc, conversionData, object);
 
-  gradient->setSpreadMethod(m_repeating ? SpreadMethodRepeat : SpreadMethodPad);
-  gradient->setDrawsInPMColorSpace(true);
+  RefPtr<Gradient> gradient = Gradient::create(
+      desc.p0, desc.r0, desc.p1, desc.r1,
+      isDegenerate ? 1 : secondRadius.aspectRatio(), desc.spreadMethod,
+      Gradient::ColorInterpolation::Premultiplied);
 
   // Now add the stops.
-  addStops(gradient.get(), conversionData, object);
+  gradient->addColorStops(desc.stops);
 
   return gradient.release();
 }
diff --git a/third_party/WebKit/Source/core/css/CSSGradientValue.h b/third_party/WebKit/Source/core/css/CSSGradientValue.h
index 0fcead9..19967def 100644
--- a/third_party/WebKit/Source/core/css/CSSGradientValue.h
+++ b/third_party/WebKit/Source/core/css/CSSGradientValue.h
@@ -114,6 +114,8 @@
 
   DECLARE_TRACE_AFTER_DISPATCH();
 
+  struct GradientDesc;
+
  protected:
   CSSGradientValue(ClassType classType,
                    CSSGradientRepeat repeat,
@@ -123,10 +125,10 @@
         m_gradientType(gradientType),
         m_repeating(repeat == Repeating) {}
 
-  void addStops(Gradient*,
+  void addStops(GradientDesc&,
                 const CSSToLengthConversionData&,
                 const LayoutObject&);
-  void addDeprecatedStops(Gradient*, const LayoutObject&);
+  void addDeprecatedStops(GradientDesc&, const LayoutObject&);
 
   // Resolve points/radii to front end values.
   FloatPoint computeEndPoint(CSSValue*,
diff --git a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
index b6574da..f8618151 100644
--- a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
@@ -368,10 +368,10 @@
 }
 
 TEST_F(EventHandlerTest, ClearHandleAfterTap) {
-  setHtmlInnerHTML("<textarea cols=50 rows=50>Enter text</textarea>");
+  setHtmlInnerHTML("<textarea cols=50  rows=10>Enter text</textarea>");
 
   // Show handle
-  LongPressEventBuilder longPressEvent(IntPoint(200, 200));
+  LongPressEventBuilder longPressEvent(IntPoint(200, 10));
   document().frame()->eventHandler().handleGestureEvent(longPressEvent);
 
   ASSERT_TRUE(
@@ -379,11 +379,9 @@
   ASSERT_TRUE(selection().isHandleVisible());
 
   // Tap away from text area should clear handle
-  TapEventBuilder singleTapEvent(IntPoint(700, 700), 1);
+  TapEventBuilder singleTapEvent(IntPoint(200, 350), 1);
   document().frame()->eventHandler().handleGestureEvent(singleTapEvent);
 
-  ASSERT_TRUE(
-      selection().computeVisibleSelectionInDOMTreeDeprecated().isNone());
   ASSERT_FALSE(selection().isHandleVisible());
 }
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceLinearGradient.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceLinearGradient.cpp
index d79ca19..3c525aa 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceLinearGradient.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceLinearGradient.cpp
@@ -52,10 +52,10 @@
 
 PassRefPtr<Gradient> LayoutSVGResourceLinearGradient::buildGradient() const {
   const LinearGradientAttributes& attributes = this->attributes();
-  RefPtr<Gradient> gradient =
-      Gradient::create(startPoint(attributes), endPoint(attributes));
-  gradient->setSpreadMethod(
-      platformSpreadMethodFromSVGType(attributes.spreadMethod()));
+  RefPtr<Gradient> gradient = Gradient::create(
+      startPoint(attributes), endPoint(attributes),
+      platformSpreadMethodFromSVGType(attributes.spreadMethod()),
+      Gradient::ColorInterpolation::Unpremultiplied);
   gradient->addColorStops(attributes.stops());
   return gradient.release();
 }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceRadialGradient.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceRadialGradient.cpp
index b6408d7..c673fe5 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceRadialGradient.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceRadialGradient.cpp
@@ -65,11 +65,11 @@
 
 PassRefPtr<Gradient> LayoutSVGResourceRadialGradient::buildGradient() const {
   const RadialGradientAttributes& attributes = this->attributes();
-  RefPtr<Gradient> gradient =
-      Gradient::create(focalPoint(attributes), focalRadius(attributes),
-                       centerPoint(attributes), radius(attributes));
-  gradient->setSpreadMethod(
-      platformSpreadMethodFromSVGType(attributes.spreadMethod()));
+  RefPtr<Gradient> gradient = Gradient::create(
+      focalPoint(attributes), focalRadius(attributes), centerPoint(attributes),
+      radius(attributes), 1,
+      platformSpreadMethodFromSVGType(attributes.spreadMethod()),
+      Gradient::ColorInterpolation::Unpremultiplied);
   gradient->addColorStops(attributes.stops());
   return gradient.release();
 }
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index ea25b99..665b1d7 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -134,6 +134,8 @@
   "front_end/console/ConsoleViewMessage.js",
   "front_end/console/ConsoleViewport.js",
   "front_end/console/module.json",
+  "front_end/console_model/ConsoleModel.js",
+  "front_end/console_model/module.json",
   "front_end/cookie_table/CookiesTable.js",
   "front_end/cookie_table/module.json",
   "front_end/coverage/coverageListView.css",
@@ -436,7 +438,6 @@
   "front_end/screencast/screencastView.css",
   "front_end/screencast/ScreencastView.js",
   "front_end/sdk/Connections.js",
-  "front_end/sdk/ConsoleModel.js",
   "front_end/sdk/ContentProviders.js",
   "front_end/sdk/CookieModel.js",
   "front_end/sdk/CookieParser.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js
index e1c8f01..7d10d989 100644
--- a/third_party/WebKit/Source/devtools/front_end/Tests.js
+++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -514,19 +514,23 @@
   TestSuite.prototype.testConsoleOnNavigateBack = function() {
 
     function filteredMessages() {
-      return SDK.consoleModel.messages().filter(a => a.source !== SDK.ConsoleMessage.MessageSource.Violation);
+      return ConsoleModel.consoleModel.messages().filter(
+          a => a.source !== ConsoleModel.ConsoleMessage.MessageSource.Violation);
     }
 
-    if (filteredMessages().length === 1)
+    if (filteredMessages().length === 1) {
       firstConsoleMessageReceived.call(this, null);
-    else
-      SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
+    } else {
+      ConsoleModel.consoleModel.addEventListener(
+          ConsoleModel.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
+    }
 
 
     function firstConsoleMessageReceived(event) {
-      if (event && event.data.source === SDK.ConsoleMessage.MessageSource.Violation)
+      if (event && event.data.source === ConsoleModel.ConsoleMessage.MessageSource.Violation)
         return;
-      SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
+      ConsoleModel.consoleModel.removeEventListener(
+          ConsoleModel.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
       this.evaluateInConsole_('clickLink();', didClickLink.bind(this));
     }
 
@@ -682,12 +686,13 @@
 
         messages.splice(index, 1);
         if (!messages.length) {
-          SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
+          ConsoleModel.consoleModel.removeEventListener(
+              ConsoleModel.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
           next();
         }
       }
 
-      SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
+      ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
       SDK.multitargetNetworkManager.setNetworkConditions(preset);
     }
 
@@ -832,7 +837,7 @@
   };
 
   TestSuite.prototype.testWindowInitializedOnNavigateBack = function() {
-    var messages = SDK.consoleModel.messages();
+    var messages = ConsoleModel.consoleModel.messages();
     this.assertEquals(1, messages.length);
     var text = messages[0].messageText;
     if (text.indexOf('Uncaught') !== -1)
@@ -867,7 +872,7 @@
   };
 
   TestSuite.prototype.waitForTestResultsInConsole = function() {
-    var messages = SDK.consoleModel.messages();
+    var messages = ConsoleModel.consoleModel.messages();
     for (var i = 0; i < messages.length; ++i) {
       var text = messages[i].messageText;
       if (text === 'PASS')
@@ -884,7 +889,7 @@
         this.fail(text);
     }
 
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
     this.takeControl();
   };
 
@@ -928,12 +933,12 @@
         Array.prototype.slice.call(arguments, 1, -1).map(arg => JSON.stringify(arg)).join(',') + ',';
     this.evaluateInConsole_(
         `${functionName}(${argsString} function() { console.log('${doneMessage}'); });`, function() {});
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage);
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, onConsoleMessage);
 
     function onConsoleMessage(event) {
       var text = event.data.messageText;
       if (text === doneMessage) {
-        SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage);
+        ConsoleModel.consoleModel.removeEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, onConsoleMessage);
         callback();
       }
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
index cb1e587..bc208e5 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -38,15 +38,17 @@
   constructor(workspace) {
     this._workspace = workspace;
 
-    /** @type {!Object.<string, !Array.<!SDK.ConsoleMessage>>} */
+    /** @type {!Object.<string, !Array.<!ConsoleModel.ConsoleMessage>>} */
     this._pendingConsoleMessages = {};
 
     /** @type {!Array.<!Bindings.PresentationConsoleMessage>} */
     this._presentationConsoleMessages = [];
 
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, this._onConsoleMessageAdded, this);
-    SDK.consoleModel.messages().forEach(this._consoleMessageAdded, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.MessageAdded, this._onConsoleMessageAdded, this);
+    ConsoleModel.consoleModel.messages().forEach(this._consoleMessageAdded, this);
     // TODO(dgozman): setImmediate because we race with DebuggerWorkspaceBinding on ParsedScriptSource event delivery.
     SDK.targetManager.addModelListener(
         SDK.DebuggerModel, SDK.DebuggerModel.Events.ParsedScriptSource,
@@ -64,12 +66,12 @@
    * @param {!Common.Event} event
    */
   _onConsoleMessageAdded(event) {
-    var message = /** @type {!SDK.ConsoleMessage} */ (event.data);
+    var message = /** @type {!ConsoleModel.ConsoleMessage} */ (event.data);
     this._consoleMessageAdded(message);
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    */
   _consoleMessageAdded(message) {
     if (!message.isErrorOrWarning())
@@ -83,7 +85,7 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @return {?SDK.DebuggerModel.Location}
    */
   _rawLocation(message) {
@@ -103,18 +105,18 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @param {!SDK.DebuggerModel.Location} rawLocation
    */
   _addConsoleMessageToScript(message, rawLocation) {
-    if (message.source === SDK.ConsoleMessage.MessageSource.Violation)
+    if (message.source === ConsoleModel.ConsoleMessage.MessageSource.Violation)
       return;
     this._presentationConsoleMessages.push(
         new Bindings.PresentationConsoleMessage(message, rawLocation, this._locationPool));
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    */
   _addPendingConsoleMessage(message) {
     if (!message.url)
@@ -170,13 +172,13 @@
  */
 Bindings.PresentationConsoleMessage = class {
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @param {!SDK.DebuggerModel.Location} rawLocation
    * @param {!Bindings.LiveLocationPool} locationPool
    */
   constructor(message, rawLocation, locationPool) {
     this._text = message.messageText;
-    this._level = message.level === SDK.ConsoleMessage.MessageLevel.Error ?
+    this._level = message.level === ConsoleModel.ConsoleMessage.MessageLevel.Error ?
         Workspace.UISourceCode.Message.Level.Error :
         Workspace.UISourceCode.Message.Level.Warning;
     Bindings.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this._updateLocation.bind(this), locationPool);
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/module.json b/third_party/WebKit/Source/devtools/front_end/bindings/module.json
index 9cba604..577bb33d 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/module.json
@@ -3,7 +3,8 @@
         "sdk",
         "platform",
         "services",
-        "workspace"
+        "workspace",
+        "console_model"
     ],
     "scripts": [
         "LiveLocation.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
index 0704bbc..f0c2ff7 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsolePrompt.js
@@ -191,7 +191,7 @@
     this.setText('');
     var currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
     if (currentExecutionContext) {
-      SDK.consoleModel.evaluateCommandInConsole(currentExecutionContext, text, useCommandLineAPI);
+      ConsoleModel.consoleModel.evaluateCommandInConsole(currentExecutionContext, text, useCommandLineAPI);
       if (Console.ConsolePanel.instance().isShowing())
         Host.userMetrics.actionTaken(Host.UserMetrics.Action.CommandEvaluatedInConsolePanel);
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
index 12af176..921bec5 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -182,7 +182,7 @@
   }
 
   static clearConsole() {
-    SDK.consoleModel.requestClearMessages();
+    ConsoleModel.consoleModel.requestClearMessages();
   }
 
   /**
@@ -225,11 +225,15 @@
   }
 
   _fetchMultitargetMessages() {
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, this._onConsoleMessageAdded, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageUpdated, this._onConsoleMessageUpdated, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.CommandEvaluated, this._commandEvaluated, this);
-    SDK.consoleModel.messages().forEach(this._addConsoleMessage, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.MessageAdded, this._onConsoleMessageAdded, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.MessageUpdated, this._onConsoleMessageUpdated, this);
+    ConsoleModel.consoleModel.addEventListener(
+        ConsoleModel.ConsoleModel.Events.CommandEvaluated, this._commandEvaluated, this);
+    ConsoleModel.consoleModel.messages().forEach(this._addConsoleMessage, this);
     this._viewport.invalidate();
   }
 
@@ -301,22 +305,22 @@
    * @param {!Common.Console.Message} message
    */
   _addSinkMessage(message) {
-    var level = SDK.ConsoleMessage.MessageLevel.Verbose;
+    var level = ConsoleModel.ConsoleMessage.MessageLevel.Verbose;
     switch (message.level) {
       case Common.Console.MessageLevel.Info:
-        level = SDK.ConsoleMessage.MessageLevel.Info;
+        level = ConsoleModel.ConsoleMessage.MessageLevel.Info;
         break;
       case Common.Console.MessageLevel.Error:
-        level = SDK.ConsoleMessage.MessageLevel.Error;
+        level = ConsoleModel.ConsoleMessage.MessageLevel.Error;
         break;
       case Common.Console.MessageLevel.Warning:
-        level = SDK.ConsoleMessage.MessageLevel.Warning;
+        level = ConsoleModel.ConsoleMessage.MessageLevel.Warning;
         break;
     }
 
-    var consoleMessage = new SDK.ConsoleMessage(
-        null, SDK.ConsoleMessage.MessageSource.Other, level, message.text, undefined, undefined, undefined, undefined,
-        undefined, undefined, undefined, message.timestamp);
+    var consoleMessage = new ConsoleModel.ConsoleMessage(
+        null, ConsoleModel.ConsoleMessage.MessageSource.Other, level, message.text, undefined, undefined, undefined,
+        undefined, undefined, undefined, undefined, message.timestamp);
     this._addConsoleMessage(consoleMessage);
   }
 
@@ -435,12 +439,12 @@
    * @param {!Common.Event} event
    */
   _onConsoleMessageAdded(event) {
-    var message = /** @type {!SDK.ConsoleMessage} */ (event.data);
+    var message = /** @type {!ConsoleModel.ConsoleMessage} */ (event.data);
     this._addConsoleMessage(message);
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    */
   _addConsoleMessage(message) {
     /**
@@ -449,11 +453,12 @@
      * @return {number}
      */
     function compareTimestamps(viewMessage1, viewMessage2) {
-      return SDK.ConsoleMessage.timestampComparator(viewMessage1.consoleMessage(), viewMessage2.consoleMessage());
+      return ConsoleModel.ConsoleMessage.timestampComparator(
+          viewMessage1.consoleMessage(), viewMessage2.consoleMessage());
     }
 
-    if (message.type === SDK.ConsoleMessage.MessageType.Command ||
-        message.type === SDK.ConsoleMessage.MessageType.Result) {
+    if (message.type === ConsoleModel.ConsoleMessage.MessageType.Command ||
+        message.type === ConsoleModel.ConsoleMessage.MessageType.Result) {
       message.timestamp =
           this._consoleMessages.length ? this._consoleMessages.peekLast().consoleMessage().timestamp : 0;
     }
@@ -484,7 +489,7 @@
    * @param {!Common.Event} event
    */
   _onConsoleMessageUpdated(event) {
-    var message = /** @type {!SDK.ConsoleMessage} */ (event.data);
+    var message = /** @type {!ConsoleModel.ConsoleMessage} */ (event.data);
     var viewMessage = message[this._viewMessageSymbol];
     if (viewMessage) {
       viewMessage.updateMessageElement();
@@ -511,7 +516,7 @@
       return;
 
     var lastMessage = this._visibleViewMessages.peekLast();
-    if (viewMessage.consoleMessage().type === SDK.ConsoleMessage.MessageType.EndGroup) {
+    if (viewMessage.consoleMessage().type === ConsoleModel.ConsoleMessage.MessageType.EndGroup) {
       if (lastMessage && !this._currentGroup.messagesHidden())
         lastMessage.incrementCloseGroupDecorationCount();
       this._currentGroup = this._currentGroup.parentGroup();
@@ -537,18 +542,18 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @return {!Console.ConsoleViewMessage}
    */
   _createViewMessage(message) {
     var nestingLevel = this._currentGroup.nestingLevel();
     switch (message.type) {
-      case SDK.ConsoleMessage.MessageType.Command:
+      case ConsoleModel.ConsoleMessage.MessageType.Command:
         return new Console.ConsoleCommand(message, this._linkifier, nestingLevel);
-      case SDK.ConsoleMessage.MessageType.Result:
+      case ConsoleModel.ConsoleMessage.MessageType.Result:
         return new Console.ConsoleCommandResult(message, this._linkifier, nestingLevel);
-      case SDK.ConsoleMessage.MessageType.StartGroupCollapsed:
-      case SDK.ConsoleMessage.MessageType.StartGroup:
+      case ConsoleModel.ConsoleMessage.MessageType.StartGroupCollapsed:
+      case ConsoleModel.ConsoleMessage.MessageType.StartGroup:
         return new Console.ConsoleGroupViewMessage(message, this._linkifier, nestingLevel);
       default:
         return new Console.ConsoleViewMessage(message, this._linkifier, nestingLevel);
@@ -784,25 +789,26 @@
 
   /**
    * @param {?SDK.RemoteObject} result
-   * @param {!SDK.ConsoleMessage} originatingConsoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} originatingConsoleMessage
    * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
    */
   _printResult(result, originatingConsoleMessage, exceptionDetails) {
     if (!result)
       return;
 
-    var level = !!exceptionDetails ? SDK.ConsoleMessage.MessageLevel.Error : SDK.ConsoleMessage.MessageLevel.Info;
+    var level = !!exceptionDetails ? ConsoleModel.ConsoleMessage.MessageLevel.Error :
+                                     ConsoleModel.ConsoleMessage.MessageLevel.Info;
     var message;
     if (!exceptionDetails) {
-      message = new SDK.ConsoleMessage(
-          result.target(), SDK.ConsoleMessage.MessageSource.JS, level, '', SDK.ConsoleMessage.MessageType.Result,
-          undefined, undefined, undefined, undefined, [result]);
+      message = new ConsoleModel.ConsoleMessage(
+          result.target(), ConsoleModel.ConsoleMessage.MessageSource.JS, level, '',
+          ConsoleModel.ConsoleMessage.MessageType.Result, undefined, undefined, undefined, undefined, [result]);
     } else {
-      message = SDK.ConsoleMessage.fromException(
-          result.target(), exceptionDetails, SDK.ConsoleMessage.MessageType.Result, undefined, undefined);
+      message = ConsoleModel.ConsoleMessage.fromException(
+          result.target(), exceptionDetails, ConsoleModel.ConsoleMessage.MessageType.Result, undefined, undefined);
     }
     message.setOriginatingMessage(originatingConsoleMessage);
-    SDK.consoleModel.addMessage(message);
+    ConsoleModel.consoleModel.addMessage(message);
   }
 
   /**
@@ -810,7 +816,7 @@
    */
   _commandEvaluated(event) {
     var data =
-        /** @type {{result: ?SDK.RemoteObject, text: string, commandMessage: !SDK.ConsoleMessage, exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)}} */
+        /** @type {{result: ?SDK.RemoteObject, text: string, commandMessage: !ConsoleModel.ConsoleMessage, exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)}} */
         (event.data);
     this._prompt.history().pushHistoryItem(data.text);
     this._consoleHistorySetting.set(
@@ -1045,7 +1051,7 @@
 
     this._messageURLFiltersSetting = Common.settings.createSetting('messageURLFilters', {});
     this._messageLevelFiltersSetting =
-        Common.settings.createSetting('messageLevelFilters2', SDK.ConsoleMessage.MessageLevel.Info);
+        Common.settings.createSetting('messageLevelFilters2', ConsoleModel.ConsoleMessage.MessageLevel.Info);
     this._hideNetworkMessagesSetting = Common.moduleSetting('hideNetworkMessages');
 
     this._messageURLFiltersSetting.addChangeListener(this._filterChanged);
@@ -1056,10 +1062,10 @@
     this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, this._textFilterChanged, this);
 
     var levels = [
-      {value: SDK.ConsoleMessage.MessageLevel.Verbose, label: Common.UIString('Verbose')},
-      {value: SDK.ConsoleMessage.MessageLevel.Info, label: Common.UIString('Info'), default: true},
-      {value: SDK.ConsoleMessage.MessageLevel.Warning, label: Common.UIString('Warnings')},
-      {value: SDK.ConsoleMessage.MessageLevel.Error, label: Common.UIString('Errors')}
+      {value: ConsoleModel.ConsoleMessage.MessageLevel.Verbose, label: Common.UIString('Verbose')},
+      {value: ConsoleModel.ConsoleMessage.MessageLevel.Info, label: Common.UIString('Info'), default: true},
+      {value: ConsoleModel.ConsoleMessage.MessageLevel.Warning, label: Common.UIString('Warnings')},
+      {value: ConsoleModel.ConsoleMessage.MessageLevel.Error, label: Common.UIString('Errors')}
     ];
 
     this._levelComboBox =
@@ -1124,22 +1130,22 @@
     }
 
     if (this._hideNetworkMessagesSetting.get() &&
-        viewMessage.consoleMessage().source === SDK.ConsoleMessage.MessageSource.Network)
+        viewMessage.consoleMessage().source === ConsoleModel.ConsoleMessage.MessageSource.Network)
       return false;
 
     if (viewMessage.consoleMessage().isGroupMessage())
       return true;
 
-    if (message.type === SDK.ConsoleMessage.MessageType.Result ||
-        message.type === SDK.ConsoleMessage.MessageType.Command)
+    if (message.type === ConsoleModel.ConsoleMessage.MessageType.Result ||
+        message.type === ConsoleModel.ConsoleMessage.MessageType.Command)
       return true;
 
     if (message.url && this._messageURLFiltersSetting.get()[message.url])
       return false;
 
-    var filterOrdinal = SDK.ConsoleMessage.MessageLevel.ordinal(
-        /** @type {!SDK.ConsoleMessage.MessageLevel} */ (this._messageLevelFiltersSetting.get()));
-    if (message.level && SDK.ConsoleMessage.MessageLevel.ordinal(message.level) < filterOrdinal)
+    var filterOrdinal = ConsoleModel.ConsoleMessage.MessageLevel.ordinal(
+        /** @type {!ConsoleModel.ConsoleMessage.MessageLevel} */ (this._messageLevelFiltersSetting.get()));
+    if (message.level && ConsoleModel.ConsoleMessage.MessageLevel.ordinal(message.level) < filterOrdinal)
       return false;
 
     if (this._filterRegex) {
@@ -1155,7 +1161,7 @@
 
   reset() {
     this._messageURLFiltersSetting.set({});
-    this._messageLevelFiltersSetting.set(SDK.ConsoleMessage.MessageLevel.Info);
+    this._messageLevelFiltersSetting.set(ConsoleModel.ConsoleMessage.MessageLevel.Info);
     this._showTargetMessagesCheckbox.inputElement.checked = false;
     this._hideNetworkMessagesSetting.set(false);
     this._textFilterUI.setValue('');
@@ -1168,7 +1174,7 @@
  */
 Console.ConsoleCommand = class extends Console.ConsoleViewMessage {
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @param {!Components.Linkifier} linkifier
    * @param {number} nestingLevel
    */
@@ -1221,7 +1227,7 @@
  */
 Console.ConsoleCommandResult = class extends Console.ConsoleViewMessage {
   /**
-   * @param {!SDK.ConsoleMessage} message
+   * @param {!ConsoleModel.ConsoleMessage} message
    * @param {!Components.Linkifier} linkifier
    * @param {number} nestingLevel
    */
@@ -1237,7 +1243,7 @@
     var element = super.contentElement();
     if (!element.classList.contains('console-user-command-result')) {
       element.classList.add('console-user-command-result');
-      if (this.consoleMessage().level === SDK.ConsoleMessage.MessageLevel.Info) {
+      if (this.consoleMessage().level === ConsoleModel.ConsoleMessage.MessageLevel.Info) {
         var icon = UI.Icon.create('smallicon-command-result', 'command-result-icon');
         element.insertBefore(icon, element.firstChild);
       }
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index 6d3a809..4f470bf 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -33,7 +33,7 @@
  */
 Console.ConsoleViewMessage = class {
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @param {!Components.Linkifier} linkifier
    * @param {number} nestingLevel
    */
@@ -100,7 +100,7 @@
     // This value reflects the 18px min-height of .console-message, plus the
     // 1px border of .console-message-wrapper. Keep in sync with consoleView.css.
     const defaultConsoleRowHeight = 19;
-    if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
+    if (this._message.type === ConsoleModel.ConsoleMessage.MessageType.Table) {
       var table = this._message.parameters[0];
       if (table && table.preview)
         return defaultConsoleRowHeight * table.preview.properties.length;
@@ -109,14 +109,14 @@
   }
 
   /**
-   * @return {!SDK.ConsoleMessage}
+   * @return {!ConsoleModel.ConsoleMessage}
    */
   consoleMessage() {
     return this._message;
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @return {!Element}
    */
   _buildTableMessage(consoleMessage) {
@@ -188,34 +188,34 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @return {!Element}
    */
   _buildMessage(consoleMessage) {
     var messageElement;
     var messageText = consoleMessage.messageText;
-    if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
+    if (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI) {
       switch (consoleMessage.type) {
-        case SDK.ConsoleMessage.MessageType.Trace:
+        case ConsoleModel.ConsoleMessage.MessageType.Trace:
           messageElement = this._format(consoleMessage.parameters || ['console.trace']);
           break;
-        case SDK.ConsoleMessage.MessageType.Clear:
+        case ConsoleModel.ConsoleMessage.MessageType.Clear:
           messageElement = createElementWithClass('span', 'console-info');
           messageElement.textContent = Common.UIString('Console was cleared');
           break;
-        case SDK.ConsoleMessage.MessageType.Assert:
+        case ConsoleModel.ConsoleMessage.MessageType.Assert:
           var args = [Common.UIString('Assertion failed:')];
           if (consoleMessage.parameters)
             args = args.concat(consoleMessage.parameters);
           messageElement = this._format(args);
           break;
-        case SDK.ConsoleMessage.MessageType.Dir:
+        case ConsoleModel.ConsoleMessage.MessageType.Dir:
           var obj = consoleMessage.parameters ? consoleMessage.parameters[0] : undefined;
           var args = ['%O', obj];
           messageElement = this._format(args);
           break;
-        case SDK.ConsoleMessage.MessageType.Profile:
-        case SDK.ConsoleMessage.MessageType.ProfileEnd:
+        case ConsoleModel.ConsoleMessage.MessageType.Profile:
+        case ConsoleModel.ConsoleMessage.MessageType.ProfileEnd:
           messageElement = this._format([messageText]);
           break;
         default:
@@ -225,10 +225,10 @@
           var args = consoleMessage.parameters || [messageText];
           messageElement = messageElement || this._format(args);
       }
-    } else if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Network) {
+    } else if (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.Network) {
       if (consoleMessage.request) {
         messageElement = createElement('span');
-        if (consoleMessage.level === SDK.ConsoleMessage.MessageLevel.Error) {
+        if (consoleMessage.level === ConsoleModel.ConsoleMessage.MessageLevel.Error) {
           messageElement.createTextChild(consoleMessage.request.requestMethod + ' ');
           messageElement.appendChild(Components.Linkifier.linkifyRevealable(
               consoleMessage.request, consoleMessage.request.url(), consoleMessage.request.url()));
@@ -247,11 +247,11 @@
         messageElement = this._format([messageText]);
       }
     } else {
-      if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Violation)
+      if (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.Violation)
         messageText = Common.UIString('[Violation] %s', messageText);
-      else if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Intervention)
+      else if (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.Intervention)
         messageText = Common.UIString('[Intervention] %s', messageText);
-      if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Deprecation)
+      if (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.Deprecation)
         messageText = Common.UIString('[Deprecation] %s', messageText);
       var args = consoleMessage.parameters || [messageText];
       messageElement = this._format(args);
@@ -271,7 +271,7 @@
     /**
      * @param {string} title
      * @return {!Element}
-     * @this {SDK.ConsoleMessage}
+     * @this {ConsoleModel.ConsoleMessage}
      */
     function linkifyRequest(title) {
       return Components.Linkifier.linkifyRevealable(
@@ -280,12 +280,12 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @return {?Element}
    */
   _buildMessageAnchor(consoleMessage) {
     var anchorElement = null;
-    if (consoleMessage.source !== SDK.ConsoleMessage.MessageSource.Network || consoleMessage.request) {
+    if (consoleMessage.source !== ConsoleModel.ConsoleMessage.MessageSource.Network || consoleMessage.request) {
       if (consoleMessage.scriptId) {
         anchorElement = this._linkifyScriptId(
             consoleMessage.scriptId, consoleMessage.url || '', consoleMessage.line, consoleMessage.column);
@@ -309,7 +309,7 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @param {!SDK.Target} target
    * @param {!Components.Linkifier} linkifier
    * @return {!Element}
@@ -349,7 +349,7 @@
     }
 
     clickableElement.addEventListener('click', toggleStackTrace, false);
-    if (consoleMessage.type === SDK.ConsoleMessage.MessageType.Trace)
+    if (consoleMessage.type === ConsoleModel.ConsoleMessage.MessageType.Trace)
       expandStackTrace(true);
 
     toggleElement._expandStackTraceForTest = expandStackTrace.bind(null, true);
@@ -428,8 +428,8 @@
     // There can be string log and string eval result. We distinguish between them based on message type.
     var shouldFormatMessage =
         SDK.RemoteObject.type((/** @type {!Array.<!SDK.RemoteObject>} **/ (parameters))[0]) === 'string' &&
-        (this._message.type !== SDK.ConsoleMessage.MessageType.Result ||
-         this._message.level === SDK.ConsoleMessage.MessageLevel.Error);
+        (this._message.type !== ConsoleModel.ConsoleMessage.MessageType.Result ||
+         this._message.level === ConsoleModel.ConsoleMessage.MessageLevel.Error);
 
     // Multiple parameters with the first being a format string. Save unused substitutions.
     if (shouldFormatMessage) {
@@ -909,21 +909,21 @@
     if (this._messageLevelIcon)
       contentElement.appendChild(this._messageLevelIcon);
     this._contentElement = contentElement;
-    if (this._message.type === SDK.ConsoleMessage.MessageType.StartGroup ||
-        this._message.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed)
+    if (this._message.type === ConsoleModel.ConsoleMessage.MessageType.StartGroup ||
+        this._message.type === ConsoleModel.ConsoleMessage.MessageType.StartGroupCollapsed)
       contentElement.classList.add('console-group-title');
 
     var formattedMessage;
     var consoleMessage = this._message;
     var target = consoleMessage.target();
-    var shouldIncludeTrace =
-        !!consoleMessage.stackTrace && (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Network ||
-                                        consoleMessage.level === SDK.ConsoleMessage.MessageLevel.Error ||
-                                        consoleMessage.type === SDK.ConsoleMessage.MessageType.Trace ||
-                                        consoleMessage.level === SDK.ConsoleMessage.MessageLevel.Warning);
+    var shouldIncludeTrace = !!consoleMessage.stackTrace &&
+        (consoleMessage.source === ConsoleModel.ConsoleMessage.MessageSource.Network ||
+         consoleMessage.level === ConsoleModel.ConsoleMessage.MessageLevel.Error ||
+         consoleMessage.type === ConsoleModel.ConsoleMessage.MessageType.Trace ||
+         consoleMessage.level === ConsoleModel.ConsoleMessage.MessageLevel.Warning);
     if (target && shouldIncludeTrace)
       formattedMessage = this._buildMessageWithStackTrace(consoleMessage, target, this._linkifier);
-    else if (this._message.type === SDK.ConsoleMessage.MessageType.Table)
+    else if (this._message.type === ConsoleModel.ConsoleMessage.MessageType.Table)
       formattedMessage = this._buildTableMessage(this._message);
     else
       formattedMessage = this._buildMessage(consoleMessage);
@@ -959,30 +959,30 @@
     this._element.message = this;
 
     switch (this._message.level) {
-      case SDK.ConsoleMessage.MessageLevel.Verbose:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Verbose:
         this._element.classList.add('console-verbose-level');
         this._updateMessageLevelIcon('');
         break;
-      case SDK.ConsoleMessage.MessageLevel.Info:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Info:
         this._element.classList.add('console-info-level');
         break;
-      case SDK.ConsoleMessage.MessageLevel.Warning:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Warning:
         this._element.classList.add('console-warning-level');
         this._updateMessageLevelIcon('smallicon-warning');
         break;
-      case SDK.ConsoleMessage.MessageLevel.Error:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Error:
         this._element.classList.add('console-error-level');
         this._updateMessageLevelIcon('smallicon-error');
         break;
     }
 
     // Render verbose and info deprecations, interventions and violations with warning background.
-    if (this._message.level === SDK.ConsoleMessage.MessageLevel.Verbose ||
-        this._message.level === SDK.ConsoleMessage.MessageLevel.Info) {
+    if (this._message.level === ConsoleModel.ConsoleMessage.MessageLevel.Verbose ||
+        this._message.level === ConsoleModel.ConsoleMessage.MessageLevel.Info) {
       switch (this._message.source) {
-        case SDK.ConsoleMessage.MessageSource.Violation:
-        case SDK.ConsoleMessage.MessageSource.Deprecation:
-        case SDK.ConsoleMessage.MessageSource.Intervention:
+        case ConsoleModel.ConsoleMessage.MessageSource.Violation:
+        case ConsoleModel.ConsoleMessage.MessageSource.Deprecation:
+        case ConsoleModel.ConsoleMessage.MessageSource.Intervention:
           this._element.classList.add('console-warning-level');
           break;
       }
@@ -1037,13 +1037,13 @@
     if (!this._repeatCountElement) {
       this._repeatCountElement = createElementWithClass('label', 'console-message-repeat-count', 'dt-small-bubble');
       switch (this._message.level) {
-        case SDK.ConsoleMessage.MessageLevel.Warning:
+        case ConsoleModel.ConsoleMessage.MessageLevel.Warning:
           this._repeatCountElement.type = 'warning';
           break;
-        case SDK.ConsoleMessage.MessageLevel.Error:
+        case ConsoleModel.ConsoleMessage.MessageLevel.Error:
           this._repeatCountElement.type = 'error';
           break;
-        case SDK.ConsoleMessage.MessageLevel.Verbose:
+        case ConsoleModel.ConsoleMessage.MessageLevel.Verbose:
           this._repeatCountElement.type = 'verbose';
           break;
         default:
@@ -1212,14 +1212,14 @@
  */
 Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
   /**
-   * @param {!SDK.ConsoleMessage} consoleMessage
+   * @param {!ConsoleModel.ConsoleMessage} consoleMessage
    * @param {!Components.Linkifier} linkifier
    * @param {number} nestingLevel
    */
   constructor(consoleMessage, linkifier, nestingLevel) {
     console.assert(consoleMessage.isGroupStartMessage());
     super(consoleMessage, linkifier, nestingLevel);
-    this._collapsed = consoleMessage.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
+    this._collapsed = consoleMessage.type === ConsoleModel.ConsoleMessage.MessageType.StartGroupCollapsed;
     /** @type {?UI.Icon} */
     this._expandGroupIcon = null;
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/console/module.json b/third_party/WebKit/Source/devtools/front_end/console/module.json
index 0cf6c076..c94885e 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/console/module.json
@@ -125,7 +125,8 @@
     "dependencies": [
         "components",
         "data_grid",
-        "object_ui"
+        "object_ui",
+        "console_model"
     ],
     "scripts": [
         "ConsoleContextSelector.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
similarity index 76%
rename from third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
rename to third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index f9e5681..fe95a26 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -31,13 +31,13 @@
 /**
  * @implements {SDK.TargetManager.Observer}
  */
-SDK.ConsoleModel = class extends Common.Object {
+ConsoleModel.ConsoleModel = class extends Common.Object {
   constructor() {
     super();
 
-    /** @type {!Array.<!SDK.ConsoleMessage>} */
+    /** @type {!Array.<!ConsoleModel.ConsoleMessage>} */
     this._messages = [];
-    /** @type {!Map<!SDK.Target, !Map<number, !SDK.ConsoleMessage>>} */
+    /** @type {!Map<!SDK.Target, !Map<number, !ConsoleModel.ConsoleMessage>>} */
     this._messageByExceptionId = new Map();
     this._warnings = 0;
     this._errors = 0;
@@ -89,7 +89,7 @@
           SDK.NetworkManager.Events.WarningGenerated, this._networkWarningGenerated.bind(this, networkManager)));
     }
 
-    target[SDK.ConsoleModel._events] = eventListeners;
+    target[ConsoleModel.ConsoleModel._events] = eventListeners;
   }
 
   /**
@@ -98,7 +98,7 @@
    */
   targetRemoved(target) {
     this._messageByExceptionId.delete(target);
-    Common.EventTarget.removeEventListeners(target[SDK.ConsoleModel._events]);
+    Common.EventTarget.removeEventListeners(target[ConsoleModel.ConsoleModel._events]);
   }
 
   /**
@@ -110,15 +110,16 @@
     var target = executionContext.target();
     var requestedText = text;
 
-    var commandMessage = new SDK.ConsoleMessage(
-        target, SDK.ConsoleMessage.MessageSource.JS, null, text, SDK.ConsoleMessage.MessageType.Command);
+    var commandMessage = new ConsoleModel.ConsoleMessage(
+        target, ConsoleModel.ConsoleMessage.MessageSource.JS, null, text,
+        ConsoleModel.ConsoleMessage.MessageType.Command);
     commandMessage.setExecutionContextId(executionContext.id);
     this.addMessage(commandMessage);
 
     /**
      * @param {?SDK.RemoteObject} result
      * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
-     * @this {SDK.ConsoleModel}
+     * @this {ConsoleModel.ConsoleModel}
      */
     function printResult(result, exceptionDetails) {
       if (!result)
@@ -126,7 +127,7 @@
 
       Common.console.showPromise().then(() => {
         this.dispatchEventToListeners(
-            SDK.ConsoleModel.Events.CommandEvaluated,
+            ConsoleModel.ConsoleModel.Events.CommandEvaluated,
             {result: result, text: requestedText, commandMessage: commandMessage, exceptionDetails: exceptionDetails});
       });
     }
@@ -162,13 +163,14 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} msg
+   * @param {!ConsoleModel.ConsoleMessage} msg
    */
   addMessage(msg) {
-    if (msg.source === SDK.ConsoleMessage.MessageSource.Worker && SDK.targetManager.targetById(msg.workerId))
+    if (msg.source === ConsoleModel.ConsoleMessage.MessageSource.Worker && SDK.targetManager.targetById(msg.workerId))
       return;
 
-    if (msg.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI && msg.type === SDK.ConsoleMessage.MessageType.Clear)
+    if (msg.source === ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI &&
+        msg.type === ConsoleModel.ConsoleMessage.MessageType.Clear)
       this._clear();
 
     this._messages.push(msg);
@@ -184,14 +186,14 @@
       targetMap.set(msg._exceptionId, msg);
     }
     this._incrementErrorWarningCount(msg);
-    this.dispatchEventToListeners(SDK.ConsoleModel.Events.MessageAdded, msg);
+    this.dispatchEventToListeners(ConsoleModel.ConsoleModel.Events.MessageAdded, msg);
   }
 
   /**
    * @param {!SDK.LogModel.EntryAddedEvent} event
    */
   _logEntryAdded(event) {
-    var consoleMessage = new SDK.ConsoleMessage(
+    var consoleMessage = new ConsoleModel.ConsoleMessage(
         event.logModel.target(), event.entry.source, event.entry.level, event.entry.text, undefined, event.entry.url,
         event.entry.lineNumber, undefined, event.entry.networkRequestId, undefined, event.entry.stackTrace,
         event.entry.timestamp, undefined, undefined, event.entry.workerId);
@@ -204,7 +206,7 @@
    */
   _exceptionThrown(runtimeModel, event) {
     var exceptionWithTimestamp = /** @type {!SDK.RuntimeModel.ExceptionWithTimestamp} */ (event.data);
-    var consoleMessage = SDK.ConsoleMessage.fromException(
+    var consoleMessage = ConsoleModel.ConsoleMessage.fromException(
         runtimeModel.target(), exceptionWithTimestamp.details, undefined, exceptionWithTimestamp.timestamp, undefined);
     consoleMessage.setExceptionId(exceptionWithTimestamp.details.exceptionId);
     this.addMessage(consoleMessage);
@@ -221,8 +223,8 @@
     if (!exceptionMessage)
       return;
     this._errors--;
-    exceptionMessage.level = SDK.ConsoleMessage.MessageLevel.Info;
-    this.dispatchEventToListeners(SDK.ConsoleModel.Events.MessageUpdated, exceptionMessage);
+    exceptionMessage.level = ConsoleModel.ConsoleMessage.MessageLevel.Info;
+    this.dispatchEventToListeners(ConsoleModel.ConsoleModel.Events.MessageUpdated, exceptionMessage);
   }
 
   /**
@@ -231,23 +233,27 @@
    */
   _consoleAPICalled(runtimeModel, event) {
     var call = /** @type {!SDK.RuntimeModel.ConsoleAPICall} */ (event.data);
-    var level = SDK.ConsoleMessage.MessageLevel.Info;
-    if (call.type === SDK.ConsoleMessage.MessageType.Debug)
-      level = SDK.ConsoleMessage.MessageLevel.Verbose;
-    else if (call.type === SDK.ConsoleMessage.MessageType.Error || call.type === SDK.ConsoleMessage.MessageType.Assert)
-      level = SDK.ConsoleMessage.MessageLevel.Error;
-    else if (call.type === SDK.ConsoleMessage.MessageType.Warning)
-      level = SDK.ConsoleMessage.MessageLevel.Warning;
-    else if (call.type === SDK.ConsoleMessage.MessageType.Info || call.type === SDK.ConsoleMessage.MessageType.Log)
-      level = SDK.ConsoleMessage.MessageLevel.Info;
+    var level = ConsoleModel.ConsoleMessage.MessageLevel.Info;
+    if (call.type === ConsoleModel.ConsoleMessage.MessageType.Debug)
+      level = ConsoleModel.ConsoleMessage.MessageLevel.Verbose;
+    else if (
+        call.type === ConsoleModel.ConsoleMessage.MessageType.Error ||
+        call.type === ConsoleModel.ConsoleMessage.MessageType.Assert)
+      level = ConsoleModel.ConsoleMessage.MessageLevel.Error;
+    else if (call.type === ConsoleModel.ConsoleMessage.MessageType.Warning)
+      level = ConsoleModel.ConsoleMessage.MessageLevel.Warning;
+    else if (
+        call.type === ConsoleModel.ConsoleMessage.MessageType.Info ||
+        call.type === ConsoleModel.ConsoleMessage.MessageType.Log)
+      level = ConsoleModel.ConsoleMessage.MessageLevel.Info;
     var message = '';
     if (call.args.length && typeof call.args[0].value === 'string')
       message = call.args[0].value;
     else if (call.args.length && call.args[0].description)
       message = call.args[0].description;
     var callFrame = call.stackTrace && call.stackTrace.callFrames.length ? call.stackTrace.callFrames[0] : null;
-    var consoleMessage = new SDK.ConsoleMessage(
-        runtimeModel.target(), SDK.ConsoleMessage.MessageSource.ConsoleAPI, level,
+    var consoleMessage = new ConsoleModel.ConsoleMessage(
+        runtimeModel.target(), ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI, level,
         /** @type {string} */ (message), call.type, callFrame ? callFrame.url : undefined,
         callFrame ? callFrame.lineNumber : undefined, callFrame ? callFrame.columnNumber : undefined, undefined,
         call.args, call.stackTrace, call.timestamp, call.executionContextId, undefined);
@@ -277,7 +283,7 @@
   _consoleProfileStarted(cpuProfilerModel, event) {
     var data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
     this._addConsoleProfileMessage(
-        cpuProfilerModel, SDK.ConsoleMessage.MessageType.Profile, data.scriptLocation,
+        cpuProfilerModel, ConsoleModel.ConsoleMessage.MessageType.Profile, data.scriptLocation,
         Common.UIString('Profile \'%s\' started.', data.title));
   }
 
@@ -288,7 +294,7 @@
   _consoleProfileFinished(cpuProfilerModel, event) {
     var data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
     this._addConsoleProfileMessage(
-        cpuProfilerModel, SDK.ConsoleMessage.MessageType.ProfileEnd, data.scriptLocation,
+        cpuProfilerModel, ConsoleModel.ConsoleMessage.MessageType.ProfileEnd, data.scriptLocation,
         Common.UIString('Profile \'%s\' finished.', data.title));
   }
 
@@ -306,9 +312,10 @@
       lineNumber: scriptLocation.lineNumber,
       columnNumber: scriptLocation.columnNumber || 0
     }];
-    this.addMessage(new SDK.ConsoleMessage(
-        cpuProfilerModel.target(), SDK.ConsoleMessage.MessageSource.ConsoleAPI, SDK.ConsoleMessage.MessageLevel.Info,
-        messageText, type, undefined, undefined, undefined, undefined, stackTrace));
+    this.addMessage(new ConsoleModel.ConsoleMessage(
+        cpuProfilerModel.target(), ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI,
+        ConsoleModel.ConsoleMessage.MessageLevel.Info, messageText, type, undefined, undefined, undefined, undefined,
+        stackTrace));
   }
 
   /**
@@ -317,29 +324,30 @@
    */
   _networkWarningGenerated(networkManager, event) {
     var warning = /** @type {!SDK.NetworkManager.Warning} */ (event.data);
-    this.addMessage(new SDK.ConsoleMessage(
-        networkManager.target(), SDK.ConsoleMessage.MessageSource.Network, SDK.ConsoleMessage.MessageLevel.Warning,
-        warning.message, undefined, undefined, undefined, undefined, warning.requestId));
+    this.addMessage(new ConsoleModel.ConsoleMessage(
+        networkManager.target(), ConsoleModel.ConsoleMessage.MessageSource.Network,
+        ConsoleModel.ConsoleMessage.MessageLevel.Warning, warning.message, undefined, undefined, undefined, undefined,
+        warning.requestId));
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} msg
+   * @param {!ConsoleModel.ConsoleMessage} msg
    */
   _incrementErrorWarningCount(msg) {
-    if (msg.source === SDK.ConsoleMessage.MessageSource.Violation)
+    if (msg.source === ConsoleModel.ConsoleMessage.MessageSource.Violation)
       return;
     switch (msg.level) {
-      case SDK.ConsoleMessage.MessageLevel.Warning:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Warning:
         this._warnings++;
         break;
-      case SDK.ConsoleMessage.MessageLevel.Error:
+      case ConsoleModel.ConsoleMessage.MessageLevel.Error:
         this._errors++;
         break;
     }
   }
 
   /**
-   * @return {!Array.<!SDK.ConsoleMessage>}
+   * @return {!Array.<!ConsoleModel.ConsoleMessage>}
    */
   messages() {
     return this._messages;
@@ -358,7 +366,7 @@
     this._messageByExceptionId.clear();
     this._errors = 0;
     this._warnings = 0;
-    this.dispatchEventToListeners(SDK.ConsoleModel.Events.ConsoleCleared);
+    this.dispatchEventToListeners(ConsoleModel.ConsoleModel.Events.ConsoleCleared);
   }
 
   /**
@@ -377,7 +385,7 @@
 };
 
 /** @enum {symbol} */
-SDK.ConsoleModel.Events = {
+ConsoleModel.ConsoleModel.Events = {
   ConsoleCleared: Symbol('ConsoleCleared'),
   MessageAdded: Symbol('MessageAdded'),
   MessageUpdated: Symbol('MessageUpdated'),
@@ -388,7 +396,7 @@
 /**
  * @unrestricted
  */
-SDK.ConsoleMessage = class {
+ConsoleModel.ConsoleMessage = class {
   /**
    * @param {?SDK.Target} target
    * @param {string} source
@@ -407,26 +415,13 @@
    * @param {?string=} workerId
    */
   constructor(
-      target,
-      source,
-      level,
-      messageText,
-      type,
-      url,
-      line,
-      column,
-      requestId,
-      parameters,
-      stackTrace,
-      timestamp,
-      executionContextId,
-      scriptId,
-      workerId) {
+      target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp,
+      executionContextId, scriptId, workerId) {
     this._target = target;
     this.source = source;
-    this.level = /** @type {?SDK.ConsoleMessage.MessageLevel} */ (level);
+    this.level = /** @type {?ConsoleModel.ConsoleMessage.MessageLevel} */ (level);
     this.messageText = messageText;
-    this.type = type || SDK.ConsoleMessage.MessageType.Log;
+    this.type = type || ConsoleModel.ConsoleMessage.MessageType.Log;
     /** @type {string|undefined} */
     this.url = url || undefined;
     /** @type {number} */
@@ -457,8 +452,8 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} a
-   * @param {!SDK.ConsoleMessage} b
+   * @param {!ConsoleModel.ConsoleMessage} a
+   * @param {!ConsoleModel.ConsoleMessage} b
    * @return {number}
    */
   static timestampComparator(a, b) {
@@ -471,11 +466,11 @@
    * @param {string=} messageType
    * @param {number=} timestamp
    * @param {string=} forceUrl
-   * @return {!SDK.ConsoleMessage}
+   * @return {!ConsoleModel.ConsoleMessage}
    */
   static fromException(target, exceptionDetails, messageType, timestamp, forceUrl) {
-    return new SDK.ConsoleMessage(
-        target, SDK.ConsoleMessage.MessageSource.JS, SDK.ConsoleMessage.MessageLevel.Error,
+    return new ConsoleModel.ConsoleMessage(
+        target, ConsoleModel.ConsoleMessage.MessageSource.JS, ConsoleModel.ConsoleMessage.MessageLevel.Error,
         SDK.RuntimeModel.simpleTextFromException(exceptionDetails), messageType, forceUrl || exceptionDetails.url,
         exceptionDetails.lineNumber, exceptionDetails.columnNumber, undefined,
         exceptionDetails.exception ?
@@ -492,7 +487,7 @@
   }
 
   /**
-   * @param {!SDK.ConsoleMessage} originatingMessage
+   * @param {!ConsoleModel.ConsoleMessage} originatingMessage
    */
   setOriginatingMessage(originatingMessage) {
     this._originatingConsoleMessage = originatingMessage;
@@ -514,7 +509,7 @@
   }
 
   /**
-   * @return {?SDK.ConsoleMessage}
+   * @return {?ConsoleModel.ConsoleMessage}
    */
   originatingMessage() {
     return this._originatingConsoleMessage;
@@ -524,17 +519,17 @@
    * @return {boolean}
    */
   isGroupMessage() {
-    return this.type === SDK.ConsoleMessage.MessageType.StartGroup ||
-        this.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed ||
-        this.type === SDK.ConsoleMessage.MessageType.EndGroup;
+    return this.type === ConsoleModel.ConsoleMessage.MessageType.StartGroup ||
+        this.type === ConsoleModel.ConsoleMessage.MessageType.StartGroupCollapsed ||
+        this.type === ConsoleModel.ConsoleMessage.MessageType.EndGroup;
   }
 
   /**
    * @return {boolean}
    */
   isGroupStartMessage() {
-    return this.type === SDK.ConsoleMessage.MessageType.StartGroup ||
-        this.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
+    return this.type === ConsoleModel.ConsoleMessage.MessageType.StartGroup ||
+        this.type === ConsoleModel.ConsoleMessage.MessageType.StartGroupCollapsed;
   }
 
   /**
@@ -542,11 +537,12 @@
    */
   isErrorOrWarning() {
     return (
-        this.level === SDK.ConsoleMessage.MessageLevel.Warning || this.level === SDK.ConsoleMessage.MessageLevel.Error);
+        this.level === ConsoleModel.ConsoleMessage.MessageLevel.Warning ||
+        this.level === ConsoleModel.ConsoleMessage.MessageLevel.Error);
   }
 
   /**
-   * @param {?SDK.ConsoleMessage} msg
+   * @param {?ConsoleModel.ConsoleMessage} msg
    * @return {boolean}
    */
   isEqual(msg) {
@@ -605,7 +601,7 @@
 /**
  * @enum {string}
  */
-SDK.ConsoleMessage.MessageSource = {
+ConsoleModel.ConsoleMessage.MessageSource = {
   XML: 'xml',
   JS: 'javascript',
   Network: 'network',
@@ -625,7 +621,7 @@
 /**
  * @enum {string}
  */
-SDK.ConsoleMessage.MessageType = {
+ConsoleModel.ConsoleMessage.MessageType = {
   Log: 'log',
   Debug: 'debug',
   Info: 'info',
@@ -649,7 +645,7 @@
 /**
  * @enum {string}
  */
-SDK.ConsoleMessage.MessageLevel = {
+ConsoleModel.ConsoleMessage.MessageLevel = {
   Verbose: 'verbose',
   Info: 'info',
   Warning: 'warning',
@@ -657,22 +653,22 @@
 };
 
 /**
- * @param {!SDK.ConsoleMessage.MessageLevel} level
+ * @param {!ConsoleModel.ConsoleMessage.MessageLevel} level
  * @return {number}
  */
-SDK.ConsoleMessage.MessageLevel.ordinal = function(level) {
-  if (level === SDK.ConsoleMessage.MessageLevel.Verbose)
+ConsoleModel.ConsoleMessage.MessageLevel.ordinal = function(level) {
+  if (level === ConsoleModel.ConsoleMessage.MessageLevel.Verbose)
     return 0;
-  if (level === SDK.ConsoleMessage.MessageLevel.Info)
+  if (level === ConsoleModel.ConsoleMessage.MessageLevel.Info)
     return 1;
-  if (level === SDK.ConsoleMessage.MessageLevel.Warning)
+  if (level === ConsoleModel.ConsoleMessage.MessageLevel.Warning)
     return 2;
   return 3;
 };
 
-SDK.ConsoleModel._events = Symbol('SDK.ConsoleModel.events');
+ConsoleModel.ConsoleModel._events = Symbol('ConsoleModel.ConsoleModel.events');
 
 /**
- * @type {!SDK.ConsoleModel}
+ * @type {!ConsoleModel.ConsoleModel}
  */
-SDK.consoleModel;
+ConsoleModel.consoleModel;
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/module.json b/third_party/WebKit/Source/devtools/front_end/console_model/module.json
new file mode 100644
index 0000000..441f9fa3
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/module.json
@@ -0,0 +1,8 @@
+{
+    "dependencies": [
+        "sdk"
+    ],
+    "scripts": [
+        "ConsoleModel.js"
+    ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/inspector.json b/third_party/WebKit/Source/devtools/front_end/inspector.json
index efcabc79..a331425 100644
--- a/third_party/WebKit/Source/devtools/front_end/inspector.json
+++ b/third_party/WebKit/Source/devtools/front_end/inspector.json
@@ -56,7 +56,8 @@
         { "name": "event_listeners" },
         { "name": "object_ui", "type": "autostart"},
         { "name": "help", "type": "autostart"},
-        { "name": "workspace_diff" }
+        { "name": "workspace_diff" },
+        { "name": "console_model", "type": "autostart"}
     ],
 
     "has_html": true
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index bfa3748..677d0e1 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -165,7 +165,7 @@
     UI.ContextMenu.installHandler(document);
     UI.Tooltip.installHandler(document);
     Components.dockController = new Components.DockController(canDock);
-    SDK.consoleModel = new SDK.ConsoleModel();
+    ConsoleModel.consoleModel = new ConsoleModel.ConsoleModel();
     SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
     SDK.targetManager.addEventListener(
         SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));
@@ -602,9 +602,9 @@
     this._warnings = this._createItem(shadowRoot, 'smallicon-warning');
     this._titles = [];
 
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.ConsoleCleared, this._update, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, this._update, this);
-    SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageUpdated, this._update, this);
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.ConsoleCleared, this._update, this);
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageAdded, this._update, this);
+    ConsoleModel.consoleModel.addEventListener(ConsoleModel.ConsoleModel.Events.MessageUpdated, this._update, this);
     this._update();
   }
 
@@ -637,8 +637,8 @@
   }
 
   _update() {
-    var errors = SDK.consoleModel.errors();
-    var warnings = SDK.consoleModel.warnings();
+    var errors = ConsoleModel.consoleModel.errors();
+    var warnings = ConsoleModel.consoleModel.warnings();
 
     this._titles = [];
     this._toolbarItem.setVisible(!!(errors || warnings));
diff --git a/third_party/WebKit/Source/devtools/front_end/main/module.json b/third_party/WebKit/Source/devtools/front_end/main/module.json
index c1480768..52a3d5a 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/main/module.json
@@ -436,7 +436,8 @@
         "platform",
         "sdk",
         "persistence",
-        "help"
+        "help",
+        "console_model"
     ],
     "scripts": [
         "RenderingOptions.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
index 8c1721dd..4b612215 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -120,7 +120,6 @@
         "Target.js",
         "TargetManager.js",
         "Connections.js",
-        "ConsoleModel.js",
         "ContentProviders.js",
         "CookieModel.js",
         "CookieParser.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js b/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
index c25cf7c..e8929d1 100644
--- a/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/snippets/ScriptSnippetModel.js
@@ -275,10 +275,10 @@
    * @param {?string=} sourceURL
    */
   _printRunScriptResult(target, result, scriptId, sourceURL) {
-    var consoleMessage = new SDK.ConsoleMessage(
-        target, SDK.ConsoleMessage.MessageSource.JS, SDK.ConsoleMessage.MessageLevel.Info, '', undefined, sourceURL,
-        undefined, undefined, undefined, [result], undefined, undefined, undefined, scriptId);
-    SDK.consoleModel.addMessage(consoleMessage);
+    var consoleMessage = new ConsoleModel.ConsoleMessage(
+        target, ConsoleModel.ConsoleMessage.MessageSource.JS, ConsoleModel.ConsoleMessage.MessageLevel.Info, '',
+        undefined, sourceURL, undefined, undefined, undefined, [result], undefined, undefined, undefined, scriptId);
+    ConsoleModel.consoleModel.addMessage(consoleMessage);
   }
 
   /**
@@ -287,8 +287,8 @@
    * @param {?string=} sourceURL
    */
   _printRunOrCompileScriptResultFailure(target, exceptionDetails, sourceURL) {
-    SDK.consoleModel.addMessage(
-        SDK.ConsoleMessage.fromException(target, exceptionDetails, undefined, undefined, sourceURL || undefined));
+    ConsoleModel.consoleModel.addMessage(ConsoleModel.ConsoleMessage.fromException(
+        target, exceptionDetails, undefined, undefined, sourceURL || undefined));
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
index 695c0a1..4fd9a0c 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -956,7 +956,7 @@
       if (wasThrown || !result || result.type !== 'string') {
         failedToSave(result);
       } else {
-        SDK.consoleModel.evaluateCommandInConsole(
+        ConsoleModel.consoleModel.evaluateCommandInConsole(
             /** @type {!SDK.ExecutionContext} */ (currentExecutionContext), result.value,
             /* useCommandLineAPI */ false);
       }
@@ -1268,7 +1268,7 @@
           var text = frame.textEditor.text(frame.textEditor.selection());
           var executionContext = UI.context.flavor(SDK.ExecutionContext);
           if (executionContext)
-            SDK.consoleModel.evaluateCommandInConsole(executionContext, text, /* useCommandLineAPI */ true);
+            ConsoleModel.consoleModel.evaluateCommandInConsole(executionContext, text, /* useCommandLineAPI */ true);
         }
         return true;
     }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
index 06d7a9c6..922a5aa9 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
@@ -61,6 +61,8 @@
     this._rowHeight = 17;
     this._userInteracted = false;
     this._userEnteredText = '';
+    this._defaultSelectionIsDimmed = false;
+
     /** @type {?string} */
     this._onlyCompletion = null;
 
@@ -81,6 +83,7 @@
    * @param {boolean} value
    */
   setDefaultSelectionIsDimmed(value) {
+    this._defaultSelectionIsDimmed = value;
     this._element.classList.toggle('default-selection-is-dimmed', value);
   }
 
@@ -259,8 +262,11 @@
   selectedItemChanged(from, to, fromElement, toElement) {
     if (fromElement)
       fromElement.classList.remove('selected', 'force-white-icons');
-    if (toElement)
-      toElement.classList.add('selected', 'force-white-icons');
+    if (toElement) {
+      toElement.classList.add('selected');
+      if (fromElement || this._userInteracted || !this._defaultSelectionIsDimmed)
+        toElement.classList.add('force-white-icons');
+    }
     if (!to)
       return;
     this._applySuggestion(true);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css b/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css
index 0a0ec31..70ab416 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css
@@ -94,7 +94,7 @@
 }
 
 .default-selection-is-dimmed .suggest-box-content-item.selected {
-    background-color: whitesmoke;
+    background-color: #E0E0E0;
 }
 
 .default-selection-is-dimmed .suggest-box-content-item.selected > span {
diff --git a/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js b/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js
index 307f117..c07c5f7 100644
--- a/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js
+++ b/third_party/WebKit/Source/devtools/scripts/extract_module/extract_module.js
@@ -24,17 +24,13 @@
 const MODULES_TO_REMOVE = [];
 
 const JS_FILES_MAPPING = [
-  {file: 'components/CustomPreviewComponent.js', new: 'object_ui'},
-  {file: 'components/ObjectPopoverHelper.js', new: 'object_ui'},
-  {file: 'components/ObjectPropertiesSection.js', new: 'object_ui'},
-  {file: 'components/JavaScriptAutocomplete.js', new: 'object_ui'},
-  {file: 'components/RemoteObjectPreviewFormatter.js', new: 'object_ui'},
+  {file: 'sdk/ConsoleModel.js', new: 'console_model'},
 ];
 
 const MODULE_MAPPING = {
-  object_ui: {
-    dependencies: ['ui', 'sdk', 'components'],
-    dependents: ['console', 'sources', 'extensions', 'event_listeners', 'resources', 'profiler', 'network'],
+  console_model: {
+    dependencies: ['sdk'],
+    dependents: ['bindings', 'console', 'main'],
     applications: ['inspector.json'],
     autostart: true,  // set to autostart because of extensions
   },
diff --git a/third_party/WebKit/Source/modules/background_fetch/BUILD.gn b/third_party/WebKit/Source/modules/background_fetch/BUILD.gn
index c2036e6..4ba3957 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BUILD.gn
+++ b/third_party/WebKit/Source/modules/background_fetch/BUILD.gn
@@ -6,6 +6,8 @@
 
 blink_modules_sources("background_fetch") {
   sources = [
+    "BackgroundFetchBridge.cpp",
+    "BackgroundFetchBridge.h",
     "BackgroundFetchClickEvent.cpp",
     "BackgroundFetchClickEvent.h",
     "BackgroundFetchEvent.cpp",
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp
new file mode 100644
index 0000000..ef89640
--- /dev/null
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.cpp
@@ -0,0 +1,123 @@
+// 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 "modules/background_fetch/BackgroundFetchBridge.h"
+
+#include <utility>
+#include "modules/background_fetch/BackgroundFetchOptions.h"
+#include "modules/background_fetch/BackgroundFetchRegistration.h"
+#include "modules/background_fetch/IconDefinition.h"
+#include "public/platform/InterfaceProvider.h"
+#include "public/platform/Platform.h"
+#include "public/platform/modules/serviceworker/WebServiceWorkerRegistration.h"
+
+namespace blink {
+
+namespace {
+
+// Creates a new BackgroundFetchRegistration instance given a Service Worker
+// Registration and a Mojo BackgroundFetchRegistrationPtr instance.
+BackgroundFetchRegistration* CreateBackgroundFetchRegistration(
+    ServiceWorkerRegistration* serviceWorkerRegistration,
+    mojom::blink::BackgroundFetchRegistrationPtr registrationPtr) {
+  HeapVector<IconDefinition> icons;
+
+  for (const auto& iconPtr : registrationPtr->icons) {
+    IconDefinition icon;
+    icon.setSrc(iconPtr->src);
+    icon.setSizes(iconPtr->sizes);
+    icon.setType(iconPtr->type);
+
+    icons.push_back(icon);
+  }
+
+  return new BackgroundFetchRegistration(
+      serviceWorkerRegistration, registrationPtr->tag, std::move(icons),
+      registrationPtr->total_download_size, registrationPtr->title);
+}
+
+}  // namespace
+
+// static
+BackgroundFetchBridge* BackgroundFetchBridge::from(
+    ServiceWorkerRegistration* serviceWorkerRegistration) {
+  DCHECK(serviceWorkerRegistration);
+
+  BackgroundFetchBridge* bridge = static_cast<BackgroundFetchBridge*>(
+      Supplement<ServiceWorkerRegistration>::from(serviceWorkerRegistration,
+                                                  supplementName()));
+
+  if (!bridge) {
+    bridge = new BackgroundFetchBridge(*serviceWorkerRegistration);
+    Supplement<ServiceWorkerRegistration>::provideTo(*serviceWorkerRegistration,
+                                                     supplementName(), bridge);
+  }
+
+  return bridge;
+}
+
+// static
+const char* BackgroundFetchBridge::supplementName() {
+  return "BackgroundFetchBridge";
+}
+
+BackgroundFetchBridge::BackgroundFetchBridge(
+    ServiceWorkerRegistration& registration)
+    : Supplement<ServiceWorkerRegistration>(registration) {}
+
+BackgroundFetchBridge::~BackgroundFetchBridge() = default;
+
+void BackgroundFetchBridge::abort(const String& tag) {
+  getService()->Abort(supplementable()->webRegistration()->registrationId(),
+                      tag);
+}
+
+void BackgroundFetchBridge::updateUI(
+    const String& tag,
+    const String& title,
+    std::unique_ptr<UpdateUICallback> callback) {
+  getService()->UpdateUI(supplementable()->webRegistration()->registrationId(),
+                         tag, title,
+                         convertToBaseCallback(std::move(callback)));
+}
+
+void BackgroundFetchBridge::getRegistration(
+    const String& tag,
+    std::unique_ptr<GetRegistrationCallback> callback) {
+  getService()->GetRegistration(
+      supplementable()->webRegistration()->registrationId(), tag,
+      convertToBaseCallback(
+          WTF::bind(&BackgroundFetchBridge::didGetRegistration,
+                    wrapPersistent(this), WTF::passed(std::move(callback)))));
+}
+
+void BackgroundFetchBridge::didGetRegistration(
+    std::unique_ptr<GetRegistrationCallback> callback,
+    mojom::blink::BackgroundFetchError error,
+    mojom::blink::BackgroundFetchRegistrationPtr registrationPtr) {
+  BackgroundFetchRegistration* registration = nullptr;
+
+  if (registrationPtr) {
+    DCHECK_EQ(error, mojom::blink::BackgroundFetchError::NONE);
+    registration = CreateBackgroundFetchRegistration(
+        supplementable(), std::move(registrationPtr));
+  }
+
+  (*callback)(error, registration);
+}
+
+void BackgroundFetchBridge::getTags(std::unique_ptr<GetTagsCallback> callback) {
+  getService()->GetTags(supplementable()->webRegistration()->registrationId(),
+                        convertToBaseCallback(std::move(callback)));
+}
+
+mojom::blink::BackgroundFetchServicePtr& BackgroundFetchBridge::getService() {
+  if (!m_backgroundFetchService) {
+    Platform::current()->interfaceProvider()->getInterface(
+        mojo::MakeRequest(&m_backgroundFetchService));
+  }
+  return m_backgroundFetchService;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h
new file mode 100644
index 0000000..837237d
--- /dev/null
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchBridge.h
@@ -0,0 +1,81 @@
+// 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 BackgroundFetchBridge_h
+#define BackgroundFetchBridge_h
+
+#include <memory>
+#include "modules/serviceworkers/ServiceWorkerRegistration.h"
+#include "platform/Supplementable.h"
+#include "platform/heap/Handle.h"
+#include "public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
+#include "wtf/Functional.h"
+#include "wtf/Vector.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+class BackgroundFetchRegistration;
+
+// The bridge is responsible for establishing and maintaining the Mojo
+// connection to the BackgroundFetchService. It's keyed on an active Service
+// Worker Registration.
+class BackgroundFetchBridge final
+    : public GarbageCollectedFinalized<BackgroundFetchBridge>,
+      public Supplement<ServiceWorkerRegistration> {
+  USING_GARBAGE_COLLECTED_MIXIN(BackgroundFetchBridge);
+  WTF_MAKE_NONCOPYABLE(BackgroundFetchBridge);
+
+ public:
+  using UpdateUICallback = Function<void(mojom::blink::BackgroundFetchError)>;
+  using GetRegistrationCallback =
+      Function<void(mojom::blink::BackgroundFetchError,
+                    BackgroundFetchRegistration*)>;
+  using GetTagsCallback =
+      Function<void(mojom::blink::BackgroundFetchError, const Vector<String>&)>;
+
+  static BackgroundFetchBridge* from(ServiceWorkerRegistration*);
+  static const char* supplementName();
+
+  virtual ~BackgroundFetchBridge();
+
+  // TODO(peter): Implement support for the `fetch()` function in the bridge.
+
+  // Updates the user interface for the Background Fetch identified by |tag|
+  // with the updated |title|. Will invoke the |callback| when the interface
+  // has been requested to update.
+  void updateUI(const String& tag,
+                const String& title,
+                std::unique_ptr<UpdateUICallback>);
+
+  // Aborts the active Background Fetch for |tag|. Does not respond.
+  void abort(const String& tag);
+
+  // Gets the Background Fetch registration for the given |tag|. Will invoke the
+  // |callback| with the Background Fetch registration, which may be a nullptr
+  // if the |tag| does not exist, when the Mojo call has completed.
+  void getRegistration(const String& tag,
+                       std::unique_ptr<GetRegistrationCallback>);
+
+  // Gets the sequence of tags for active Background Fetch registrations. Will
+  // invoke the |callback| with the tags when the Mojo call has completed.
+  void getTags(std::unique_ptr<GetTagsCallback>);
+
+ private:
+  explicit BackgroundFetchBridge(ServiceWorkerRegistration&);
+
+  // Returns an initialized BackgroundFetchServicePtr. A connection will be
+  // established after the first call to this method.
+  mojom::blink::BackgroundFetchServicePtr& getService();
+
+  void didGetRegistration(std::unique_ptr<GetRegistrationCallback>,
+                          mojom::blink::BackgroundFetchError,
+                          mojom::blink::BackgroundFetchRegistrationPtr);
+
+  mojom::blink::BackgroundFetchServicePtr m_backgroundFetchService;
+};
+
+}  // namespace blink
+
+#endif  // BackgroundFetchBridge_h
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
index a1339f5..14dd263 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.cpp
@@ -7,6 +7,7 @@
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
 #include "bindings/core/v8/V8ThrowException.h"
+#include "modules/background_fetch/BackgroundFetchBridge.h"
 #include "modules/background_fetch/BackgroundFetchOptions.h"
 #include "modules/background_fetch/BackgroundFetchRegistration.h"
 #include "modules/serviceworkers/ServiceWorkerRegistration.h"
@@ -17,12 +18,13 @@
     ServiceWorkerRegistration* registration)
     : m_registration(registration) {
   DCHECK(registration);
+  m_bridge = BackgroundFetchBridge::from(m_registration);
 }
 
 ScriptPromise BackgroundFetchManager::fetch(
     ScriptState* scriptState,
-    String tag,
-    HeapVector<RequestOrUSVString> requests,
+    const String& tag,
+    const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
     const BackgroundFetchOptions& options) {
   if (!m_registration->active()) {
     return ScriptPromise::reject(
@@ -48,7 +50,7 @@
 }
 
 ScriptPromise BackgroundFetchManager::get(ScriptState* scriptState,
-                                          String tag) {
+                                          const String& tag) {
   if (!m_registration->active()) {
     return ScriptPromise::reject(
         scriptState,
@@ -60,13 +62,29 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
 
-  // TODO(peter): Get the background fetch registration for `tag` from the
-  // browser process. There may not be one.
-  resolver->resolve(v8::Null(scriptState->isolate()));
+  m_bridge->getRegistration(
+      tag, WTF::bind(&BackgroundFetchManager::didGetRegistration,
+                     wrapPersistent(this), wrapPersistent(resolver)));
 
   return promise;
 }
 
+void BackgroundFetchManager::didGetRegistration(
+    ScriptPromiseResolver* resolver,
+    mojom::blink::BackgroundFetchError error,
+    BackgroundFetchRegistration* registration) {
+  switch (error) {
+    case mojom::blink::BackgroundFetchError::NONE:
+      resolver->resolve(registration);
+      return;
+    case mojom::blink::BackgroundFetchError::DUPLICATED_TAG:
+      // Not applicable for this callback.
+      break;
+  }
+
+  NOTREACHED();
+}
+
 ScriptPromise BackgroundFetchManager::getTags(ScriptState* scriptState) {
   if (!m_registration->active()) {
     return ScriptPromise::reject(
@@ -79,14 +97,31 @@
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
 
-  // TODO(peter): Get a list of tags from the browser process.
-  resolver->resolve(Vector<String>());
+  m_bridge->getTags(WTF::bind(&BackgroundFetchManager::didGetTags,
+                              wrapPersistent(this), wrapPersistent(resolver)));
 
   return promise;
 }
 
+void BackgroundFetchManager::didGetTags(
+    ScriptPromiseResolver* resolver,
+    mojom::blink::BackgroundFetchError error,
+    const Vector<String>& tags) {
+  switch (error) {
+    case mojom::blink::BackgroundFetchError::NONE:
+      resolver->resolve(tags);
+      return;
+    case mojom::blink::BackgroundFetchError::DUPLICATED_TAG:
+      // Not applicable for this callback.
+      break;
+  }
+
+  NOTREACHED();
+}
+
 DEFINE_TRACE(BackgroundFetchManager) {
   visitor->trace(m_registration);
+  visitor->trace(m_bridge);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h
index e52725e..03cd38f8 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.h
@@ -9,11 +9,15 @@
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "platform/heap/GarbageCollected.h"
 #include "platform/heap/Handle.h"
+#include "public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
 
 namespace blink {
 
+class BackgroundFetchBridge;
 class BackgroundFetchOptions;
-class RequestOrUSVString;
+class BackgroundFetchRegistration;
+class RequestOrUSVStringOrRequestOrUSVStringSequence;
+class ScriptPromiseResolver;
 class ScriptState;
 class ServiceWorkerRegistration;
 
@@ -31,11 +35,12 @@
   }
 
   // Web Exposed methods defined in the IDL file.
-  ScriptPromise fetch(ScriptState*,
-                      String tag,
-                      HeapVector<RequestOrUSVString> requests,
-                      const BackgroundFetchOptions&);
-  ScriptPromise get(ScriptState*, String tag);
+  ScriptPromise fetch(
+      ScriptState*,
+      const String& tag,
+      const RequestOrUSVStringOrRequestOrUSVStringSequence& requests,
+      const BackgroundFetchOptions&);
+  ScriptPromise get(ScriptState*, const String& tag);
   ScriptPromise getTags(ScriptState*);
 
   DECLARE_TRACE();
@@ -43,7 +48,15 @@
  private:
   explicit BackgroundFetchManager(ServiceWorkerRegistration*);
 
+  void didGetRegistration(ScriptPromiseResolver*,
+                          mojom::blink::BackgroundFetchError,
+                          BackgroundFetchRegistration*);
+  void didGetTags(ScriptPromiseResolver*,
+                  mojom::blink::BackgroundFetchError,
+                  const Vector<String>& tags);
+
   Member<ServiceWorkerRegistration> m_registration;
+  Member<BackgroundFetchBridge> m_bridge;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl
index 085096f3..a30ad00 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchManager.idl
@@ -8,10 +8,7 @@
     Exposed=(Window,Worker),
     RuntimeEnabled=BackgroundFetch
 ] interface BackgroundFetchManager {
-    // TODO(peter): The `requests` argument of `fetch()` should accept either an
-    // individual RequestInfo, or a sequence of them.
-    [CallWith=ScriptState] Promise<BackgroundFetchRegistration> fetch(DOMString tag, sequence<RequestInfo> requests, optional BackgroundFetchOptions options);
-
+    [CallWith=ScriptState] Promise<BackgroundFetchRegistration> fetch(DOMString tag, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options);
     [CallWith=ScriptState] Promise<BackgroundFetchRegistration?> get(DOMString tag);
     [CallWith=ScriptState] Promise<FrozenArray<DOMString>> getTags();
 };
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp
index 0a7aefe..b5ed2d0 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchRegistration.cpp
@@ -4,6 +4,7 @@
 
 #include "modules/background_fetch/BackgroundFetchRegistration.h"
 
+#include "modules/background_fetch/BackgroundFetchBridge.h"
 #include "modules/background_fetch/IconDefinition.h"
 #include "modules/serviceworkers/ServiceWorkerRegistration.h"
 
@@ -40,8 +41,7 @@
 }
 
 void BackgroundFetchRegistration::abort() {
-  // TODO(peter): Implement the ability to abort the active background fetch
-  // for the |m_registration| identified by the |m_tag|.
+  BackgroundFetchBridge::from(m_registration)->abort(m_tag);
 }
 
 DEFINE_TRACE(BackgroundFetchRegistration) {
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
index d5cc50d..3551dbe 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.cpp
@@ -4,9 +4,11 @@
 
 #include "modules/background_fetch/BackgroundFetchedEvent.h"
 
+#include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "bindings/core/v8/ScriptState.h"
 #include "core/dom/DOMException.h"
 #include "modules/EventModulesNames.h"
+#include "modules/background_fetch/BackgroundFetchBridge.h"
 #include "modules/background_fetch/BackgroundFetchSettledRequest.h"
 #include "modules/background_fetch/BackgroundFetchedEventInit.h"
 
@@ -14,9 +16,11 @@
 
 BackgroundFetchedEvent::BackgroundFetchedEvent(
     const AtomicString& type,
-    const BackgroundFetchedEventInit& init)
+    const BackgroundFetchedEventInit& init,
+    ServiceWorkerRegistration* registration)
     : BackgroundFetchEvent(type, init),
-      m_completedFetches(init.completedFetches()) {}
+      m_completedFetches(init.completedFetches()),
+      m_registration(registration) {}
 
 BackgroundFetchedEvent::~BackgroundFetchedEvent() = default;
 
@@ -26,10 +30,37 @@
 }
 
 ScriptPromise BackgroundFetchedEvent::updateUI(ScriptState* scriptState,
-                                               String title) {
-  return ScriptPromise::rejectWithDOMException(
-      scriptState,
-      DOMException::create(NotSupportedError, "Not implemented yet."));
+                                               const String& title) {
+  if (!m_registration) {
+    // Return a Promise that will never settle when a developer calls this
+    // method on a BackgroundFetchedEvent instance they created themselves.
+    return ScriptPromise();
+  }
+
+  ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+  ScriptPromise promise = resolver->promise();
+
+  BackgroundFetchBridge::from(m_registration)
+      ->updateUI(tag(), title,
+                 WTF::bind(&BackgroundFetchedEvent::didUpdateUI,
+                           wrapPersistent(this), wrapPersistent(resolver)));
+
+  return promise;
+}
+
+void BackgroundFetchedEvent::didUpdateUI(
+    ScriptPromiseResolver* resolver,
+    mojom::blink::BackgroundFetchError error) {
+  switch (error) {
+    case mojom::blink::BackgroundFetchError::NONE:
+      resolver->resolve();
+      return;
+    case mojom::blink::BackgroundFetchError::DUPLICATED_TAG:
+      // Not applicable for this callback.
+      break;
+  }
+
+  NOTREACHED();
 }
 
 const AtomicString& BackgroundFetchedEvent::interfaceName() const {
@@ -38,6 +69,7 @@
 
 DEFINE_TRACE(BackgroundFetchedEvent) {
   visitor->trace(m_completedFetches);
+  visitor->trace(m_registration);
   BackgroundFetchEvent::trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.h b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.h
index aaee6f61..1e63594 100644
--- a/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.h
+++ b/third_party/WebKit/Source/modules/background_fetch/BackgroundFetchedEvent.h
@@ -8,12 +8,14 @@
 #include "bindings/core/v8/ScriptPromise.h"
 #include "modules/background_fetch/BackgroundFetchEvent.h"
 #include "platform/heap/Handle.h"
+#include "public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
 #include "wtf/text/AtomicString.h"
 
 namespace blink {
 
 class BackgroundFetchSettledRequest;
 class BackgroundFetchedEventInit;
+class ServiceWorkerRegistration;
 
 class BackgroundFetchedEvent final : public BackgroundFetchEvent {
   DEFINE_WRAPPERTYPEINFO();
@@ -22,7 +24,15 @@
   static BackgroundFetchedEvent* create(
       const AtomicString& type,
       const BackgroundFetchedEventInit& initializer) {
-    return new BackgroundFetchedEvent(type, initializer);
+    return new BackgroundFetchedEvent(type, initializer,
+                                      nullptr /* registration */);
+  }
+
+  static BackgroundFetchedEvent* create(
+      const AtomicString& type,
+      const BackgroundFetchedEventInit& initializer,
+      ServiceWorkerRegistration* registration) {
+    return new BackgroundFetchedEvent(type, initializer, registration);
   }
 
   ~BackgroundFetchedEvent() override;
@@ -31,7 +41,7 @@
   HeapVector<Member<BackgroundFetchSettledRequest>> completedFetches() const;
 
   // Web Exposed method defined in the IDL file.
-  ScriptPromise updateUI(ScriptState*, String title);
+  ScriptPromise updateUI(ScriptState*, const String& title);
 
   // ExtendableEvent interface.
   const AtomicString& interfaceName() const override;
@@ -40,9 +50,13 @@
 
  private:
   BackgroundFetchedEvent(const AtomicString& type,
-                         const BackgroundFetchedEventInit&);
+                         const BackgroundFetchedEventInit&,
+                         ServiceWorkerRegistration*);
+
+  void didUpdateUI(ScriptPromiseResolver*, mojom::blink::BackgroundFetchError);
 
   HeapVector<Member<BackgroundFetchSettledRequest>> m_completedFetches;
+  Member<ServiceWorkerRegistration> m_registration;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webusb/USB.cpp b/third_party/WebKit/Source/modules/webusb/USB.cpp
index 381cc394..2a667a2 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -53,12 +53,7 @@
 }  // namespace
 
 USB::USB(LocalFrame& frame)
-    : ContextLifecycleObserver(frame.document()), m_clientBinding(this) {
-  frame.interfaceProvider()->getInterface(mojo::MakeRequest(&m_deviceManager));
-  m_deviceManager.set_connection_error_handler(convertToBaseCallback(WTF::bind(
-      &USB::onDeviceManagerConnectionError, wrapWeakPersistent(this))));
-  m_deviceManager->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
-}
+    : ContextLifecycleObserver(frame.document()), m_clientBinding(this) {}
 
 USB::~USB() {
   // |m_deviceManager| and |m_chooserService| may still be valid but there
@@ -77,6 +72,7 @@
 ScriptPromise USB::getDevices(ScriptState* scriptState) {
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
+  ensureDeviceManagerConnection();
   if (!m_deviceManager) {
     resolver->reject(DOMException::create(NotSupportedError));
   } else {
@@ -91,20 +87,15 @@
 
 ScriptPromise USB::requestDevice(ScriptState* scriptState,
                                  const USBDeviceRequestOptions& options) {
-  ExecutionContext* executionContext = scriptState->getExecutionContext();
-
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
   ScriptPromise promise = resolver->promise();
 
   if (!m_chooserService) {
-    LocalFrame* frame = executionContext->isDocument()
-                            ? toDocument(executionContext)->frame()
-                            : nullptr;
-    if (!frame) {
+    if (!frame()) {
       resolver->reject(DOMException::create(NotSupportedError));
       return promise;
     }
-    frame->interfaceProvider()->getInterface(
+    frame()->interfaceProvider()->getInterface(
         mojo::MakeRequest(&m_chooserService));
     m_chooserService.set_connection_error_handler(
         convertToBaseCallback(WTF::bind(&USB::onChooserServiceConnectionError,
@@ -180,16 +171,18 @@
     return;
   m_chooserServiceRequests.erase(requestEntry);
 
+  ensureDeviceManagerConnection();
   if (!m_deviceManager) {
     resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
     return;
   }
 
-  if (deviceInfo)
+  if (deviceInfo) {
     resolver->resolve(getOrCreateDevice(std::move(deviceInfo)));
-  else
+  } else {
     resolver->reject(
         DOMException::create(NotFoundError, "No device selected."));
+  }
 }
 
 void USB::OnDeviceAdded(usb::DeviceInfoPtr deviceInfo) {
@@ -203,15 +196,17 @@
 void USB::OnDeviceRemoved(usb::DeviceInfoPtr deviceInfo) {
   String guid = deviceInfo->guid;
   USBDevice* device = m_deviceCache.at(guid);
-  if (!device)
+  if (!device) {
     device = USBDevice::create(std::move(deviceInfo), nullptr,
                                getExecutionContext());
+  }
   dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, device));
   m_deviceCache.erase(guid);
 }
 
 void USB::onDeviceManagerConnectionError() {
   m_deviceManager.reset();
+  m_clientBinding.Close();
   for (ScriptPromiseResolver* resolver : m_deviceManagerRequests)
     resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
   m_deviceManagerRequests.clear();
@@ -224,6 +219,28 @@
   m_chooserServiceRequests.clear();
 }
 
+void USB::addedEventListener(const AtomicString& eventType,
+                             RegisteredEventListener& listener) {
+  EventTargetWithInlineData::addedEventListener(eventType, listener);
+  if (eventType == EventTypeNames::connect ||
+      eventType == EventTypeNames::disconnect) {
+    ensureDeviceManagerConnection();
+  }
+}
+
+void USB::ensureDeviceManagerConnection() {
+  if (m_deviceManager || !frame())
+    return;
+
+  frame()->interfaceProvider()->getInterface(
+      mojo::MakeRequest(&m_deviceManager));
+  m_deviceManager.set_connection_error_handler(convertToBaseCallback(WTF::bind(
+      &USB::onDeviceManagerConnectionError, wrapWeakPersistent(this))));
+
+  DCHECK(!m_clientBinding.is_bound());
+  m_deviceManager->SetClient(m_clientBinding.CreateInterfacePtrAndBind());
+}
+
 DEFINE_TRACE(USB) {
   visitor->trace(m_deviceManagerRequests);
   visitor->trace(m_chooserServiceRequests);
diff --git a/third_party/WebKit/Source/modules/webusb/USB.h b/third_party/WebKit/Source/modules/webusb/USB.h
index 92ad0d9..5d73165c 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.h
+++ b/third_party/WebKit/Source/modules/webusb/USB.h
@@ -69,9 +69,16 @@
 
   DECLARE_VIRTUAL_TRACE();
 
+ protected:
+  // EventTarget protected overrides.
+  void addedEventListener(const AtomicString& eventType,
+                          RegisteredEventListener&) override;
+
  private:
   explicit USB(LocalFrame& frame);
 
+  void ensureDeviceManagerConnection();
+
   device::usb::blink::DeviceManagerPtr m_deviceManager;
   HeapHashSet<Member<ScriptPromiseResolver>> m_deviceManagerRequests;
   device::usb::blink::ChooserServicePtr m_chooserService;
diff --git a/third_party/WebKit/Source/platform/graphics/Gradient.cpp b/third_party/WebKit/Source/platform/graphics/Gradient.cpp
index e6d5452..0ef2a039 100644
--- a/third_party/WebKit/Source/platform/graphics/Gradient.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Gradient.cpp
@@ -42,7 +42,10 @@
 
 namespace blink {
 
-Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1)
+Gradient::Gradient(const FloatPoint& p0,
+                   const FloatPoint& p1,
+                   GradientSpreadMethod spreadMethod,
+                   ColorInterpolation interpolation)
     : m_p0(p0),
       m_p1(p1),
       m_r0(0),
@@ -50,14 +53,16 @@
       m_aspectRatio(1),
       m_radial(false),
       m_stopsSorted(false),
-      m_drawInPMColorSpace(false),
-      m_spreadMethod(SpreadMethodPad) {}
+      m_spreadMethod(spreadMethod),
+      m_colorInterpolation(interpolation) {}
 
 Gradient::Gradient(const FloatPoint& p0,
                    float r0,
                    const FloatPoint& p1,
                    float r1,
-                   float aspectRatio)
+                   float aspectRatio,
+                   GradientSpreadMethod spreadMethod,
+                   ColorInterpolation interpolation)
     : m_p0(p0),
       m_p1(p1),
       m_r0(r0),
@@ -65,8 +70,8 @@
       m_aspectRatio(aspectRatio),
       m_radial(true),
       m_stopsSorted(false),
-      m_drawInPMColorSpace(false),
-      m_spreadMethod(SpreadMethodPad) {}
+      m_spreadMethod(spreadMethod),
+      m_colorInterpolation(interpolation) {}
 
 Gradient::~Gradient() {}
 
@@ -103,25 +108,6 @@
   std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
 }
 
-void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod) {
-  // FIXME: Should it become necessary, allow calls to this method after
-  // |m_gradient| has been set.
-  DCHECK(!m_cachedShader);
-
-  if (m_spreadMethod == spreadMethod)
-    return;
-
-  m_spreadMethod = spreadMethod;
-}
-
-void Gradient::setDrawsInPMColorSpace(bool drawInPMColorSpace) {
-  if (drawInPMColorSpace == m_drawInPMColorSpace)
-    return;
-
-  m_drawInPMColorSpace = drawInPMColorSpace;
-  m_cachedShader.reset();
-}
-
 // Determine the total number of stops needed, including pseudo-stops at the
 // ends as necessary.
 static size_t totalStopsNeeded(const Gradient::ColorStop* stopData,
@@ -208,9 +194,9 @@
   }
 
   sk_sp<SkShader> shader;
-  uint32_t shouldDrawInPMColorSpace =
-      m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag
-                           : 0;
+  uint32_t flags = m_colorInterpolation == ColorInterpolation::Premultiplied
+                       ? SkGradientShader::kInterpolateColorsInPremul_Flag
+                       : 0;
   if (m_radial) {
     SkMatrix adjustedLocalMatrix = localMatrix;
 
@@ -228,8 +214,7 @@
     if (m_p0 == m_p1 && m_r0 <= 0.0f) {
       shader = SkGradientShader::MakeRadial(
           m_p1.data(), m_r1, colors.data(), pos.data(),
-          static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace,
-          &adjustedLocalMatrix);
+          static_cast<int>(countUsed), tile, flags, &adjustedLocalMatrix);
     } else {
       // The radii we give to Skia must be positive. If we're given a
       // negative radius, ask for zero instead.
@@ -237,14 +222,13 @@
       SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
       shader = SkGradientShader::MakeTwoPointConical(
           m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(),
-          static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace,
-          &adjustedLocalMatrix);
+          static_cast<int>(countUsed), tile, flags, &adjustedLocalMatrix);
     }
   } else {
     SkPoint pts[2] = {m_p0.data(), m_p1.data()};
-    shader = SkGradientShader::MakeLinear(
-        pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile,
-        shouldDrawInPMColorSpace, &localMatrix);
+    shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
+                                          static_cast<int>(countUsed), tile,
+                                          flags, &localMatrix);
   }
 
   if (!shader) {
diff --git a/third_party/WebKit/Source/platform/graphics/Gradient.h b/third_party/WebKit/Source/platform/graphics/Gradient.h
index 273c1fed..bb4832b 100644
--- a/third_party/WebKit/Source/platform/graphics/Gradient.h
+++ b/third_party/WebKit/Source/platform/graphics/Gradient.h
@@ -49,16 +49,28 @@
   WTF_MAKE_NONCOPYABLE(Gradient);
 
  public:
-  static PassRefPtr<Gradient> create(const FloatPoint& p0,
-                                     const FloatPoint& p1) {
-    return adoptRef(new Gradient(p0, p1));
+  enum class ColorInterpolation {
+    Premultiplied,
+    Unpremultiplied,
+  };
+
+  static PassRefPtr<Gradient> create(
+      const FloatPoint& p0,
+      const FloatPoint& p1,
+      GradientSpreadMethod spreadMethod = SpreadMethodPad,
+      ColorInterpolation interpolation = ColorInterpolation::Unpremultiplied) {
+    return adoptRef(new Gradient(p0, p1, spreadMethod, interpolation));
   }
-  static PassRefPtr<Gradient> create(const FloatPoint& p0,
-                                     float r0,
-                                     const FloatPoint& p1,
-                                     float r1,
-                                     float aspectRatio = 1) {
-    return adoptRef(new Gradient(p0, r0, p1, r1, aspectRatio));
+  static PassRefPtr<Gradient> create(
+      const FloatPoint& p0,
+      float r0,
+      const FloatPoint& p1,
+      float r1,
+      float aspectRatio = 1,
+      GradientSpreadMethod spreadMethod = SpreadMethodPad,
+      ColorInterpolation interpolation = ColorInterpolation::Unpremultiplied) {
+    return adoptRef(
+        new Gradient(p0, r0, p1, r1, aspectRatio, spreadMethod, interpolation));
   }
   ~Gradient();
 
@@ -84,51 +96,25 @@
   const FloatPoint& p0() const { return m_p0; }
   const FloatPoint& p1() const { return m_p1; }
 
-  void setP0(const FloatPoint& p) {
-    if (m_p0 == p)
-      return;
-
-    m_p0 = p;
-  }
-
-  void setP1(const FloatPoint& p) {
-    if (m_p1 == p)
-      return;
-
-    m_p1 = p;
-  }
-
   float startRadius() const { return m_r0; }
   float endRadius() const { return m_r1; }
 
-  void setStartRadius(float r) {
-    if (m_r0 == r)
-      return;
-
-    m_r0 = r;
-  }
-
-  void setEndRadius(float r) {
-    if (m_r1 == r)
-      return;
-
-    m_r1 = r;
-  }
-
   void applyToFlags(PaintFlags&, const SkMatrix& localMatrix);
 
-  void setDrawsInPMColorSpace(bool drawInPMColorSpace);
-
-  void setSpreadMethod(GradientSpreadMethod);
   GradientSpreadMethod spreadMethod() const { return m_spreadMethod; }
 
  private:
-  Gradient(const FloatPoint& p0, const FloatPoint& p1);
+  Gradient(const FloatPoint& p0,
+           const FloatPoint& p1,
+           GradientSpreadMethod,
+           ColorInterpolation);
   Gradient(const FloatPoint& p0,
            float r0,
            const FloatPoint& p1,
            float r1,
-           float aspectRatio);
+           float aspectRatio,
+           GradientSpreadMethod,
+           ColorInterpolation);
 
   sk_sp<PaintShader> createShader(const SkMatrix& localMatrix);
 
@@ -142,8 +128,8 @@
   Vector<ColorStop, 2> m_stops;
   bool m_radial;
   bool m_stopsSorted;
-  bool m_drawInPMColorSpace;
   GradientSpreadMethod m_spreadMethod;
+  ColorInterpolation m_colorInterpolation;
 
   mutable sk_sp<PaintShader> m_cachedShader;
 };
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 9459ec1..a1ae793 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -653,6 +653,7 @@
   sources = [
     "platform/mime_registry.mojom",
     "platform/modules/app_banner/app_banner.mojom",
+    "platform/modules/background_fetch/background_fetch.mojom",
     "platform/modules/background_sync/background_sync.mojom",
     "platform/modules/bluetooth/web_bluetooth.mojom",
     "platform/modules/broadcastchannel/broadcast_channel.mojom",
diff --git a/third_party/WebKit/public/platform/modules/background_fetch/OWNERS b/third_party/WebKit/public/platform/modules/background_fetch/OWNERS
new file mode 100644
index 0000000..f239b900
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/background_fetch/OWNERS
@@ -0,0 +1,7 @@
+peter@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# TEAM: platform-capabilities@chromium.org
+# COMPONENT: Blink>BackgroundFetch
diff --git a/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom b/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom
new file mode 100644
index 0000000..9092281
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/background_fetch/background_fetch.mojom
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+enum BackgroundFetchError {
+  NONE,
+  DUPLICATED_TAG
+};
+
+struct IconDefinition {
+  string src;
+  string sizes;
+  string type;
+};
+
+struct BackgroundFetchRegistration {
+  string tag;
+  array<IconDefinition> icons;
+  int64 total_download_size = 0;
+  string title = "";
+};
+
+interface BackgroundFetchService {
+  // TODO(peter): Implement support for the `fetch()` function in Mojo.
+
+  // Updates the user interface for the Background Fetch identified by the
+  // |service_worker_registration_id| and the |tag|.
+  UpdateUI(int64 service_worker_registration_id, string tag, string title)
+      => (BackgroundFetchError error);
+
+  // Aborts the Background Fetch registration identified by the
+  // |service_worker_registration_id| and the |tag|.
+  Abort(int64 service_worker_registration_id, string tag);
+
+  // Gets the Background Fetch registration identified by the
+  // |service_worker_registration_id| and the |tag|.
+  GetRegistration(int64 service_worker_registration_id, string tag)
+      => (BackgroundFetchError error,
+          BackgroundFetchRegistration? registration);
+
+  // Gets the sequence of tags for active Background Fetch registrations given
+  // the |service_worker_registration_id|.
+  GetTags(int64 service_worker_registration_id)
+      => (BackgroundFetchError error,
+          array<string> tags);
+};
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 9239e75..8eca868 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -9985,6 +9985,14 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="MobileNTPOpenedInNewTab">
+  <owner>fhorschig@chromium.org</owner>
+  <description>
+    The user manually created a New Tab Page (NTP) in a new tab that has not
+    been shown before. This includes the initial tab (when starting Chrome).
+  </description>
+</action>
+
 <action name="MobileNTPRecentlyClosed">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9dab252..a6c7ce90 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -90950,6 +90950,11 @@
   <int value="1161" label="AUDIO_SETMUTE"/>
   <int value="1162" label="AUDIO_GETDEVICES"/>
   <int value="1163" label="VIRTUALKEYBOARD_RESTRICTFEATURES"/>
+  <int value="1164" label="NETWORKINGCASTPRIVATE_VERIFYDESTINATION"/>
+  <int value="1165" label="NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTCREDENTIALS"/>
+  <int value="1166" label="NETWORKINGCASTPRIVATE_VERIFYANDENCRYPTDATA"/>
+  <int value="1167" label="NETWORKINGCASTPRIVATE_SETWIFITDLSENABLEDSTATE"/>
+  <int value="1168" label="NETWORKINGCASTPRIVATE_GETWIFITDLSSTATUS"/>
 </enum>
 
 <enum name="ExtensionIconState" type="int">
@@ -91375,6 +91380,7 @@
   <int value="200" label="kClipboard"/>
   <int value="201" label="kNetworkingOnc"/>
   <int value="202" label="kVirtualKeyboard"/>
+  <int value="203" label="kNetworkingCastPrivate"/>
 </enum>
 
 <enum name="ExtensionServiceVerifyAllSuccess" type="int">
@@ -94304,6 +94310,7 @@
   <int value="4" label="File could not be memory-mapped by system."/>
   <int value="5" label="File has invalid contents."/>
   <int value="6" label="File could not be exclusively opened."/>
+  <int value="7" label="File contents internally deleted."/>
 </enum>
 
 <enum name="FileReaderSyncWorkerType" type="int">
@@ -109504,6 +109511,9 @@
     The credentials are being transfered to a new profile, so the old one is
     signed out.
   </int>
+  <int value="7" label="Authentication failed with force signin">
+    Signed out because credentials are invalid and force-sign-in is enabled.
+  </int>
 </enum>
 
 <enum name="SigninSource" type="int">
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
index f338a950..340e1263 100644
--- a/ui/base/accelerators/accelerator.cc
+++ b/ui/base/accelerators/accelerator.cc
@@ -27,33 +27,33 @@
 
 namespace {
 
-const int kModifierMask = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
-                            ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN;
+const int kModifierMask =
+    EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN | EF_COMMAND_DOWN;
 
 const int kInterestingFlagsMask =
-    kModifierMask | ui::EF_IS_SYNTHESIZED | ui::EF_IS_REPEAT;
+    kModifierMask | EF_IS_SYNTHESIZED | EF_IS_REPEAT;
 
 }  // namespace
 
-Accelerator::Accelerator()
-    : key_code_(ui::VKEY_UNKNOWN), type_(ui::ET_KEY_PRESSED), modifiers_(0) {}
+Accelerator::Accelerator() : Accelerator(VKEY_UNKNOWN, EF_NONE) {}
 
-Accelerator::Accelerator(KeyboardCode keycode, int modifiers)
-    : key_code_(keycode),
-      type_(ui::ET_KEY_PRESSED),
+Accelerator::Accelerator(KeyboardCode key_code, int modifiers)
+    : key_code_(key_code),
+      key_state_(KeyState::PRESSED),
       modifiers_(modifiers & kInterestingFlagsMask) {}
 
 Accelerator::Accelerator(const KeyEvent& key_event)
     : key_code_(key_event.key_code()),
-      type_(key_event.type()),
+      key_state_(key_event.type() == ET_KEY_PRESSED ? KeyState::PRESSED
+                                                    : KeyState::RELEASED),
       // |modifiers_| may include the repeat flag.
       modifiers_(key_event.flags() & kInterestingFlagsMask) {}
 
 Accelerator::Accelerator(const Accelerator& accelerator) {
   key_code_ = accelerator.key_code_;
-  type_ = accelerator.type_;
+  key_state_ = accelerator.key_state_;
   modifiers_ = accelerator.modifiers_;
-  if (accelerator.platform_accelerator_.get())
+  if (accelerator.platform_accelerator_)
     platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
 }
 
@@ -68,9 +68,9 @@
 Accelerator& Accelerator::operator=(const Accelerator& accelerator) {
   if (this != &accelerator) {
     key_code_ = accelerator.key_code_;
-    type_ = accelerator.type_;
+    key_state_ = accelerator.key_state_;
     modifiers_ = accelerator.modifiers_;
-    if (accelerator.platform_accelerator_.get())
+    if (accelerator.platform_accelerator_)
       platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
     else
       platform_accelerator_.reset();
@@ -81,14 +81,16 @@
 bool Accelerator::operator <(const Accelerator& rhs) const {
   if (key_code_ != rhs.key_code_)
     return key_code_ < rhs.key_code_;
-  if (type_ != rhs.type_)
-    return type_ < rhs.type_;
+  if (key_state_ != rhs.key_state_) {
+    return static_cast<int32_t>(key_state_) <
+           static_cast<int32_t>(rhs.key_state_);
+  }
   return MaskOutKeyEventFlags(modifiers_) <
          MaskOutKeyEventFlags(rhs.modifiers_);
 }
 
 bool Accelerator::operator ==(const Accelerator& rhs) const {
-  if ((key_code_ == rhs.key_code_) && (type_ == rhs.type_) &&
+  if ((key_code_ == rhs.key_code_) && (key_state_ == rhs.key_state_) &&
       (MaskOutKeyEventFlags(modifiers_) ==
        MaskOutKeyEventFlags(rhs.modifiers_)))
     return true;
@@ -127,73 +129,73 @@
 base::string16 Accelerator::GetShortcutText() const {
   int string_id = 0;
   switch (key_code_) {
-    case ui::VKEY_TAB:
+    case VKEY_TAB:
       string_id = IDS_APP_TAB_KEY;
       break;
-    case ui::VKEY_RETURN:
+    case VKEY_RETURN:
       string_id = IDS_APP_ENTER_KEY;
       break;
-    case ui::VKEY_ESCAPE:
+    case VKEY_ESCAPE:
       string_id = IDS_APP_ESC_KEY;
       break;
-    case ui::VKEY_SPACE:
+    case VKEY_SPACE:
       string_id = IDS_APP_SPACE_KEY;
       break;
-    case ui::VKEY_PRIOR:
+    case VKEY_PRIOR:
       string_id = IDS_APP_PAGEUP_KEY;
       break;
-    case ui::VKEY_NEXT:
+    case VKEY_NEXT:
       string_id = IDS_APP_PAGEDOWN_KEY;
       break;
-    case ui::VKEY_END:
+    case VKEY_END:
       string_id = IDS_APP_END_KEY;
       break;
-    case ui::VKEY_HOME:
+    case VKEY_HOME:
       string_id = IDS_APP_HOME_KEY;
       break;
-    case ui::VKEY_INSERT:
+    case VKEY_INSERT:
       string_id = IDS_APP_INSERT_KEY;
       break;
-    case ui::VKEY_DELETE:
+    case VKEY_DELETE:
       string_id = IDS_APP_DELETE_KEY;
       break;
-    case ui::VKEY_LEFT:
+    case VKEY_LEFT:
       string_id = IDS_APP_LEFT_ARROW_KEY;
       break;
-    case ui::VKEY_RIGHT:
+    case VKEY_RIGHT:
       string_id = IDS_APP_RIGHT_ARROW_KEY;
       break;
-    case ui::VKEY_UP:
+    case VKEY_UP:
       string_id = IDS_APP_UP_ARROW_KEY;
       break;
-    case ui::VKEY_DOWN:
+    case VKEY_DOWN:
       string_id = IDS_APP_DOWN_ARROW_KEY;
       break;
-    case ui::VKEY_BACK:
+    case VKEY_BACK:
       string_id = IDS_APP_BACKSPACE_KEY;
       break;
-    case ui::VKEY_F1:
+    case VKEY_F1:
       string_id = IDS_APP_F1_KEY;
       break;
-    case ui::VKEY_F11:
+    case VKEY_F11:
       string_id = IDS_APP_F11_KEY;
       break;
-    case ui::VKEY_OEM_COMMA:
+    case VKEY_OEM_COMMA:
       string_id = IDS_APP_COMMA_KEY;
       break;
-    case ui::VKEY_OEM_PERIOD:
+    case VKEY_OEM_PERIOD:
       string_id = IDS_APP_PERIOD_KEY;
       break;
-    case ui::VKEY_MEDIA_NEXT_TRACK:
+    case VKEY_MEDIA_NEXT_TRACK:
       string_id = IDS_APP_MEDIA_NEXT_TRACK_KEY;
       break;
-    case ui::VKEY_MEDIA_PLAY_PAUSE:
+    case VKEY_MEDIA_PLAY_PAUSE:
       string_id = IDS_APP_MEDIA_PLAY_PAUSE_KEY;
       break;
-    case ui::VKEY_MEDIA_PREV_TRACK:
+    case VKEY_MEDIA_PREV_TRACK:
       string_id = IDS_APP_MEDIA_PREV_TRACK_KEY;
       break;
-    case ui::VKEY_MEDIA_STOP:
+    case VKEY_MEDIA_STOP:
       string_id = IDS_APP_MEDIA_STOP_KEY;
       break;
     default:
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
index 7941f33..4363198a 100644
--- a/ui/base/accelerators/accelerator.h
+++ b/ui/base/accelerators/accelerator.h
@@ -35,9 +35,14 @@
 // repeat flag in its comparison.
 class UI_BASE_EXPORT Accelerator {
  public:
+  enum class KeyState {
+    PRESSED,
+    RELEASED,
+  };
+
   Accelerator();
   // NOTE: this constructor strips out non key related flags.
-  Accelerator(ui::KeyboardCode keycode, int modifiers);
+  Accelerator(KeyboardCode key_code, int modifiers);
   explicit Accelerator(const KeyEvent& key_event);
   Accelerator(const Accelerator& accelerator);
   ~Accelerator();
@@ -56,12 +61,11 @@
 
   bool operator !=(const Accelerator& rhs) const;
 
-  ui::KeyboardCode key_code() const { return key_code_; }
+  KeyboardCode key_code() const { return key_code_; }
 
-  // Sets the event type if the accelerator should be processed on an event
-  // other than ui::ET_KEY_PRESSED.
-  void set_type(ui::EventType type) { type_ = type; }
-  ui::EventType type() const { return type_; }
+  // Sets the key state that triggers the accelerator. Default is PRESSED.
+  void set_key_state(KeyState state) { key_state_ = state; }
+  KeyState key_state() const { return key_state_; }
 
   int modifiers() const { return modifiers_; }
 
@@ -87,8 +91,7 @@
   // The keycode (VK_...).
   KeyboardCode key_code_;
 
-  // The event type (usually ui::ET_KEY_PRESSED).
-  EventType type_;
+  KeyState key_state_;
 
   // The state of the Shift/Ctrl/Alt keys. This corresponds to Event::flags().
   int modifiers_;
@@ -120,9 +123,8 @@
  public:
   // Gets the accelerator for the specified command id. Returns true if the
   // command id has a valid accelerator, false otherwise.
-  virtual bool GetAcceleratorForCommandId(
-      int command_id,
-      ui::Accelerator* accelerator) const = 0;
+  virtual bool GetAcceleratorForCommandId(int command_id,
+                                          Accelerator* accelerator) const = 0;
 
  protected:
   virtual ~AcceleratorProvider() {}
diff --git a/ui/base/accelerators/accelerator_manager_unittest.cc b/ui/base/accelerators/accelerator_manager_unittest.cc
index 50e8841..3cca7da 100644
--- a/ui/base/accelerators/accelerator_manager_unittest.cc
+++ b/ui/base/accelerators/accelerator_manager_unittest.cc
@@ -247,9 +247,7 @@
     EXPECT_EQ(last_count + 1, target.accelerator_pressed_count()) << i;
 
     // The non-registered accelerators are not processed.
-    accelerator.set_type(ET_UNKNOWN);
-    EXPECT_FALSE(manager_.Process(accelerator)) << i;  // different type
-    accelerator.set_type(ET_KEY_RELEASED);
+    accelerator.set_key_state(Accelerator::KeyState::RELEASED);
     EXPECT_FALSE(manager_.Process(accelerator)) << i;  // different type
 
     EXPECT_FALSE(manager_.Process(GetAccelerator(VKEY_UNKNOWN, modifiers)))
diff --git a/ui/content_accelerators/accelerator_util.cc b/ui/content_accelerators/accelerator_util.cc
index 4e9d0b4..b2924a26 100644
--- a/ui/content_accelerators/accelerator_util.cc
+++ b/ui/content_accelerators/accelerator_util.cc
@@ -41,7 +41,7 @@
       static_cast<ui::KeyboardCode>(event.windowsKeyCode),
       GetModifiersFromNativeWebKeyboardEvent(event));
   if (event.type() == blink::WebInputEvent::KeyUp)
-    accelerator.set_type(ui::ET_KEY_RELEASED);
+    accelerator.set_key_state(Accelerator::KeyState::RELEASED);
   return accelerator;
 }
 
diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp
index 2ff25d7..15c5727 100644
--- a/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/foreground/js/compiled_resources2.gyp
@@ -5,10 +5,24 @@
   'targets': [
 #    {
 #      'target_name': 'actions_controller',
+#      'dependencies': [
+#        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+#        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+#        '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
+#        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:context_menu_handler',
+#        'actions_model',
+#      ],
 #      'includes': ['../../../compile_js2.gypi'],
 #    },
 #    {
 #      'target_name': 'actions_model',
+#      'dependencies': [
+#        '../../background/js/compiled_resources2.gyp:drive_sync_handler',
+#        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+#        '<(EXTERNS_GYP):file_manager_private',
+#        'folder_shortcuts_data_model',
+#        'metadata/compiled_resources2.gyp:metadata_model',
+#      ],
 #      'includes': ['../../../compile_js2.gypi'],
 #    },
 #    {
@@ -61,6 +75,12 @@
 #    },
 #    {
 #      'target_name': 'file_selection',
+#      'dependencies': [
+#        '../../common/js/compiled_resources2.gyp:util',
+#        '../../common/js/compiled_resources2.gyp:volume_manager_common',
+#        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+#        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+#      ],
 #      'includes': ['../../../compile_js2.gypi'],
 #    },
 #    {
@@ -75,10 +95,18 @@
 #      'target_name': 'file_watcher',
 #      'includes': ['../../../compile_js2.gypi'],
 #    },
-#    {
-#      'target_name': 'folder_shortcuts_data_model',
-#      'includes': ['../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'folder_shortcuts_data_model',
+      'dependencies': [
+        '../../common/js/compiled_resources2.gyp:async_util',
+        '../../common/js/compiled_resources2.gyp:metrics',
+        '../../common/js/compiled_resources2.gyp:util',
+        '../../common/js/compiled_resources2.gyp:volume_manager_common',
+        '<(EXTERNS_GYP):chrome_extensions',
+        'volume_manager_wrapper',
+      ],
+      'includes': ['../../../compile_js2.gypi'],
+    },
 #    {
 #      'target_name': 'gear_menu_controller',
 #      'includes': ['../../../compile_js2.gypi'],
@@ -206,6 +234,12 @@
     },
 #    {
 #      'target_name': 'toolbar_controller',
+#      'dependencies': [
+#        '../../common/js/compiled_resources2.gyp:util',
+#        'file_selection',
+#        'ui/compiled_resources2.gyp:list_container',
+#        'ui/compiled_resources2.gyp:location_line',
+#      ],
 #      'includes': ['../../../compile_js2.gypi'],
 #    },
     {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
index 12aee82..f42d42d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
@@ -101,14 +101,21 @@
 #      'target_name': 'gear_menu',
 #      'includes': ['../../../../compile_js2.gypi'],
 #    },
-#    {
-#      'target_name': 'list_container',
-#      'includes': ['../../../../compile_js2.gypi'],
-#    },
-#    {
-#      'target_name': 'location_line',
-#      'includes': ['../../../../compile_js2.gypi'],
-#    },
+    {
+      'target_name': 'list_container',
+      'includes': ['../../../../compile_js2.gypi'],
+    },
+    {
+      'target_name': 'location_line',
+      'dependencies': [
+        '../../../../externs/compiled_resources2.gyp:platform',
+        '../../../../externs/compiled_resources2.gyp:volume_manager',
+        '../../../common/js/compiled_resources2.gyp:util',
+        '../../../common/js/compiled_resources2.gyp:volume_manager_common',
+        '../compiled_resources2.gyp:volume_manager_wrapper',
+      ],
+      'includes': ['../../../../compile_js2.gypi'],
+    },
 #    {
 #      'target_name': 'multi_profile_share_dialog',
 #      'includes': ['../../../../compile_js2.gypi'],
diff --git a/ui/gfx/render_text_mac.mm b/ui/gfx/render_text_mac.mm
index 6075a0d7..eafd25a 100644
--- a/ui/gfx/render_text_mac.mm
+++ b/ui/gfx/render_text_mac.mm
@@ -428,14 +428,6 @@
     run->width = run_width;
     run->glyphs.resize(glyph_count);
     CTRunGetGlyphs(ct_run, empty_cf_range, &run->glyphs[0]);
-    // CTRunGetGlyphs() sometimes returns glyphs with value 65535 and zero
-    // width (this has been observed at the beginning of a string containing
-    // Arabic content). Passing these to Skia will trigger an assertion;
-    // instead set their values to 0.
-    for (size_t glyph = 0; glyph < glyph_count; glyph++) {
-      if (run->glyphs[glyph] == 65535)
-        run->glyphs[glyph] = 0;
-    }
 
     run->glyph_positions.resize(glyph_count);
     const CGPoint* positions_ptr = CTRunGetPositionsPtr(ct_run);
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index 9d41e98ad..d4c7487b3 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -421,8 +421,10 @@
   }
 }
 
-int GetFourCCFormatForFramebuffer(gfx::BufferFormat format) {
-  // Currently, drm supports 24 bitcolordepth for hardware overlay.
+int GetFourCCFormatForOpaqueFramebuffer(gfx::BufferFormat format) {
+  // DRM atomic interface doesn't currently support specifying an alpha
+  // blending. We can simulate disabling alpha bleding creating an fb
+  // with a format without the alpha channel.
   switch (format) {
     case gfx::BufferFormat::RGBA_8888:
     case gfx::BufferFormat::RGBX_8888:
diff --git a/ui/ozone/platform/drm/common/drm_util.h b/ui/ozone/platform/drm/common/drm_util.h
index 52e90fe..57f9d217 100644
--- a/ui/ozone/platform/drm/common/drm_util.h
+++ b/ui/ozone/platform/drm/common/drm_util.h
@@ -66,7 +66,7 @@
 int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format);
 gfx::BufferFormat GetBufferFormatFromFourCCFormat(int format);
 
-int GetFourCCFormatForFramebuffer(gfx::BufferFormat format);
+int GetFourCCFormatForOpaqueFramebuffer(gfx::BufferFormat format);
 
 gfx::Size GetMaximumCursorSize(int fd);
 
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.cc b/ui/ozone/platform/drm/gpu/drm_buffer.cc
index 17bc5d3..d511661b 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -99,6 +99,14 @@
   return fb_pixel_format_;
 }
 
+uint32_t DrmBuffer::GetOpaqueFramebufferId() const {
+  return framebuffer_;
+}
+
+uint32_t DrmBuffer::GetOpaqueFramebufferPixelFormat() const {
+  return fb_pixel_format_;
+}
+
 uint32_t DrmBuffer::GetHandle() const {
   return handle_;
 }
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.h b/ui/ozone/platform/drm/gpu/drm_buffer.h
index a9460b49..dd162198 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.h
@@ -38,6 +38,8 @@
   // ScanoutBuffer:
   uint32_t GetFramebufferId() const override;
   uint32_t GetFramebufferPixelFormat() const override;
+  uint32_t GetOpaqueFramebufferId() const override;
+  uint32_t GetOpaqueFramebufferPixelFormat() const override;
   uint32_t GetHandle() const override;
   gfx::Size GetSize() const override;
   const DrmDevice* GetDrmDevice() const override;
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
index af00fe3..bfe65bbb 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -131,7 +131,10 @@
     gfx::Size scaled_buffer_size = GetScaledSize(
         overlay.buffer_size, overlay.display_rect, overlay.crop_rect);
 
-    uint32_t original_format = GetFourCCFormatForFramebuffer(overlay.format);
+    uint32_t original_format =
+        overlay.plane_z_order
+            ? GetFourCCFormatFromBufferFormat(overlay.format)
+            : GetFourCCFormatForOpaqueFramebuffer(overlay.format);
     scoped_refptr<ScanoutBuffer> buffer =
         GetBufferForPageFlipTest(drm, overlay.buffer_size, original_format,
                                  buffer_generator_, &reusable_buffers);
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index f0a69e73..3bffad6 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -122,19 +122,21 @@
   ui::OverlayCheck_Params primary_candidate;
   primary_candidate.buffer_size = primary_rect_.size();
   primary_candidate.display_rect = primary_rect_;
+  primary_candidate.format = gfx::BufferFormat::BGRX_8888;
   overlay_params_.push_back(primary_candidate);
 
   ui::OverlayCheck_Params overlay_candidate;
   overlay_candidate.buffer_size = overlay_rect_.size();
   overlay_candidate.display_rect = overlay_rect_;
   overlay_candidate.plane_z_order = 1;
+  overlay_candidate.format = gfx::BufferFormat::BGRX_8888;
   overlay_params_.push_back(overlay_candidate);
 
   scoped_refptr<ui::DrmDevice> drm =
       window_->GetController()->GetAllocationDrmDevice();
   for (const auto& param : overlay_params_) {
     scoped_refptr<ui::ScanoutBuffer> scanout_buffer = buffer_generator_->Create(
-        drm, ui::GetFourCCFormatForFramebuffer(param.format),
+        drm, ui::GetFourCCFormatFromBufferFormat(param.format),
         param.buffer_size);
     ui::OverlayPlane plane(std::move(scanout_buffer), param.plane_z_order,
                            param.transform, param.display_rect, param.crop_rect,
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
index eb0b900..d36ec22 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
@@ -21,11 +21,9 @@
     : drm_(drm), bo_(bo) {
   if (flags & GBM_BO_USE_SCANOUT) {
     DCHECK(bo_);
-    // The framebuffer format might be different than the format:
-    // drm supports 24 bit color depth and formats with alpha will
-    // be converted to one without it.
-    framebuffer_pixel_format_ =
-        GetFourCCFormatForFramebuffer(GetBufferFormatFromFourCCFormat(format));
+    framebuffer_pixel_format_ = format;
+    opaque_framebuffer_pixel_format_ = GetFourCCFormatForOpaqueFramebuffer(
+        GetBufferFormatFromFourCCFormat(format));
 
     // TODO(dcastagna): Add multi-planar support.
     uint32_t handles[4] = {0};
@@ -43,6 +41,12 @@
     drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo),
                           framebuffer_pixel_format_, handles, strides, offsets,
                           modifiers, &framebuffer_, addfb_flags);
+    if (opaque_framebuffer_pixel_format_ != framebuffer_pixel_format_) {
+      drm_->AddFramebuffer2(gbm_bo_get_width(bo), gbm_bo_get_height(bo),
+                            opaque_framebuffer_pixel_format_, handles, strides,
+                            offsets, modifiers, &opaque_framebuffer_,
+                            addfb_flags);
+    }
   }
 }
 
@@ -55,6 +59,10 @@
   return framebuffer_;
 }
 
+uint32_t GbmBufferBase::GetOpaqueFramebufferId() const {
+  return opaque_framebuffer_ ? opaque_framebuffer_ : framebuffer_;
+}
+
 uint32_t GbmBufferBase::GetHandle() const {
   return gbm_bo_get_handle(bo_).u32;
 }
@@ -68,6 +76,11 @@
   return framebuffer_pixel_format_;
 }
 
+uint32_t GbmBufferBase::GetOpaqueFramebufferPixelFormat() const {
+  DCHECK(framebuffer_);
+  return opaque_framebuffer_pixel_format_;
+}
+
 const DrmDevice* GbmBufferBase::GetDrmDevice() const {
   return drm_.get();
 }
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
index a4732c7..1aca1bb 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
@@ -27,9 +27,11 @@
 
   // ScanoutBuffer:
   uint32_t GetFramebufferId() const override;
+  uint32_t GetOpaqueFramebufferId() const override;
   uint32_t GetHandle() const override;
   gfx::Size GetSize() const override;
   uint32_t GetFramebufferPixelFormat() const override;
+  uint32_t GetOpaqueFramebufferPixelFormat() const override;
   const DrmDevice* GetDrmDevice() const override;
   bool RequiresGlFinish() const override;
 
@@ -47,6 +49,11 @@
   gbm_bo* bo_;
   uint32_t framebuffer_ = 0;
   uint32_t framebuffer_pixel_format_ = 0;
+  // If |opaque_framebuffer_pixel_format_| differs from
+  // |framebuffer_pixel_format_| the following member is set to a valid fb,
+  // otherwise it is set to 0.
+  uint32_t opaque_framebuffer_ = 0;
+  uint32_t opaque_framebuffer_pixel_format_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(GbmBufferBase);
 };
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index e3a2b28..17bdd2a 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -95,8 +95,11 @@
     CrtcController* crtc) {
   HardwareDisplayPlaneAtomic* atomic_plane =
       static_cast<HardwareDisplayPlaneAtomic*>(hw_plane);
+  uint32_t framebuffer_id = overlay.z_order
+                                ? overlay.buffer->GetFramebufferId()
+                                : overlay.buffer->GetOpaqueFramebufferId();
   if (!atomic_plane->SetPlaneData(plane_list->atomic_property_set.get(),
-                                  crtc_id, overlay.buffer->GetFramebufferId(),
+                                  crtc_id, framebuffer_id,
                                   overlay.display_bounds, src_rect)) {
     LOG(ERROR) << "Failed to set plane properties";
     return false;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
index 0c92d4aa..e412076 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
@@ -110,7 +110,7 @@
       plane_list->legacy_page_flips.back().crtc_id != crtc_id) {
     plane_list->legacy_page_flips.push_back(
         HardwareDisplayPlaneList::PageFlipInfo(
-            crtc_id, overlay.buffer->GetFramebufferId(), crtc));
+            crtc_id, overlay.buffer->GetOpaqueFramebufferId(), crtc));
   } else {
     plane_list->legacy_page_flips.back().planes.push_back(
         HardwareDisplayPlaneList::PageFlipInfo::Plane(
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
index d372f8e..91c0082d 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
@@ -15,6 +15,10 @@
   return 1;
 }
 
+uint32_t MockScanoutBuffer::GetOpaqueFramebufferId() const {
+  return 2;
+}
+
 uint32_t MockScanoutBuffer::GetHandle() const {
   return 0;
 }
@@ -27,6 +31,10 @@
   return format_;
 }
 
+uint32_t MockScanoutBuffer::GetOpaqueFramebufferPixelFormat() const {
+  return format_;
+}
+
 const DrmDevice* MockScanoutBuffer::GetDrmDevice() const {
   return nullptr;
 }
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
index 71411f3..e2e9046 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
@@ -20,9 +20,11 @@
 
   // ScanoutBuffer:
   uint32_t GetFramebufferId() const override;
+  uint32_t GetOpaqueFramebufferId() const override;
   uint32_t GetHandle() const override;
   gfx::Size GetSize() const override;
   uint32_t GetFramebufferPixelFormat() const override;
+  uint32_t GetOpaqueFramebufferPixelFormat() const override;
   const DrmDevice* GetDrmDevice() const override;
   bool RequiresGlFinish() const override;
 
diff --git a/ui/ozone/platform/drm/gpu/scanout_buffer.h b/ui/ozone/platform/drm/gpu/scanout_buffer.h
index 529490a..8a5cd13c 100644
--- a/ui/ozone/platform/drm/gpu/scanout_buffer.h
+++ b/ui/ozone/platform/drm/gpu/scanout_buffer.h
@@ -21,11 +21,19 @@
   // ID allocated by the KMS API when the buffer is registered (via the handle).
   virtual uint32_t GetFramebufferId() const = 0;
 
+  // ID allocated if the buffer is also registered with a different pixel format
+  // so that it can be scheduled as an opaque buffer.
+  virtual uint32_t GetOpaqueFramebufferId() const = 0;
+
   // Returns FourCC format representing the way pixel data has been encoded in
   // memory for the registered framebuffer. This can be used to check if frame
   // buffer is compatible with a given hardware plane.
   virtual uint32_t GetFramebufferPixelFormat() const = 0;
 
+  // Returns FourCC format that should be used to schedule this buffer for
+  // scanout when used as an opaque buffer.
+  virtual uint32_t GetOpaqueFramebufferPixelFormat() const = 0;
+
   // Handle for the buffer. This is received when allocating the buffer.
   virtual uint32_t GetHandle() const = 0;
 
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 09e9b4257..881188e 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -345,7 +345,7 @@
 
   gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
   scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice();
-  uint32_t fourcc_format = ui::GetFourCCFormatForFramebuffer(format);
+  uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format);
   scoped_refptr<ScanoutBuffer> buffer =
       buffer_generator_->Create(drm, fourcc_format, bounds.size());
   if (!buffer) {
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 8414521..2530685 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -771,8 +771,11 @@
 
 // This function is called by BrowserView to execute clipboard commands.
 bool Textfield::AcceleratorPressed(const ui::Accelerator& accelerator) {
-  ui::KeyEvent event(accelerator.type(), accelerator.key_code(),
-                     accelerator.modifiers());
+  ui::KeyEvent event(
+      accelerator.key_state() == ui::Accelerator::KeyState::PRESSED
+          ? ui::ET_KEY_PRESSED
+          : ui::ET_KEY_RELEASED,
+      accelerator.key_code(), accelerator.modifiers());
   ExecuteTextEditCommand(GetCommandForKeyEvent(event));
   return true;
 }