diff --git a/AUTHORS b/AUTHORS
index f773b6d..e244d396 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -405,6 +405,7 @@
 Kenneth Zhou <knthzh@gmail.com>
 Keonho Kim <keonho07.kim@samsung.com>
 Ketan Goyal <ketan.goyal@samsung.com>
+Kevin Gibbons <bakkot@gmail.com>
 Kevin Lee Helpingstine <sig11@reprehensible.net>
 Kevin M. McCormick <mckev@amazon.com>
 Khasim Syed Mohammed <khasim.mohammed@linaro.org>
diff --git a/BUILD.gn b/BUILD.gn
index 5dbfd23a..1ab50210 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -98,6 +98,8 @@
   if (!is_ios && !is_android && !is_chromecast && !is_fuchsia) {
     deps += [
       "//chrome",
+      "//chrome/installer/zucchini:zucchini",
+      "//chrome/installer/zucchini:zucchini_unittests",
       "//chrome/test:browser_tests",
       "//chrome/test:interactive_ui_tests",
       "//chrome/test:sync_integration_tests",
diff --git a/DEPS b/DEPS
index fa8f4632..3c0c08fd7 100644
--- a/DEPS
+++ b/DEPS
@@ -56,7 +56,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
-  'buildtools_revision': '9a65473a7e8f39f04fd134e69470ab1b48514b0e',
+  'buildtools_revision': 'b92ff913082ac9223b48eee9a5fc9db91346279a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'd5a13afe9265463a497db40d8c66a8a736a86bc2',
+  'pdfium_revision': 'e10509a3d2a1641984845d579963d574305ea6cc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '821867d51814b9ac27220e10e496c58e034c9c2a',
+  'catapult_revision': '1556ddcf20a16bdd8f54d7a9bd43df8dc5b4a53d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -366,7 +366,7 @@
       Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0',
 
     'src/ios/third_party/material_components_ios/src':
-      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'b452b1e7fb85cc9aeef2df2b6a44cbe0e8594560',
+      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'f2fbf2501a825c023f2d846aeba4a292f1053c03',
 
     'src/ios/third_party/material_font_disk_loader_ios/src':
       Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '8e30188777b016182658fbaa0a4a020a48183224',
diff --git a/WATCHLISTS b/WATCHLISTS
index fe1759c..2a4e2bd 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1904,7 +1904,6 @@
              'imcheng+watch@chromium.org',
              'isheriff+watch@chromium.org',
              'jasonroberts+watch@google.com',
-             'mfoltz+watch@chromium.org',
              'miu+watch@chromium.org',
              'xjz+watch@chromium.org'],
     'cast_certificate': ['dougsteed+watch@chromium.org',
@@ -2225,8 +2224,7 @@
                'nhiroki@chromium.org',
                'tzik@chromium.org'],
     'tab_alert_indicators': ['miu+watch@chromium.org'],
-    'tab_capture': ['mfoltz+watch@chromium.org',
-                    'miu+watch@chromium.org',
+    'tab_capture': ['miu+watch@chromium.org',
                     'xjz+watch@chromium.org'],
     'tab_contents': ['ajwong+watch@chromium.org',
                      'avi@chromium.org',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 7febf9a..9339118 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -166,7 +166,8 @@
 // A dummy binder for mojo interface autofill::mojom::PasswordManagerDriver.
 void DummyBindPasswordManagerDriver(
     const service_manager::BindSourceInfo& source_info,
-    autofill::mojom::PasswordManagerDriverRequest request) {}
+    autofill::mojom::PasswordManagerDriverRequest request,
+    content::RenderFrameHost* render_frame_host) {}
 
 }  // anonymous namespace
 
@@ -189,7 +190,15 @@
   return AwBrowserContext::GetDefault();
 }
 
-AwContentBrowserClient::AwContentBrowserClient() {}
+AwContentBrowserClient::AwContentBrowserClient() {
+  frame_interfaces_.AddInterface(
+      base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver));
+  // Although WebView does not support password manager feature, renderer code
+  // could still request this interface, so we register a dummy binder which
+  // just drops the incoming request, to avoid the 'Failed to locate a binder
+  // for interface' error log..
+  frame_interfaces_.AddInterface(base::Bind(&DummyBindPasswordManagerDriver));
+}
 
 AwContentBrowserClient::~AwContentBrowserClient() {}
 
@@ -542,18 +551,16 @@
   return base::JSONReader::Read(manifest_contents);
 }
 
-void AwContentBrowserClient::ExposeInterfacesToFrame(
-    service_manager::BinderRegistry* registry,
-    content::RenderFrameHost* render_frame_host) {
-  registry->AddInterface(
-      base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver,
-                 render_frame_host));
-
-  // Although WebView does not support password manager feature, renderer code
-  // could still request this interface, so we register a dummy binder which
-  // just drops the incoming request, to avoid the 'Failed to locate a binder
-  // for interface' error log..
-  registry->AddInterface(base::Bind(&DummyBindPasswordManagerDriver));
+void AwContentBrowserClient::BindInterfaceRequestFromFrame(
+    content::RenderFrameHost* render_frame_host,
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  if (frame_interfaces_.CanBindInterface(interface_name)) {
+    frame_interfaces_.BindInterface(source_info, interface_name,
+                                    std::move(interface_pipe),
+                                    render_frame_host);
+  }
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index bc18ddb..c6596ad 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -12,6 +12,11 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "content/public/browser/content_browser_client.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+namespace content {
+class RenderFrameHost;
+}
 
 namespace android_webview {
 
@@ -128,15 +133,20 @@
   content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
   std::unique_ptr<base::Value> GetServiceManifestOverlay(
       base::StringPiece name) override;
-  void ExposeInterfacesToFrame(
-      service_manager::BinderRegistry* registry,
-      content::RenderFrameHost* render_frame_host) override;
+  void BindInterfaceRequestFromFrame(
+      content::RenderFrameHost* render_frame_host,
+      const service_manager::BindSourceInfo& source_info,
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle interface_pipe) override;
 
  private:
   // Android WebView currently has a single global (non-off-the-record) browser
   // context.
   std::unique_ptr<AwBrowserContext> browser_context_;
 
+  service_manager::BinderRegistryWithParams<content::RenderFrameHost*>
+      frame_interfaces_;
+
   DISALLOW_COPY_AND_ASSIGN(AwContentBrowserClient);
 };
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index db72762..8439256 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -79,19 +79,6 @@
     "default_accessibility_delegate.h",
     "default_wallpaper_delegate.cc",
     "default_wallpaper_delegate.h",
-    "devtools/ash_devtools_css_agent.cc",
-    "devtools/ash_devtools_css_agent.h",
-    "devtools/ash_devtools_dom_agent.cc",
-    "devtools/ash_devtools_dom_agent.h",
-    "devtools/ui_element.cc",
-    "devtools/ui_element.h",
-    "devtools/ui_element_delegate.h",
-    "devtools/view_element.cc",
-    "devtools/view_element.h",
-    "devtools/widget_element.cc",
-    "devtools/widget_element.h",
-    "devtools/window_element.cc",
-    "devtools/window_element.h",
     "display/ash_display_controller.cc",
     "display/ash_display_controller.h",
     "display/cursor_window_controller.cc",
@@ -856,6 +843,7 @@
     "//components/session_manager:base",
     "//components/signin/core/account_id",
     "//components/ui_devtools",
+    "//components/ui_devtools/views",
     "//components/user_manager",
     "//components/vector_icons",
     "//components/wallpaper",
@@ -1166,7 +1154,6 @@
     "accelerators/spoken_feedback_toggler_unittest.cc",
     "ash_touch_exploration_manager_chromeos_unittest.cc",
     "autoclick/autoclick_unittest.cc",
-    "devtools/ash_devtools_unittest.cc",
     "display/display_configuration_controller_unittest.cc",
     "drag_drop/drag_image_view_unittest.cc",
     "first_run/first_run_helper_unittest.cc",
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
index 8a708ec..f7336f85 100644
--- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
+++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -510,16 +510,6 @@
   EXPECT_EQ(display::Display::ROTATE_90, GetCurrentInternalDisplayRotation());
 }
 
-// Tests that if a user sets a display rotation that accelerometer rotation
-// becomes locked.
-TEST_F(ScreenOrientationControllerTest,
-       NonAccelerometerRotationChangesLockRotation) {
-  EnableMaximizeMode(true);
-  ASSERT_FALSE(RotationLocked());
-  SetInternalDisplayRotation(display::Display::ROTATE_270);
-  EXPECT_TRUE(RotationLocked());
-}
-
 // Tests that if a user changes the display rotation, while rotation is locked,
 // that the updates are recorded. Upon exiting maximize mode the latest user
 // rotation should be applied.
@@ -621,33 +611,6 @@
   EXPECT_EQ(display::Display::ROTATE_0, GetCurrentInternalDisplayRotation());
 }
 
-// Tests that when MaximizeMode is triggered before the internal display is
-// ready, that ScreenOrientationController still begins listening to events,
-// which require an internal display to be acted upon.
-TEST_F(ScreenOrientationControllerTest, InternalDisplayNotAvailableAtStartup) {
-  display::test::DisplayManagerTestApi(display_manager())
-      .SetFirstDisplayAsInternalDisplay();
-
-  int64_t internal_display_id = display::Display::InternalDisplayId();
-  display::Display::SetInternalDisplayId(display::kInvalidDisplayId);
-
-  EnableMaximizeMode(true);
-
-  // Should not crash, even though there is no internal display.
-  SetDisplayRotationById(internal_display_id, display::Display::ROTATE_180);
-  EXPECT_FALSE(RotationLocked());
-
-  // Should not crash, even though the invalid display id is requested.
-  SetDisplayRotationById(display::kInvalidDisplayId,
-                         display::Display::ROTATE_180);
-  EXPECT_FALSE(RotationLocked());
-
-  // With an internal display now available, functionality should resume.
-  display::Display::SetInternalDisplayId(internal_display_id);
-  SetInternalDisplayRotation(display::Display::ROTATE_90);
-  EXPECT_TRUE(RotationLocked());
-}
-
 // Verifies rotating an inactive Display is successful.
 TEST_F(ScreenOrientationControllerTest, RotateInactiveDisplay) {
   const int64_t kInternalDisplayId = 9;
diff --git a/ash/devtools/ash_devtools_css_agent.h b/ash/devtools/ash_devtools_css_agent.h
deleted file mode 100644
index 9225475..0000000
--- a/ash/devtools/ash_devtools_css_agent.h
+++ /dev/null
@@ -1,57 +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 ASH_DEVTOOLS_ASH_DEVTOOLS_CSS_AGENT_H_
-#define ASH_DEVTOOLS_ASH_DEVTOOLS_CSS_AGENT_H_
-
-#include "ash/ash_export.h"
-#include "ash/devtools/ash_devtools_dom_agent.h"
-#include "base/macros.h"
-#include "components/ui_devtools/CSS.h"
-
-namespace ash {
-namespace devtools {
-
-class ASH_EXPORT AshDevToolsCSSAgent
-    : public NON_EXPORTED_BASE(ui::devtools::UiDevToolsBaseAgent<
-                               ui::devtools::protocol::CSS::Metainfo>),
-      public AshDevToolsDOMAgentObserver {
- public:
-  explicit AshDevToolsCSSAgent(AshDevToolsDOMAgent* dom_agent);
-  ~AshDevToolsCSSAgent() override;
-
-  // CSS::Backend:
-  ui::devtools::protocol::Response enable() override;
-  ui::devtools::protocol::Response disable() override;
-  ui::devtools::protocol::Response getMatchedStylesForNode(
-      int node_id,
-      ui::devtools::protocol::Maybe<ui::devtools::protocol::CSS::CSSStyle>*
-          inline_style) override;
-  ui::devtools::protocol::Response setStyleTexts(
-      std::unique_ptr<ui::devtools::protocol::Array<
-          ui::devtools::protocol::CSS::StyleDeclarationEdit>> edits,
-      std::unique_ptr<
-          ui::devtools::protocol::Array<ui::devtools::protocol::CSS::CSSStyle>>*
-          result) override;
-
-  // AshDevToolsDOMAgentObserver:
-  void OnNodeBoundsChanged(int node_id) override;
-
- private:
-  std::unique_ptr<ui::devtools::protocol::CSS::CSSStyle> GetStylesForNode(
-      int node_id);
-  void InvalidateStyleSheet(int node_id);
-  bool GetPropertiesForNodeId(int node_id, gfx::Rect* bounds, bool* visible);
-  bool SetPropertiesForNodeId(int node_id,
-                              const gfx::Rect& bounds,
-                              bool visible);
-  AshDevToolsDOMAgent* dom_agent_;
-
-  DISALLOW_COPY_AND_ASSIGN(AshDevToolsCSSAgent);
-};
-
-}  // namespace devtools
-}  // namespace ash
-
-#endif  // ASH_DEVTOOLS_ASH_DEVTOOLS_CSS_AGENT_H_
diff --git a/ash/devtools/ash_devtools_dom_agent.h b/ash/devtools/ash_devtools_dom_agent.h
deleted file mode 100644
index 8a171fe..0000000
--- a/ash/devtools/ash_devtools_dom_agent.h
+++ /dev/null
@@ -1,109 +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 ASH_DEVTOOLS_ASH_DEVTOOLS_DOM_AGENT_H_
-#define ASH_DEVTOOLS_ASH_DEVTOOLS_DOM_AGENT_H_
-
-#include "ash/ash_export.h"
-#include "ash/devtools/ui_element_delegate.h"
-#include "base/macros.h"
-#include "components/ui_devtools/DOM.h"
-#include "components/ui_devtools/devtools_base_agent.h"
-#include "ui/aura/env_observer.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace aura {
-class Window;
-}
-
-namespace ash {
-namespace devtools {
-
-class UIElement;
-
-class ASH_EXPORT AshDevToolsDOMAgentObserver {
- public:
-  // TODO(thanhph): Use UIElement* as input argument instead.
-  virtual void OnNodeBoundsChanged(int node_id) = 0;
-};
-
-class ASH_EXPORT AshDevToolsDOMAgent
-    : public NON_EXPORTED_BASE(ui::devtools::UiDevToolsBaseAgent<
-                               ui::devtools::protocol::DOM::Metainfo>),
-      public UIElementDelegate,
-      public aura::EnvObserver {
- public:
-  AshDevToolsDOMAgent();
-  ~AshDevToolsDOMAgent() override;
-
-  // DOM::Backend:
-  ui::devtools::protocol::Response disable() override;
-  ui::devtools::protocol::Response getDocument(
-      std::unique_ptr<ui::devtools::protocol::DOM::Node>* out_root) override;
-  ui::devtools::protocol::Response highlightNode(
-      std::unique_ptr<ui::devtools::protocol::DOM::HighlightConfig>
-          highlight_config,
-      ui::devtools::protocol::Maybe<int> node_id) override;
-  ui::devtools::protocol::Response hideHighlight() override;
-
-  // UIElementDelegate:
-  void OnUIElementAdded(UIElement* parent, UIElement* child) override;
-  void OnUIElementReordered(UIElement* parent, UIElement* child) override;
-  void OnUIElementRemoved(UIElement* ui_element) override;
-  void OnUIElementBoundsChanged(UIElement* ui_element) override;
-  bool IsHighlightingWindow(aura::Window* window) override;
-
-  void AddObserver(AshDevToolsDOMAgentObserver* observer);
-  void RemoveObserver(AshDevToolsDOMAgentObserver* observer);
-  UIElement* GetElementFromNodeId(int node_id);
-  UIElement* window_element_root() const { return window_element_root_.get(); };
-  const std::vector<aura::Window*>& root_windows() const {
-    return root_windows_;
-  };
-
- private:
-  // aura::EnvObserver:
-  void OnWindowInitialized(aura::Window* window) override {}
-  void OnHostInitialized(aura::WindowTreeHost* host) override;
-
-  void OnNodeBoundsChanged(int node_id);
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> BuildInitialTree();
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> BuildTreeForUIElement(
-      UIElement* ui_element);
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> BuildTreeForWindow(
-      UIElement* window_element_root,
-      aura::Window* window);
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> BuildTreeForRootWidget(
-      UIElement* widget_element,
-      views::Widget* widget);
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> BuildTreeForView(
-      UIElement* view_element,
-      views::View* view);
-  void RemoveDomNode(UIElement* ui_element);
-  void Reset();
-  void InitializeHighlightingWidget();
-  void UpdateHighlight(
-      const std::pair<aura::Window*, gfx::Rect>& window_and_bounds,
-      SkColor background,
-      SkColor border);
-  ui::devtools::protocol::Response HighlightNode(
-      std::unique_ptr<ui::devtools::protocol::DOM::HighlightConfig>
-          highlight_config,
-      int node_id);
-
-  bool is_building_tree_;
-  std::unique_ptr<UIElement> window_element_root_;
-  std::unordered_map<int, UIElement*> node_id_to_ui_element_;
-  std::unique_ptr<views::Widget> widget_for_highlighting_;
-  std::vector<aura::Window*> root_windows_;
-  base::ObserverList<AshDevToolsDOMAgentObserver> observers_;
-
-  DISALLOW_COPY_AND_ASSIGN(AshDevToolsDOMAgent);
-};
-
-}  // namespace devtools
-}  // namespace ash
-
-#endif  // ASH_DEVTOOLS_ASH_DEVTOOLS_DOM_AGENT_H_
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 924f214..8288bc8 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -1673,8 +1673,6 @@
 }
 
 TEST_F(DisplayManagerTest, UIScale) {
-  display::test::ScopedDisable125DSFForUIScaling disable;
-
   UpdateDisplay("1280x800");
   int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
   display::test::DisplayManagerTestApi(display_manager())
@@ -1785,17 +1783,6 @@
   display = display::Screen::GetScreen()->GetPrimaryDisplay();
   EXPECT_EQ(1.0f, display.device_scale_factor());
   EXPECT_EQ("1280x850", display.bounds().size().ToString());
-
-  // 1.25 ui scaling on 1.25 DSF device should use 1.0 DSF
-  // on screen.
-  UpdateDisplay("1280x850*1.25");
-  display::test::DisplayManagerTestApi(display_manager())
-      .SetDisplayUIScale(display_id, 1.25f);
-  EXPECT_EQ(1.25f, GetDisplayInfoAt(0).configured_ui_scale());
-  EXPECT_EQ(1.0f, GetDisplayInfoAt(0).GetEffectiveUIScale());
-  display = display::Screen::GetScreen()->GetPrimaryDisplay();
-  EXPECT_EQ(1.0f, display.device_scale_factor());
-  EXPECT_EQ("1280x850", display.bounds().size().ToString());
 }
 
 TEST_F(DisplayManagerTest, UIScaleWithDisplayMode) {
@@ -2796,16 +2783,6 @@
   EXPECT_NE(gfx::FontRenderParams::HINTING_NONE, GetFontHintingParams());
 }
 
-TEST_F(DisplayManagerFontTest, TextSubpixelPositioningWithDsf125Internal) {
-  display::test::ScopedDisable125DSFForUIScaling disable;
-  FontTestHelper helper(1.25f, FontTestHelper::INTERNAL);
-  ASSERT_DOUBLE_EQ(
-      1.25f,
-      display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor());
-  EXPECT_TRUE(IsTextSubpixelPositioningEnabled());
-  EXPECT_EQ(gfx::FontRenderParams::HINTING_NONE, GetFontHintingParams());
-}
-
 TEST_F(DisplayManagerFontTest, TextSubpixelPositioningWithDsf200Internal) {
   FontTestHelper helper(2.0f, FontTestHelper::INTERNAL);
   ASSERT_DOUBLE_EQ(
@@ -3213,4 +3190,26 @@
             test_api.GetCurrentOrientation());
 }
 
+// crbug.com/734107
+TEST_F(DisplayManagerOrientationTest, DisplayChangeShouldNotSaveUserRotation) {
+  Shell* shell = Shell::Get();
+  display::DisplayManager* display_manager = shell->display_manager();
+  display::test::DisplayManagerTestApi test_api(display_manager);
+  test_api.SetFirstDisplayAsInternalDisplay();
+  display::Screen* screen = display::Screen::GetScreen();
+
+  Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager(
+      true);
+  // Emulate that Animator is calling this async when animation is completed.
+  display_manager->SetDisplayRotation(
+      screen->GetPrimaryDisplay().id(), display::Display::ROTATE_90,
+      display::Display::ROTATION_SOURCE_ACCELEROMETER);
+  EXPECT_EQ(display::Display::ROTATE_90,
+            screen->GetPrimaryDisplay().rotation());
+
+  Shell::Get()->maximize_mode_controller()->EnableMaximizeModeWindowManager(
+      false);
+  EXPECT_EQ(display::Display::ROTATE_0, screen->GetPrimaryDisplay().rotation());
+}
+
 }  // namespace ash
diff --git a/ash/display/screen_orientation_controller_chromeos.cc b/ash/display/screen_orientation_controller_chromeos.cc
index 2c865f60..746ee41b 100644
--- a/ash/display/screen_orientation_controller_chromeos.cc
+++ b/ash/display/screen_orientation_controller_chromeos.cc
@@ -288,20 +288,17 @@
     return;
   if (!display::Display::HasInternalDisplay())
     return;
-  display::Display::Rotation user_rotation =
+  if (!Shell::Get()->display_manager()->IsActiveDisplayId(
+          display::Display::InternalDisplayId())) {
+    return;
+  }
+
+  // TODO(oshima): We should disable the orientation change in settings
+  // because application may not work correctly.
+  current_rotation_ =
       ShellPort::Get()
           ->GetDisplayInfo(display::Display::InternalDisplayId())
           .GetActiveRotation();
-  if (user_rotation != current_rotation_) {
-    // TODO(oshima): We should disable the orientation change in settings
-    // because application may not work correctly.
-
-    // A user may change other display configuration settings. When the user
-    // does change the rotation setting, then lock rotation to prevent the
-    // accelerometer from erasing their change.
-    SetRotationLockedInternal(true);
-    user_rotation_ = current_rotation_ = user_rotation;
-  }
 }
 
 void ScreenOrientationController::OnMaximizeModeStarted() {
diff --git a/ash/shell.cc b/ash/shell.cc
index f3f6048f..55ea0ce 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -20,8 +20,6 @@
 #include "ash/aura/shell_port_classic.h"
 #include "ash/autoclick/autoclick_controller.h"
 #include "ash/cast_config_controller.h"
-#include "ash/devtools/ash_devtools_css_agent.h"
-#include "ash/devtools/ash_devtools_dom_agent.h"
 #include "ash/display/ash_display_controller.h"
 #include "ash/display/cursor_window_controller.h"
 #include "ash/display/display_color_manager_chromeos.h"
@@ -133,6 +131,8 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/ui_devtools/devtools_server.h"
+#include "components/ui_devtools/views/ui_devtools_css_agent.h"
+#include "components/ui_devtools/views/ui_devtools_dom_agent.h"
 #include "services/preferences/public/cpp/pref_service_factory.h"
 #include "services/preferences/public/interfaces/preferences.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -856,12 +856,12 @@
   wallpaper_controller_ = base::MakeUnique<WallpaperController>();
 
   // Start devtools server
-  devtools_server_ = ui::devtools::UiDevToolsServer::Create(nullptr);
+  devtools_server_ = ui_devtools::UiDevToolsServer::Create(nullptr);
   if (devtools_server_) {
-    auto dom_backend = base::MakeUnique<devtools::AshDevToolsDOMAgent>();
+    auto dom_backend = base::MakeUnique<ui_devtools::UIDevToolsDOMAgent>();
     auto css_backend =
-        base::MakeUnique<devtools::AshDevToolsCSSAgent>(dom_backend.get());
-    auto devtools_client = base::MakeUnique<ui::devtools::UiDevToolsClient>(
+        base::MakeUnique<ui_devtools::UIDevToolsCSSAgent>(dom_backend.get());
+    auto devtools_client = base::MakeUnique<ui_devtools::UiDevToolsClient>(
         "Ash", devtools_server_.get());
     devtools_client->AddAgent(std::move(dom_backend));
     devtools_client->AddAgent(std::move(css_backend));
diff --git a/ash/shell.h b/ash/shell.h
index fa34265..020ad59 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -60,9 +60,10 @@
 namespace ui {
 class UserActivityDetector;
 class UserActivityPowerManagerNotifier;
-namespace devtools {
-class UiDevToolsServer;
 }
+
+namespace ui_devtools {
+class UiDevToolsServer;
 }
 
 namespace views {
@@ -718,7 +719,7 @@
   std::unique_ptr<::wm::WindowModalityController> window_modality_controller_;
   std::unique_ptr<app_list::AppList> app_list_;
   std::unique_ptr<::PrefService> pref_service_;
-  std::unique_ptr<ui::devtools::UiDevToolsServer> devtools_server_;
+  std::unique_ptr<ui_devtools::UiDevToolsServer> devtools_server_;
   std::unique_ptr<views::corewm::TooltipController> tooltip_controller_;
   LinkHandlerModelFactory* link_handler_model_factory_;
   std::unique_ptr<PowerButtonController> power_button_controller_;
diff --git a/base/files/file_enumerator_posix.cc b/base/files/file_enumerator_posix.cc
index 2b54c6d..fbd40e09 100644
--- a/base/files/file_enumerator_posix.cc
+++ b/base/files/file_enumerator_posix.cc
@@ -125,16 +125,8 @@
   if (!dir)
     return false;
 
-#if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_BSD) &&    \
-    !defined(OS_SOLARIS) && !defined(OS_ANDROID) && !defined(OS_AIX) && \
-    !defined(OS_FUCHSIA)
-#error Port warning: depending on the definition of struct dirent, \
-         additional space for pathname may be needed
-#endif
-
-  struct dirent dent_buf;
   struct dirent* dent;
-  while (readdir_r(dir, &dent_buf, &dent) == 0 && dent) {
+  while ((dent = readdir(dir))) {
     FileInfo info;
     info.filename_ = FilePath(dent->d_name);
 
diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc
index e5afedb..a0ef589d 100644
--- a/base/files/important_file_writer_unittest.cc
+++ b/base/files/important_file_writer_unittest.cc
@@ -335,7 +335,7 @@
   histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError", 0);
   histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError.test", 0);
 
-  FilePath invalid_file_ = FilePath().AppendASCII("bad/../path");
+  FilePath invalid_file_ = FilePath().AppendASCII("bad/../non_existent/path");
   EXPECT_FALSE(PathExists(invalid_file_));
   EXPECT_FALSE(
       ImportantFileWriter::WriteFileAtomically(invalid_file_, nullptr));
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 9dbf663..68c6717 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -172,10 +172,8 @@
     return kHeapProfilingModePseudo;
   if (profiling_mode == switches::kEnableHeapProfilingModeNative)
     return kHeapProfilingModeNative;
-  if (profiling_mode == switches::kEnableHeapProfilingTaskProfiler &&
-      base::debug::ThreadHeapUsageTracker::IsHeapTrackingEnabled()) {
+  if (profiling_mode == switches::kEnableHeapProfilingTaskProfiler)
     return kHeapProfilingModeTaskProfiler;
-  }
 #endif  // BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
   return kHeapProfilingModeInvalid;
 }
@@ -200,7 +198,8 @@
           AllocationContextTracker::CaptureMode::NATIVE_STACK);
       break;
     case kHeapProfilingModeTaskProfiler:
-      base::debug::ThreadHeapUsageTracker::EnableHeapTracking();
+      if (!base::debug::ThreadHeapUsageTracker::IsHeapTrackingEnabled())
+        base::debug::ThreadHeapUsageTracker::EnableHeapTracking();
       break;
   }
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index fdc06eb..7024bd3 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1678,12 +1678,6 @@
     ]
   }
 
-  java_cpp_enum("credit_card_javagen") {
-    sources = [
-      "../components/autofill/core/browser/credit_card.h",
-    ]
-  }
-
   java_cpp_enum("signin_metrics_enum_javagen") {
     sources = [
       "../components/signin/core/browser/signin_metrics.h",
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 6690f82..f1f0836 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -250,7 +250,6 @@
     ":resource_id_javagen",
     "//chrome:content_setting_javagen",
     "//chrome:content_settings_type_javagen",
-    "//chrome:credit_card_javagen",
     "//chrome:data_use_ui_message_enum_javagen",
     "//chrome:offline_pages_enum_javagen",
     "//chrome:page_info_connection_type_javagen",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
index 1e44667..62ce02e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java
@@ -352,9 +352,7 @@
      */
     public static class CreditCard {
         // Note that while some of these fields are numbers, they're predominantly read,
-        // marshaled and compared as strings. To save conversions, we sometimes use strings.
-        @CardType
-        private final int mCardType;
+        // marshaled and compared as strings. To save conversions, we use strings everywhere.
         private String mGUID;
         private String mOrigin;
         private boolean mIsLocal;
@@ -373,17 +371,16 @@
         public static CreditCard create(String guid, String origin, boolean isLocal,
                 boolean isCached, String name, String number, String obfuscatedNumber, String month,
                 String year, String basicCardIssuerNetwork, int enumeratedIconId,
-                @CardType int cardType, String billingAddressId, String serverId) {
+                String billingAddressId, String serverId) {
             return new CreditCard(guid, origin, isLocal, isCached, name, number, obfuscatedNumber,
                     month, year, basicCardIssuerNetwork,
-                    ResourceId.mapToDrawableId(enumeratedIconId), cardType, billingAddressId,
-                    serverId);
+                    ResourceId.mapToDrawableId(enumeratedIconId), billingAddressId, serverId);
         }
 
         public CreditCard(String guid, String origin, boolean isLocal, boolean isCached,
                 String name, String number, String obfuscatedNumber, String month, String year,
-                String basicCardIssuerNetwork, int issuerIconDrawableId, @CardType int cardType,
-                String billingAddressId, String serverId) {
+                String basicCardIssuerNetwork, int issuerIconDrawableId, String billingAddressId,
+                String serverId) {
             mGUID = guid;
             mOrigin = origin;
             mIsLocal = isLocal;
@@ -395,7 +392,6 @@
             mYear = year;
             mBasicCardIssuerNetwork = basicCardIssuerNetwork;
             mIssuerIconDrawableId = issuerIconDrawableId;
-            mCardType = cardType;
             mBillingAddressId = billingAddressId;
             mServerId = serverId;
         }
@@ -404,7 +400,7 @@
             this("" /* guid */, AutofillAndPaymentsPreferences.SETTINGS_ORIGIN /*origin */,
                     true /* isLocal */, false /* isCached */, "" /* name */, "" /* number */,
                     "" /* obfuscatedNumber */, "" /* month */, "" /* year */,
-                    "" /* basicCardIssuerNetwork */, 0 /* issuerIconDrawableId */, CardType.UNKNOWN,
+                    "" /* basicCardIssuerNetwork */, 0 /* issuerIconDrawableId */,
                     "" /* billingAddressId */, "" /* serverId */);
         }
 
@@ -414,8 +410,7 @@
                 String obfuscatedNumber, String month, String year) {
             this(guid, origin, true /* isLocal */, false /* isCached */, name, number,
                     obfuscatedNumber, month, year, "" /* basicCardIssuerNetwork */,
-                    0 /* issuerIconDrawableId */, CardType.UNKNOWN, "" /* billingAddressId */,
-                    "" /* serverId */);
+                    0 /* issuerIconDrawableId */, "" /* billingAddressId */, "" /* serverId */);
         }
 
         @CalledByNative("CreditCard")
@@ -477,12 +472,6 @@
             return mIssuerIconDrawableId;
         }
 
-        @CardType
-        @CalledByNative("CreditCard")
-        public int getCardType() {
-            return mCardType;
-        }
-
         @CalledByNative("CreditCard")
         public String getBillingAddressId() {
             return mBillingAddressId;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
index a3711c7..c8e3624 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
@@ -132,6 +132,13 @@
         return mView;
     }
 
+    /**
+     * Returns the accessibility message from the view to announce when this infobar is first shown.
+     */
+    protected CharSequence getAccessibilityMessage(TextView messageView) {
+        return messageView.getText();
+    }
+
     @Override
     public CharSequence getAccessibilityText() {
         if (mView == null) return "";
@@ -141,7 +148,8 @@
         if (usesCompactLayout()) return mContext.getString(R.string.bottom_bar_screen_position);
         TextView messageView = (TextView) mView.findViewById(R.id.infobar_message);
         if (messageView == null) return "";
-        return messageView.getText() + mContext.getString(R.string.bottom_bar_screen_position);
+        return getAccessibilityMessage(messageView)
+                + mContext.getString(R.string.bottom_bar_screen_position);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
index 4c07d2a..55a299a82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
@@ -4,7 +4,10 @@
 
 package org.chromium.chrome.browser.infobar;
 
+import android.widget.TextView;
+
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ResourceId;
 
 /**
@@ -28,6 +31,11 @@
     }
 
     @Override
+    protected CharSequence getAccessibilityMessage(TextView messageView) {
+        return getContext().getString(R.string.previews_infobar_accessibility_title);
+    }
+
+    @Override
     public void createContent(InfoBarLayout layout) {
         super.createContent(layout);
         if (mTimestampText.isEmpty()) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
index 2f7049c..630e4c9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentApp.java
@@ -574,9 +574,4 @@
 
     @Override
     public void dismissInstrument() {}
-
-    @Override
-    public int getAdditionalAppTextResourceId() {
-        return 0;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
index 643b3a8..6b769b43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentApp.java
@@ -7,14 +7,11 @@
 import android.os.Handler;
 import android.text.TextUtils;
 
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.BasicCardNetwork;
-import org.chromium.payments.mojom.BasicCardType;
 import org.chromium.payments.mojom.PaymentItem;
 import org.chromium.payments.mojom.PaymentMethodData;
 
@@ -32,11 +29,7 @@
     /** The method name for any type of credit card. */
     public static final String BASIC_CARD_METHOD_NAME = "basic-card";
 
-    /** The total number of all possible card types (i.e., credit, debit, prepaid, unknown). */
-    private static final int TOTAL_NUMBER_OF_CARD_TYPES = 4;
-
     private final WebContents mWebContents;
-    private Set<Integer> mBasicCardTypes;
 
     /**
      * Builds a payment app backed by autofill cards.
@@ -57,13 +50,11 @@
 
         Set<String> basicCardSupportedNetworks =
                 convertBasicCardToNetworks(methodDataMap.get(BASIC_CARD_METHOD_NAME));
-        mBasicCardTypes = convertBasicCardToTypes(methodDataMap.get(BASIC_CARD_METHOD_NAME));
 
         for (int i = 0; i < cards.size(); i++) {
             CreditCard card = cards.get(i);
             AutofillProfile billingAddress = TextUtils.isEmpty(card.getBillingAddressId())
-                    ? null
-                    : pdm.getProfile(card.getBillingAddressId());
+                    ? null : pdm.getProfile(card.getBillingAddressId());
 
             if (billingAddress != null
                     && AutofillAddress.checkAddressCompletionStatus(
@@ -82,18 +73,9 @@
                 methodName = card.getBasicCardIssuerNetwork();
             }
 
-            if (methodName != null && mBasicCardTypes.contains(card.getCardType())) {
-                // Whether this card matches the card type (credit, debit, prepaid) exactly. If the
-                // merchant requests all card types, then this is always true. If the merchant
-                // requests only a subset of card types, then this is false for "unknown" card
-                // types. The "unknown" card types is where Chrome is unable to determine the type
-                // of card. Cards that don't match the card type exactly cannot be pre-selected in
-                // the UI.
-                boolean matchesMerchantCardTypeExactly = card.getCardType() != CardType.UNKNOWN
-                        || mBasicCardTypes.size() == TOTAL_NUMBER_OF_CARD_TYPES;
-
-                instruments.add(new AutofillPaymentInstrument(mWebContents, card, billingAddress,
-                        methodName, matchesMerchantCardTypeExactly));
+            if (methodName != null) {
+                instruments.add(new AutofillPaymentInstrument(
+                        mWebContents, card, billingAddress, methodName));
             }
         }
 
@@ -125,29 +107,6 @@
         return result;
     }
 
-    /**
-     * @return A set of card types (e.g., CardType.DEBIT, CardType.PREPAID)
-     * accepted by "basic-card" method.
-     */
-    public static Set<Integer> convertBasicCardToTypes(PaymentMethodData data) {
-        Set<Integer> result = new HashSet<>();
-        result.add(CardType.UNKNOWN);
-
-        Map<Integer, Integer> cardTypes = getCardTypes();
-        if (data == null || data.supportedTypes == null || data.supportedTypes.length == 0) {
-            // Merchant website supports all card types.
-            result.addAll(cardTypes.values());
-        } else {
-            // Merchant website supports some card types.
-            for (int i = 0; i < data.supportedTypes.length; i++) {
-                Integer cardType = cardTypes.get(data.supportedTypes[i]);
-                if (cardType != null) result.add(cardType);
-            }
-        }
-
-        return result;
-    }
-
     private static Map<Integer, String> getNetworks() {
         Map<Integer, String> networks = new HashMap<>();
         networks.put(BasicCardNetwork.AMEX, "amex");
@@ -161,14 +120,6 @@
         return networks;
     }
 
-    private static Map<Integer, Integer> getCardTypes() {
-        Map<Integer, Integer> cardTypes = new HashMap<>();
-        cardTypes.put(BasicCardType.CREDIT, CardType.CREDIT);
-        cardTypes.put(BasicCardType.DEBIT, CardType.DEBIT);
-        cardTypes.put(BasicCardType.PREPAID, CardType.PREPAID);
-        return cardTypes;
-    }
-
     @Override
     public Set<String> getAppMethodNames() {
         Set<String> methods = new HashSet<>(getNetworks().values());
@@ -200,28 +151,4 @@
     public String getAppIdentifier() {
         return "Chrome_Autofill_Payment_App";
     }
-
-    @Override
-    public int getAdditionalAppTextResourceId() {
-        // If the merchant has restricted the accepted card types (credit, debit, prepaid), then the
-        // list of payment instruments should include a message describing the accepted card types,
-        // e.g., "Debit cards are accepted" or "Debit and prepaid cards are accepted."
-        if (mBasicCardTypes == null || mBasicCardTypes.size() == TOTAL_NUMBER_OF_CARD_TYPES) {
-            return 0;
-        }
-
-        int credit = mBasicCardTypes.contains(CardType.CREDIT) ? 1 : 0;
-        int debit = mBasicCardTypes.contains(CardType.DEBIT) ? 1 : 0;
-        int prepaid = mBasicCardTypes.contains(CardType.PREPAID) ? 1 : 0;
-        int[][][] resourceIds = new int[2][2][2];
-        resourceIds[0][0][0] = 0;
-        resourceIds[0][0][1] = R.string.payments_prepaid_cards_are_accepted_label;
-        resourceIds[0][1][0] = R.string.payments_debit_cards_are_accepted_label;
-        resourceIds[0][1][1] = R.string.payments_debit_prepaid_cards_are_accepted_label;
-        resourceIds[1][0][0] = R.string.payments_credit_cards_are_accepted_label;
-        resourceIds[1][0][1] = R.string.payments_credit_prepaid_cards_are_accepted_label;
-        resourceIds[1][1][0] = R.string.payments_credit_debit_cards_are_accepted_label;
-        resourceIds[1][1][1] = 0;
-        return resourceIds[credit][debit][prepaid];
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
index 94465d53..80d6156 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillPaymentInstrument.java
@@ -36,7 +36,6 @@
 public class AutofillPaymentInstrument extends PaymentInstrument
         implements FullCardRequestDelegate, NormalizedAddressRequestDelegate {
     private final WebContents mWebContents;
-    private final boolean mIsMatchingMerchantsRequestedCardType;
     private CreditCard mCard;
     private String mSecurityCode;
     @Nullable private AutofillProfile mBillingAddress;
@@ -49,26 +48,19 @@
     /**
      * Builds a payment instrument for the given credit card.
      *
-     * @param webContents                    The web contents where PaymentRequest was invoked.
-     * @param card                           The autofill card that can be used for payment.
-     * @param billingAddress                 The billing address for the card.
-     * @param methodName                     The payment method name, e.g., "basic-card", "visa",
-     *                                       amex", or null.
-     * @param matchesMerchantCardTypeExactly Whether the card type (credit, debit, prepaid) matches
-     *                                       the type that the merchant has requested exactly. This
-     *                                       should be false for unknown card types, if the merchant
-     *                                       cannot accept some card types.
+     * @param webContents    The web contents where PaymentRequest was invoked.
+     * @param card           The autofill card that can be used for payment.
+     * @param billingAddress The billing address for the card.
+     * @param methodName     The payment method name, e.g., "basic-card", "visa", amex", or null.
      */
     public AutofillPaymentInstrument(WebContents webContents, CreditCard card,
-            @Nullable AutofillProfile billingAddress, @Nullable String methodName,
-            boolean matchesMerchantCardTypeExactly) {
+            @Nullable AutofillProfile billingAddress, @Nullable String methodName) {
         super(card.getGUID(), card.getObfuscatedNumber(), card.getName(), null);
         mWebContents = webContents;
         mCard = card;
         mBillingAddress = billingAddress;
         mIsEditable = true;
         mMethodName = methodName;
-        mIsMatchingMerchantsRequestedCardType = matchesMerchantCardTypeExactly;
 
         Context context = ChromeActivity.fromWebContents(mWebContents);
         if (context == null) return;
@@ -99,27 +91,6 @@
     }
 
     @Override
-    public boolean isExactlyMatchingMerchantRequest() {
-        return mIsMatchingMerchantsRequestedCardType;
-    }
-
-    @Override
-    @Nullable
-    public String getCountryCode() {
-        return AutofillAddress.getCountryCode(mBillingAddress);
-    }
-
-    @Override
-    public boolean canMakePayment() {
-        return mHasValidNumberAndName; // Ignore absence of billing address.
-    }
-
-    @Override
-    public boolean canPreselect() {
-        return mIsComplete && mIsMatchingMerchantsRequestedCardType;
-    }
-
-    @Override
     public void invokePaymentApp(String unusedRequestId, String unusedMerchantName,
             String unusedOrigin, String unusedIFrameOrigin, byte[][] unusedCertificateChain,
             Map<String, PaymentMethodData> unusedMethodDataMap, PaymentItem unusedTotal,
@@ -263,6 +234,14 @@
     }
 
     /**
+     * @return Whether the card number is valid and name on card is non-empty. Billing address is
+     * not taken into consideration.
+     */
+    public boolean isValidCard() {
+        return mHasValidNumberAndName;
+    }
+
+    /**
      * Updates the instrument and marks it "complete." Called after the user has edited this
      * instrument.
      *
@@ -359,6 +338,11 @@
         return mCard;
     }
 
+    /** @return The billing address associated with this credit card. */
+    public AutofillProfile getBillingAddress() {
+        return mBillingAddress;
+    }
+
     @Override
     public String getPreviewString(String labelSeparator, int maxLength) {
         StringBuilder previewString = new StringBuilder(getLabel());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
index 8546d4fa..281c0fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -15,7 +15,6 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.CreditCardScanner;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
@@ -90,7 +89,7 @@
     /** The dropdown key that triggers the address editor to add a new billing address. */
     private static final String BILLING_ADDRESS_ADD_NEW = "add";
 
-    /** The shared preference for the 'save card to device' checkbox status. */
+    /** The shared preference for the 'save card to device' checkbox status*/
     private static final String CHECK_SAVE_CARD_TO_DEVICE = "check_save_card_to_device";
 
     /** The web contents where the web payments API is invoked. */
@@ -133,11 +132,6 @@
     private final Set<String> mAcceptedBasicCardIssuerNetworks;
 
     /**
-     * The accepted card types: CardType.UNKNOWN, CardType.CREDIT, CardType.DEBIT, CardType.PREPAID.
-     */
-    private final Set<Integer> mAcceptedBasicCardTypes;
-
-    /**
      * The information about the accepted card issuer networks. Used in the editor as a hint to the
      * user about the valid card issuer networks. This is important to keep in a list, because the
      * display order matters.
@@ -235,7 +229,6 @@
 
         mAcceptedIssuerNetworks = new HashSet<>();
         mAcceptedBasicCardIssuerNetworks = new HashSet<>();
-        mAcceptedBasicCardTypes = new HashSet<>();
         mAcceptedCardIssuerNetworks = new ArrayList<>();
         mHandler = new Handler();
 
@@ -320,8 +313,6 @@
                         addAcceptedNetwork(network);
                     }
                 }
-
-                mAcceptedBasicCardTypes.addAll(AutofillPaymentApp.convertBasicCardToTypes(data));
             }
         }
     }
@@ -365,8 +356,7 @@
         // Ensure that |instrument| and |card| are never null.
         final AutofillPaymentInstrument instrument = isNewCard
                 ? new AutofillPaymentInstrument(mWebContents, new CreditCard(),
-                          null /* billingAddress */, null /* methodName */,
-                          false /* matchesMerchantCardTypeExactly */)
+                          null /* billingAddress */, null /* methodName */)
                 : toEdit;
         final CreditCard card = instrument.getCard();
 
@@ -480,7 +470,8 @@
                 descriptions.add(mAcceptedCardIssuerNetworks.get(i).description);
             }
             mIconHint = EditorFieldModel.createIconList(
-                    mContext.getString(getAcceptedCardsLabelResourceId()), icons, descriptions);
+                    mContext.getString(R.string.payments_accepted_cards_label), icons,
+                    descriptions);
         }
         editor.addField(mIconHint);
 
@@ -590,22 +581,6 @@
         editor.addField(mYearField);
     }
 
-    private int getAcceptedCardsLabelResourceId() {
-        int credit = mAcceptedBasicCardTypes.contains(CardType.CREDIT) ? 1 : 0;
-        int debit = mAcceptedBasicCardTypes.contains(CardType.DEBIT) ? 1 : 0;
-        int prepaid = mAcceptedBasicCardTypes.contains(CardType.PREPAID) ? 1 : 0;
-        int[][][] resourceIds = new int[2][2][2];
-        resourceIds[0][0][0] = R.string.payments_accepted_cards_label;
-        resourceIds[0][0][1] = R.string.payments_accepted_prepaid_cards_label;
-        resourceIds[0][1][0] = R.string.payments_accepted_debit_cards_label;
-        resourceIds[0][1][1] = R.string.payments_accepted_debit_prepaid_cards_label;
-        resourceIds[1][0][0] = R.string.payments_accepted_credit_cards_label;
-        resourceIds[1][0][1] = R.string.payments_accepted_credit_prepaid_cards_label;
-        resourceIds[1][1][0] = R.string.payments_accepted_credit_debit_cards_label;
-        resourceIds[1][1][1] = R.string.payments_accepted_cards_label;
-        return resourceIds[credit][debit][prepaid];
-    }
-
     /** Builds the key-value pairs for the month dropdown. */
     private static List<DropdownKeyValue> buildMonthDropdownKeyValues(Calendar calendar) {
         List<DropdownKeyValue> result = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java
index f7c3c8d..8f729cf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentApp.java
@@ -79,10 +79,4 @@
      * @return The identifier for this payment app.
      */
     String getAppIdentifier();
-
-    /**
-     * @return The resource identifier for the additional text that should be displayed to the user
-     * when selecting a payment instrument from this payment app or 0 if not needed.
-     */
-    int getAdditionalAppTextResourceId();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java
index df6d3546..de4c93b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java
@@ -91,34 +91,6 @@
     }
 
     /**
-     * @return Whether the instrument is exactly matching all filters provided by the merchant. For
-     * example, this can return false for unknown card types, if the merchant requested only debit
-     * cards.
-     */
-    public boolean isExactlyMatchingMerchantRequest() {
-        return true;
-    }
-
-    /** @return The country code (or null if none) associated with this payment instrument. */
-    @Nullable
-    public String getCountryCode() {
-        return null;
-    }
-
-    /**
-     * @return Whether presence of this payment instrument should cause the
-     * PaymentRequest.canMakePayment() to return true.
-     */
-    public boolean canMakePayment() {
-        return true;
-    }
-
-    /** @return Whether this payment instrument can be pre-selected for immediate payment. */
-    public boolean canPreselect() {
-        return true;
-    }
-
-    /**
      * Invoke the payment app to retrieve the instrument details.
      *
      * The callback will be invoked with the resulting payment details or error.
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 d62de3bf..8803762 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
@@ -180,7 +180,7 @@
         public void addObserver(PaymentRequestImpl observer) {
             mObservers.add(observer);
         }
-    }
+    };
 
     /** Limit in the number of suggested items in a section. */
     public static final int SUGGESTIONS_LIMIT = 4;
@@ -197,32 +197,22 @@
             };
 
     /**
-     * Sorts the payment instruments by several rules:
-     * Rule 1: Non-autofill before autofill.
-     * Rule 2: Complete instruments before incomplete intsruments.
-     * Rule 3: Exact type matching instruments before non-exact type matching instruments.
-     * Rule 4: Frequently and recently used instruments before rarely and non-recently used
-     *         instruments.
+     * Comparator to sort payment apps by maximum frecency score of the contained instruments. Note
+     * that the first instrument in the list must have the maximum frecency score.
      */
-    private static final Comparator<PaymentInstrument> PAYMENT_INSTRUMENT_COMPARATOR =
+    private static final Comparator<List<PaymentInstrument>> APP_FRECENCY_COMPARATOR =
+            new Comparator<List<PaymentInstrument>>() {
+                @Override
+                public int compare(List<PaymentInstrument> a, List<PaymentInstrument> b) {
+                    return compareInstrumentsByFrecency(b.get(0), a.get(0));
+                }
+            };
+
+    /** Comparator to sort instruments in payment apps by frecency. */
+    private static final Comparator<PaymentInstrument> INSTRUMENT_FRECENCY_COMPARATOR =
             new Comparator<PaymentInstrument>() {
                 @Override
                 public int compare(PaymentInstrument a, PaymentInstrument b) {
-                    // Payment apps (not autofill) first.
-                    int autofill =
-                            (a.isAutofillInstrument() ? 1 : 0) - (b.isAutofillInstrument() ? 1 : 0);
-                    if (autofill != 0) return autofill;
-
-                    // Complete cards before cards with missing information.
-                    int completeness = (b.isComplete() ? 1 : 0) - (a.isComplete() ? 1 : 0);
-                    if (completeness != 0) return completeness;
-
-                    // Cards with matching type before unknown type cards.
-                    int typeMatch = (b.isExactlyMatchingMerchantRequest() ? 1 : 0)
-                            - (a.isExactlyMatchingMerchantRequest() ? 1 : 0);
-                    if (typeMatch != 0) return typeMatch;
-
-                    // More frequently and recently used instruments first.
                     return compareInstrumentsByFrecency(b, a);
                 }
             };
@@ -321,8 +311,8 @@
     private ContactDetailsSection mContactSection;
     private List<PaymentApp> mApps;
     private List<PaymentApp> mPendingApps;
-    private List<PaymentInstrument> mPendingInstruments;
-    private int mPaymentMethodsSectionAdditionalTextResourceId;
+    private List<List<PaymentInstrument>> mPendingInstruments;
+    private List<PaymentInstrument> mPendingAutofillInstruments;
     private SectionInformation mPaymentMethodsSection;
     private PaymentRequestUI mUI;
     private Callback<PaymentInformation> mPaymentInformationCallback;
@@ -493,8 +483,7 @@
         mShouldSkipShowingPaymentRequestUi =
                 ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_SINGLE_APP_UI_SKIP)
                 && mMethodData.size() == 1 && !mRequestShipping && !mRequestPayerName
-                && !mRequestPayerPhone
-                && !mRequestPayerEmail
+                && !mRequestPayerPhone && !mRequestPayerEmail
                 // Only allowing payment apps that own their own UIs.
                 // This excludes AutofillPaymentApp as its UI is rendered inline in
                 // the payment request UI, thus can't be skipped.
@@ -703,12 +692,13 @@
 
         mPendingApps = new ArrayList<>(mApps);
         mPendingInstruments = new ArrayList<>();
+        mPendingAutofillInstruments = new ArrayList<>();
 
         Map<PaymentApp, Map<String, PaymentMethodData>> queryApps = new ArrayMap<>();
         for (int i = 0; i < mApps.size(); i++) {
             PaymentApp app = mApps.get(i);
-            Map<String, PaymentMethodData> appMethods =
-                    filterMerchantMethodData(mMethodData, app.getAppMethodNames());
+            Map<String, PaymentMethodData> appMethods = filterMerchantMethodData(mMethodData,
+                    app.getAppMethodNames());
             if (appMethods == null || !app.supportsMethodsAndData(appMethods)) {
                 mPendingApps.remove(app);
             } else {
@@ -861,8 +851,7 @@
     }
 
     /** @return The first modifier that matches the given instrument, or null. */
-    @Nullable
-    private PaymentDetailsModifier getModifier(@Nullable PaymentInstrument instrument) {
+    @Nullable private PaymentDetailsModifier getModifier(@Nullable PaymentInstrument instrument) {
         if (mModifiers == null || instrument == null) return null;
         // Makes a copy to ensure it is modifiable.
         Set<String> methodNames = new HashSet<>(instrument.getInstrumentMethodNames());
@@ -873,7 +862,7 @@
     /**
      * Converts a list of payment items and returns their parsed representation.
      *
-     * @param items The payment items to parse. Can be null.
+     * @param items     The payment items to parse. Can be null.
      * @return A list of valid line items.
      */
     private List<LineItem> getLineItems(@Nullable PaymentItem[] items) {
@@ -895,7 +884,7 @@
     /**
      * Converts a list of shipping options and returns their parsed representation.
      *
-     * @param options The raw shipping options to parse. Can be null.
+     * @param options   The raw shipping options to parse. Can be null.
      * @return The UI representation of the shipping options.
      */
     private SectionInformation getShippingOptions(@Nullable PaymentShippingOption[] options) {
@@ -1277,8 +1266,8 @@
         PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod;
         mPaymentAppRunning = true;
 
-        PaymentOption selectedContact =
-                mContactSection != null ? mContactSection.getSelectedItem() : null;
+        PaymentOption selectedContact = mContactSection != null ? mContactSection.getSelectedItem()
+                : null;
         mPaymentResponseHelper = new PaymentResponseHelper(
                 selectedShippingAddress, selectedShippingOption, selectedContact, this);
 
@@ -1488,28 +1477,31 @@
         if (mClient == null) return;
         mPendingApps.remove(app);
 
+        // Place the instruments into either "autofill" or "non-autofill" list to be displayed when
+        // all apps have responded.
         if (instruments != null) {
+            List<PaymentInstrument> nonAutofillInstruments = new ArrayList<>();
             for (int i = 0; i < instruments.size(); i++) {
                 PaymentInstrument instrument = instruments.get(i);
-                Set<String> instrumentMethodNames =
-                        new HashSet<>(instrument.getInstrumentMethodNames());
+                Set<String> instrumentMethodNames = new HashSet<>(
+                        instrument.getInstrumentMethodNames());
                 instrumentMethodNames.retainAll(mMethodData.keySet());
                 if (!instrumentMethodNames.isEmpty()) {
                     mHideServerAutofillInstruments |=
                             instrument.isServerAutofillInstrumentReplacement();
-                    mCanMakePayment |= instrument.canMakePayment();
-                    mPendingInstruments.add(instrument);
+                    if (instrument.isAutofillInstrument()) {
+                        mPendingAutofillInstruments.add(instrument);
+                    } else {
+                        nonAutofillInstruments.add(instrument);
+                    }
                 } else {
                     instrument.dismissInstrument();
                 }
             }
-        }
-
-        int additionalTextResourceId = app.getAdditionalAppTextResourceId();
-        if (additionalTextResourceId != 0) {
-            assert mPaymentMethodsSectionAdditionalTextResourceId == 0;
-            assert app instanceof AutofillPaymentApp;
-            mPaymentMethodsSectionAdditionalTextResourceId = additionalTextResourceId;
+            if (!nonAutofillInstruments.isEmpty()) {
+                Collections.sort(nonAutofillInstruments, INSTRUMENT_FRECENCY_COMPARATOR);
+                mPendingInstruments.add(nonAutofillInstruments);
+            }
         }
 
         // Some payment apps still have not responded. Continue waiting for them.
@@ -1518,41 +1510,61 @@
         if (disconnectIfNoPaymentMethodsSupported()) return;
 
         if (mHideServerAutofillInstruments) {
-            List<PaymentInstrument> nonServerAutofillInstruments = new ArrayList<>();
-            for (int i = 0; i < mPendingInstruments.size(); i++) {
-                if (!mPendingInstruments.get(i).isServerAutofillInstrument()) {
-                    nonServerAutofillInstruments.add(mPendingInstruments.get(i));
+            List<PaymentInstrument> localAutofillInstruments = new ArrayList<>();
+            for (int i = 0; i < mPendingAutofillInstruments.size(); i++) {
+                if (!mPendingAutofillInstruments.get(i).isServerAutofillInstrument()) {
+                    localAutofillInstruments.add(mPendingAutofillInstruments.get(i));
                 }
             }
-            mPendingInstruments = nonServerAutofillInstruments;
+            mPendingAutofillInstruments = localAutofillInstruments;
         }
 
         // Load the validation rules for each unique region code in the credit card billing
         // addresses and check for validity.
         Set<String> uniqueCountryCodes = new HashSet<>();
-        for (int i = 0; i < mPendingInstruments.size(); ++i) {
-            @Nullable
-            String countryCode = mPendingInstruments.get(i).getCountryCode();
-            if (countryCode != null && !uniqueCountryCodes.contains(countryCode)) {
+        for (int i = 0; i < mPendingAutofillInstruments.size(); ++i) {
+            assert mPendingAutofillInstruments.get(i) instanceof AutofillPaymentInstrument;
+            AutofillPaymentInstrument creditCard =
+                    (AutofillPaymentInstrument) mPendingAutofillInstruments.get(i);
+
+            String countryCode = AutofillAddress.getCountryCode(creditCard.getBillingAddress());
+            if (!uniqueCountryCodes.contains(countryCode)) {
                 uniqueCountryCodes.add(countryCode);
                 PersonalDataManager.getInstance().loadRulesForAddressNormalization(countryCode);
             }
+
+            // If there's a card on file with a valid number and a name, then
+            // PaymentRequest.canMakePayment() returns true.
+            mCanMakePayment |= creditCard.isValidCard();
         }
 
-        Collections.sort(mPendingInstruments, PAYMENT_INSTRUMENT_COMPARATOR);
+        // List order:
+        // > Non-autofill instruments.
+        // > Complete autofill instruments.
+        // > Incomplete autofill instruments.
+        Collections.sort(mPendingAutofillInstruments, COMPLETENESS_COMPARATOR);
+        Collections.sort(mPendingInstruments, APP_FRECENCY_COMPARATOR);
+        if (!mPendingAutofillInstruments.isEmpty()) {
+            mPendingInstruments.add(mPendingAutofillInstruments);
+        }
 
         // Log the number of suggested credit cards.
-        int numberOfAutofillInstruments = 0;
-        for (int i = 0; i < mPendingInstruments.size(); i++) {
-            if (mPendingInstruments.get(i).isAutofillInstrument()) numberOfAutofillInstruments++;
-        }
         mJourneyLogger.setNumberOfSuggestionsShown(
-                Section.CREDIT_CARDS, numberOfAutofillInstruments);
+                Section.CREDIT_CARDS, mPendingAutofillInstruments.size());
 
         // Possibly pre-select the first instrument on the list.
-        int selection = !mPendingInstruments.isEmpty() && mPendingInstruments.get(0).canPreselect()
-                ? 0
-                : SectionInformation.NO_SELECTION;
+        int selection = SectionInformation.NO_SELECTION;
+        if (!mPendingInstruments.isEmpty()) {
+            PaymentInstrument first = mPendingInstruments.get(0).get(0);
+            if (first instanceof AutofillPaymentInstrument) {
+                AutofillPaymentInstrument creditCard = (AutofillPaymentInstrument) first;
+                if (creditCard.isComplete()) selection = 0;
+            } else {
+                // If a payment app is available, then PaymentRequest.canMakePayment() returns true.
+                mCanMakePayment = true;
+                selection = 0;
+            }
+        }
 
         CanMakePaymentQuery query = sCanMakePaymentQueries.get(mPaymentRequestOrigin);
         if (query != null && query.matchesPaymentMethods(mMethodData)) {
@@ -1560,15 +1572,12 @@
         }
 
         // The list of payment instruments is ready to display.
-        mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.TYPE_PAYMENT_METHODS,
-                selection, new ArrayList<>(mPendingInstruments));
-        if (mPaymentMethodsSectionAdditionalTextResourceId != 0) {
-            Context context = ChromeActivity.fromWebContents(mWebContents);
-            if (context != null) {
-                mPaymentMethodsSection.setAdditionalText(
-                        context.getString(mPaymentMethodsSectionAdditionalTextResourceId));
-            }
+        List<PaymentInstrument> sortedInstruments = new ArrayList<>();
+        for (List<PaymentInstrument> a : mPendingInstruments) {
+            sortedInstruments.addAll(a);
         }
+        mPaymentMethodsSection = new SectionInformation(
+                PaymentRequestUI.TYPE_PAYMENT_METHODS, selection, sortedInstruments);
 
         mPendingInstruments.clear();
 
@@ -1588,8 +1597,8 @@
     private boolean disconnectIfNoPaymentMethodsSupported() {
         if (!isFinishedQueryingPaymentApps() || !mIsCurrentPaymentRequestShowing) return false;
 
-        boolean foundPaymentMethods =
-                mPaymentMethodsSection != null && !mPaymentMethodsSection.isEmpty();
+        boolean foundPaymentMethods = mPaymentMethodsSection != null
+                && !mPaymentMethodsSection.isEmpty();
         boolean userCanAddCreditCard = mMerchantSupportsAutofillPaymentInstruments
                 && !ChromeFeatureList.isEnabled(ChromeFeatureList.NO_CREDIT_CARD_ABORT);
 
@@ -1679,8 +1688,8 @@
         if (mShippingAddressesSection.getSelectedItem() == null) return;
 
         assert mShippingAddressesSection.getSelectedItem() instanceof AutofillAddress;
-        AutofillAddress selectedAddress =
-                (AutofillAddress) mShippingAddressesSection.getSelectedItem();
+        AutofillAddress selectedAddress = (AutofillAddress) mShippingAddressesSection
+                .getSelectedItem();
 
         // The label should only include the country if the view is focused.
         if (willFocus) {
@@ -1717,10 +1726,8 @@
         onAddressNormalized(profile);
     }
 
-    /**
-     * Starts the normalization of the new shipping address. Will call back into either
-     * onAddressNormalized or onCouldNotNormalize which will send the result to the merchant.
-     */
+    /** Starts the normalization of the new shipping address. Will call back into either
+     * onAddressNormalized or onCouldNotNormalize which will send the result to the merchant. */
     private void startShippingAddressChangeNormalization(AutofillAddress address) {
         PersonalDataManager.getInstance().normalizeAddress(
                 address.getProfile(), AutofillAddress.getCountryCode(address.getProfile()), this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
index 7a73a7e..fedac13 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
@@ -75,9 +75,4 @@
     public String getAppIdentifier() {
         return "Chrome_Service_Worker_Payment_App";
     }
-
-    @Override
-    public int getAdditionalAppTextResourceId() {
-        return 0;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
index 658f0e6..8ff4cd7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -1127,27 +1127,23 @@
 
     @Override
     public String getAdditionalText(PaymentRequestSection section) {
-        if (section == mShippingAddressSection) {
-            int selectedItemIndex = mShippingAddressSectionInformation.getSelectedItemIndex();
-            if (selectedItemIndex != SectionInformation.NO_SELECTION
-                    && selectedItemIndex != SectionInformation.INVALID_SELECTION) {
-                return null;
-            }
+        if (section != mShippingAddressSection) return null;
 
-            String customErrorMessage = mShippingAddressSectionInformation.getErrorMessage();
-            if (selectedItemIndex == SectionInformation.INVALID_SELECTION
-                    && !TextUtils.isEmpty(customErrorMessage)) {
-                return customErrorMessage;
-            }
-
-            return mContext.getString(selectedItemIndex == SectionInformation.NO_SELECTION
-                            ? mShippingStrings.getSelectPrompt()
-                            : mShippingStrings.getUnsupported());
-        } else if (section == mPaymentMethodSection) {
-            return mPaymentMethodSectionInformation.getAdditionalText();
-        } else {
+        int selectedItemIndex = mShippingAddressSectionInformation.getSelectedItemIndex();
+        if (selectedItemIndex != SectionInformation.NO_SELECTION
+                && selectedItemIndex != SectionInformation.INVALID_SELECTION) {
             return null;
         }
+
+        String customErrorMessage = mShippingAddressSectionInformation.getErrorMessage();
+        if (selectedItemIndex == SectionInformation.INVALID_SELECTION
+                && !TextUtils.isEmpty(customErrorMessage)) {
+            return customErrorMessage;
+        }
+
+        return mContext.getString(selectedItemIndex == SectionInformation.NO_SELECTION
+                        ? mShippingStrings.getSelectPrompt()
+                        : mShippingStrings.getUnsupported());
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/SectionInformation.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/SectionInformation.java
index 6e3e93a..2096ca3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/SectionInformation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/SectionInformation.java
@@ -33,8 +33,6 @@
     protected ArrayList<PaymentOption> mItems;
     private int mSelectedItem;
     public String mErrorMessage;
-    @Nullable
-    public String mAddditionalText;
 
     /**
      * Builds an empty section without selection.
@@ -211,17 +209,6 @@
         return mErrorMessage;
     }
 
-    /** @param text The optional additional text to display in this section. */
-    public void setAdditionalText(String text) {
-        mAddditionalText = text;
-    }
-
-    /** @return The optional additional text to display in this section. */
-    @Nullable
-    public String getAdditionalText() {
-        return mAddditionalText;
-    }
-
     /**
      * Returns all the items in the section. Used for testing.
      *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillLocalCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillLocalCardEditor.java
index a9385c8..56454e9f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillLocalCardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillLocalCardEditor.java
@@ -19,7 +19,6 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeVersionInfo;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
@@ -185,7 +184,7 @@
                 cardNumber, "" /* obfuscatedNumber */,
                 String.valueOf(mExpirationMonth.getSelectedItemPosition() + 1),
                 (String) mExpirationYear.getSelectedItem(), "" /* basicCardPaymentType */,
-                0 /* issuerIconDrawableId */, CardType.UNKNOWN,
+                0 /* issuerIconDrawableId */,
                 ((AutofillProfile) mBillingAddress.getSelectedItem()).getGUID() /* billing */,
                 "" /* serverId */);
         personalDataManager.setCreditCard(card);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 25488db..e8ab767 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -328,8 +328,8 @@
       <message name="IDS_PAYMENT_APPS_USAGE_MESSAGE" desc="Message to explain the usage of the listed payment apps.">
         On some websites, you can pay with above supported payment apps on your device.
       </message>
-      <message name="IDS_AUTOFILL_CREDIT_CARDS_TITLE" desc="Title of the preference to list the user's cards that can be automatically filled into web page forms. These can be either credit, debit, or prepaid cards. [CHAR-LIMIT=32]">
-        Cards
+      <message name="IDS_AUTOFILL_CREDIT_CARDS_TITLE" desc="Title of the preference to list the user's credit cards that can be automatically filled into web page forms. [CHAR-LIMIT=32]">
+        Credit cards
       </message>
       <message name="IDS_AUTOFILL_CREATE_PROFILE" desc="Button that allows the user to create a new profile (which contains the user's name, address, etc) that will be automatically filled into web page forms. [CHAR-LIMIT=32]">
         Add address
@@ -337,11 +337,11 @@
       <message name="IDS_AUTOFILL_EDIT_PROFILE" desc="Button that allows the user to edit a profile (which contains the user's name, address, etc) that can be automatically filled into web page forms. [CHAR-LIMIT=32]">
         Edit address
       </message>
-      <message name="IDS_AUTOFILL_CREATE_CREDIT_CARD" desc="Button that allows the user to add a new card that will be automatically filled into web page forms. This can be either credit, debit, or prepaid card. [CHAR-LIMIT=32]">
-        Add card
+      <message name="IDS_AUTOFILL_CREATE_CREDIT_CARD" desc="Button that allows the user to add a new credit card that will be automatically filled into web page forms. [CHAR-LIMIT=32]">
+        Add credit card
       </message>
-      <message name="IDS_AUTOFILL_EDIT_CREDIT_CARD" desc="Button that allows the user to edit a card that can be automatically filled into web page forms. This can be either credit, debit, or prepaid card. [CHAR-LIMIT=32]">
-        Edit card
+      <message name="IDS_AUTOFILL_EDIT_CREDIT_CARD" desc="Button that allows the user to edit a credit card that can be automatically filled into web page forms. [CHAR-LIMIT=32]">
+        Edit credit card
       </message>
      <message name="IDS_AUTOFILL_PROFILE_EDITOR_COUNTRY" desc="Label for a spinner input field containing a list of countries or regions [CHAR-LIMIT=32]">
         Country/Region
@@ -355,8 +355,8 @@
       <message name="IDS_AUTOFILL_CREDIT_CARD_EDITOR_NAME" desc="Label for text input field containing the name on a credit card. [CHAR-LIMIT=32]">
         Name on card
       </message>
-      <message name="IDS_AUTOFILL_CREDIT_CARD_EDITOR_NUMBER" desc="Label for text input field containing a card number. This can be a credit, debit, or prepaid card. [CHAR-LIMIT=32]">
-        Card number
+      <message name="IDS_AUTOFILL_CREDIT_CARD_EDITOR_NUMBER" desc="Label for text input field containing a credit card number. [CHAR-LIMIT=32]">
+        Credit card number
       </message>
       <message name="IDS_AUTOFILL_CREDIT_CARD_EDITOR_EXPIRATION_DATE" desc="Label for text input field containing a credit card expiration date. [CHAR-LIMIT=32]">
         Expiration date
@@ -1344,7 +1344,7 @@
         Settings
       </message>
       <message name="IDS_PAYMENTS_INTEGRATION" desc="Title for preference which enables import of Google Payments data for Autofill.">
-        Cards and addresses using Google Payments
+        Credit cards and addresses using Google Payments
       </message>
       <message name="IDS_SYNC_ENCRYPTION" desc="Preference category name for sync encryption. [CHAR-LIMT=32]">
         Encryption
@@ -1543,6 +1543,9 @@
       <message name="IDS_BOTTOM_BAR_SCREEN_POSITION" desc="Accessibility label to inform users about the InfoBar location">
         Options available near bottom of the screen
       </message>
+      <message name="IDS_PREVIEWS_INFOBAR_ACCESSIBILITY_TITLE" desc="Accessibility label to inform users about the InfoBar notifying the user that mobile data usage was reduced and the page was shown faster by showing a preview version of the web page instead of the full page.">
+        Simplified page to save data and load faster.
+      </message>
 
       <!-- DuplicateDownloadInfoBar -->
       <message name="IDS_DUPLICATE_DOWNLOAD_INFOBAR_TEXT" desc="Prompt text for the confirmation dialog asking whether the user really wants to download a file when there already exists a file with the same name">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index df937cc..292189ab 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1533,8 +1533,6 @@
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestLongIdTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDataUrlTest.java",
-  "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java",
-  "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
index 6417f5a..ea160c7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
@@ -401,13 +401,13 @@
         // Create a local card and an identical server card.
         CreditCard card1 = new CreditCard("" /* guid */, "https://www.example.com" /* origin */,
                 true /* isLocal */, false /* isCached */, "John Doe", "1234123412341234", "", "5",
-                "2020", "Visa", 0 /* issuerIconDrawableId */, CardType.UNKNOWN,
-                "" /* billingAddressId */, "" /* serverId */);
+                "2020", "Visa", 0 /* issuerIconDrawableId */, "" /* billingAddressId */,
+                "" /* serverId */);
 
         CreditCard card2 = new CreditCard("" /* guid */, "https://www.example.com" /* origin */,
                 false /* isLocal */, false /* isCached */, "John Doe", "1234123412341234", "", "5",
-                "2020", "Visa", 0 /* issuerIconDrawableId */, CardType.UNKNOWN,
-                "" /* billingAddressId */, "" /* serverId */);
+                "2020", "Visa", 0 /* issuerIconDrawableId */, "" /* billingAddressId */,
+                "" /* serverId */);
 
         mHelper.setCreditCard(card1);
         mHelper.addServerCreditCard(card2);
@@ -447,9 +447,9 @@
             throws InterruptedException, ExecutionException, TimeoutException {
         String guid = mHelper.setCreditCard(
                 new CreditCard("" /* guid */, "https://www.example.com" /* origin */,
-                        true /* isLocal */, false /* isCached */, "John Doe", "1234123412341234",
-                        "", "5", "2020", "Visa", 0 /* issuerIconDrawableId */, CardType.UNKNOWN,
-                        "" /* billingAddressId */, "" /* serverId */));
+                    true /* isLocal */, false /* isCached */, "John Doe", "1234123412341234", "",
+                    "5", "2020", "Visa", 0 /* issuerIconDrawableId */, "" /* billingAddressId */,
+                    "" /* serverId */));
 
         // Make sure the credit card does not have the specific use stats form the start.
         Assert.assertTrue(1234 != mHelper.getCreditCardUseCountForTesting(guid));
@@ -496,10 +496,11 @@
     public void testRecordAndLogCreditCardUse()
             throws InterruptedException, ExecutionException, TimeoutException {
         String guid = mHelper.setCreditCard(
-                new CreditCard("" /* guid */, "https://www.example.com" /* origin */,
-                        true /* isLocal */, false /* isCached */, "John Doe", "1234123412341234",
-                        "", "5", "2020", "Visa", 0 /* issuerIconDrawableId */, CardType.UNKNOWN,
-                        "" /* billingAddressId */, "" /* serverId */));
+                    new CreditCard("" /* guid */, "https://www.example.com" /* origin */,
+                            true /* isLocal */, false /* isCached */, "John Doe",
+                            "1234123412341234", "", "5", "2020", "Visa",
+                            0 /* issuerIconDrawableId */, "" /* billingAddressId */,
+                            "" /* serverId */));
 
         // Set specific use stats for the credit card.
         mHelper.setCreditCardUseStatsForTesting(guid, 1234, 1234);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
index 312e703..7c1150bd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
@@ -26,6 +26,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UrlUtils;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.WebContentsFactory;
@@ -72,6 +73,23 @@
     private EmbeddedTestServer mTestServer;
     private InfoBarTestAnimationListener mListener;
 
+    private static class TestInfoBar extends ConfirmInfoBar {
+        private boolean mCompact;
+
+        private TestInfoBar(String message) {
+            super(0, null, message, null, null, null);
+        }
+
+        @Override
+        protected boolean usesCompactLayout() {
+            return mCompact;
+        }
+
+        public void setUsesCompactLayout(boolean compact) {
+            mCompact = compact;
+        }
+    }
+
     private void waitUntilDataReductionPromoInfoBarAppears() {
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
@@ -122,6 +140,45 @@
     }
 
     /**
+     * Verify getAccessibilityMessage().
+     */
+    @Test
+    @MediumTest
+    @Feature({"Browser", "Main"})
+    public void testGetAccessibilityMessage() {
+        TestInfoBar infoBarNoMessage = new TestInfoBar(null);
+        infoBarNoMessage.setContext(ContextUtils.getApplicationContext());
+        Assert.assertEquals("Infobar shouldn't have accessibility message before createView()", "",
+                infoBarNoMessage.getAccessibilityText());
+        infoBarNoMessage.createView();
+        Assert.assertEquals("Infobar should have accessibility message after createView()",
+                ContextUtils.getApplicationContext().getString(R.string.bottom_bar_screen_position),
+                infoBarNoMessage.getAccessibilityText());
+
+        TestInfoBar infoBarCompact = new TestInfoBar(null);
+        infoBarCompact.setContext(ContextUtils.getApplicationContext());
+        Assert.assertEquals("Infobar shouldn't have accessibility message before createView()", "",
+                infoBarCompact.getAccessibilityText());
+        infoBarCompact.setUsesCompactLayout(true);
+        infoBarCompact.createView();
+        Assert.assertEquals("Infobar should have accessibility message after createView()",
+                ContextUtils.getApplicationContext().getString(R.string.bottom_bar_screen_position),
+                infoBarCompact.getAccessibilityText());
+
+        String messsage = "Hello world";
+        TestInfoBar infoBarWithMessage = new TestInfoBar(messsage);
+        infoBarWithMessage.setContext(ContextUtils.getApplicationContext());
+        Assert.assertEquals("Infobar shouldn't have accessibility message before createView()", "",
+                infoBarWithMessage.getAccessibilityText());
+        infoBarWithMessage.createView();
+        Assert.assertEquals("Infobar should have accessibility message after createView()",
+                messsage
+                        + ContextUtils.getApplicationContext().getString(
+                                  R.string.bottom_bar_screen_position),
+                infoBarWithMessage.getAccessibilityText());
+    }
+
+    /**
      * Verify PopUp InfoBar.
      */
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
index 452d4fc..77e62fb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -48,7 +47,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** If the user has not clicked "Pay" yet, then merchant's abort will succeed. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
index 92882c1..ae6adbd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBasicCardTest.java
@@ -10,7 +10,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 
@@ -36,7 +35,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     @MediumTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
index ee71e459..80a5ecf1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -60,8 +59,8 @@
                 "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", "US",
                 "650-253-0000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, profile1, "" /* serverId */));
+                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card, profile1,
+                "" /* serverId */));
         String profile2 = helper.setProfile(new AutofillProfile("", "https://example.com", true,
                 "Rob Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", "US",
                 "650-253-0000", "jon.doe@gmail.com", "en-US"));
@@ -95,8 +94,8 @@
 
         // This card has no billing address selected.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jane Doe",
-                "4242424242424242", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, profile6, "" /* serverId */));
+                "4242424242424242", "1111", "12", "2050", "visa", R.drawable.visa_card, profile6,
+                "" /* serverId */));
 
         // Assign use stats so that incomplete profiles have the highest frecency, profile2 has the
         // highest frecency and profile3 has the lowest among the complete profiles, and profile8
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
index c7626906..ecbb6da 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -62,7 +61,7 @@
                 "Los Angeles", "", "90291", "", "US", "", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, address_without_phone, "" /* serverId */));
+                address_without_phone, "" /* serverId */));
         String address_with_phone = helper.setProfile(new AutofillProfile("", "https://example.com",
                 true, "Rob Phone", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
index a2501ec..362acde 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -48,10 +47,9 @@
             TimeoutException {
         // The user has an incomplete credit card on file. This is not sufficient for
         // canMakePayment() to return true.
-        new AutofillTestHelper().setCreditCard(
-                new CreditCard("", "https://example.com", true, true, "" /* nameOnCard */,
-                        "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                        CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+        new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
+                "" /* nameOnCard */, "4111111111111111", "1111", "12", "2050", "visa",
+                R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
index e56f8490..139c647 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -50,7 +49,7 @@
         // for canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+                "" /* billingAddressId */, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
index 54bf1ae..65adf11 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,7 +54,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "1", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
index 472e3a3..2188897b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
@@ -15,7 +15,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -43,10 +42,9 @@
             TimeoutException {
         // The user has an incomplete credit card on file. This is not sufficient for
         // canMakePayment() to return true.
-        new AutofillTestHelper().setCreditCard(
-                new CreditCard("", "https://example.com", true, true, "" /* nameOnCard */,
-                        "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                        CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+        new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
+                "" /* nameOnCard */, "4111111111111111", "1111", "12", "2050", "visa",
+                R.drawable.visa_card, "" /* billingAddressId */, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
index ee504c9e..9e98dbe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
@@ -9,7 +9,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 
 import java.util.concurrent.ExecutionException;
@@ -32,7 +31,7 @@
         // for canMakePayment() to return true.
         new AutofillTestHelper().setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+                "" /* billingAddressId */, "" /* serverId */));
     }
 
     @MediumTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
index c85923c..2dd0dea 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -53,7 +52,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java
deleted file mode 100644
index e750d92..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.payments;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
-import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/**
- * A payment integration test for a merchant that requests debit card payment. The user has a debit
- * card on file.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
-public class PaymentRequestDebitTest implements MainActivityStartCallback {
-    @Rule
-    public PaymentRequestTestRule mPaymentRequestTestRule =
-            new PaymentRequestTestRule("payment_request_debit_test.html", this);
-
-    @Override
-    public void onMainActivityStarted()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        AutofillTestHelper helper = new AutofillTestHelper();
-        String billingAddressId = helper.setProfile(new AutofillProfile("", "https://example.com",
-                true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
-                "US", "555-555-5555", "jon.doe@google.com", "en-US"));
-
-        // Should be pre-selected:
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.DEBIT, billingAddressId, "server-id-1"));
-
-        // Should be available, but never pre-selected:
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "6011111111111117", "1117", "12", "2050", "discover", R.drawable.discover_card,
-                CardType.UNKNOWN, billingAddressId, "server-id-2"));
-
-        // Should not be available:
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "378282246310005", "0005", "12", "2050", "amex", R.drawable.amex_card,
-                CardType.CREDIT, billingAddressId, "server-id-3"));
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "5555555555554444", "4444", "12", "2050", "mastercard", R.drawable.mc_card,
-                CardType.PREPAID, billingAddressId, "server-id-4"));
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Payments"})
-    public void testDebitCardTypeIsPreselectedAndUnknownCardTypeIsAvailable()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
-
-        Assert.assertTrue(mPaymentRequestTestRule.getPaymentInstrumentLabel(0).contains("Visa"));
-
-        mPaymentRequestTestRule.clickInPaymentMethodAndWait(
-                R.id.payments_section, mPaymentRequestTestRule.getReadyToPay());
-        Assert.assertEquals(2, mPaymentRequestTestRule.getNumberOfPaymentInstruments());
-
-        Assert.assertTrue(mPaymentRequestTestRule.getPaymentInstrumentLabel(0).contains("Visa"));
-        Assert.assertTrue(
-                mPaymentRequestTestRule.getPaymentInstrumentLabel(1).contains("Discover"));
-
-        mPaymentRequestTestRule.clickAndWait(
-                R.id.close_button, mPaymentRequestTestRule.getDismissed());
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Payments"})
-    public void testCanMakePaymentWithDebitCard()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        mPaymentRequestTestRule.openPageAndClickNodeAndWait(
-                "canMakePayment", mPaymentRequestTestRule.getCanMakePaymentQueryResponded());
-        mPaymentRequestTestRule.expectResultContains(new String[] {"true"});
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java
deleted file mode 100644
index 4c860723..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.payments;
-
-import android.support.test.filters.MediumTest;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
-import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
-import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-/**
- * A payment integration test for a merchant that requests debit card payment. The user does not
- * have a debit card on file, but has one card that has "unknown" card type, which should not be
- * pre-selected, but should be available for the user to select.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
-public class PaymentRequestDontHaveDebitTest implements MainActivityStartCallback {
-    @Rule
-    public PaymentRequestTestRule mPaymentRequestTestRule =
-            new PaymentRequestTestRule("payment_request_debit_test.html", this);
-
-    @Override
-    public void onMainActivityStarted()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        AutofillTestHelper helper = new AutofillTestHelper();
-        String billingAddressId = helper.setProfile(new AutofillProfile("", "https://example.com",
-                true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "",
-                "US", "555-555-5555", "jon.doe@google.com", "en-US"));
-
-        // Should be available, but never pre-selected:
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "6011111111111117", "1117", "12", "2050", "discover", R.drawable.discover_card,
-                CardType.UNKNOWN, billingAddressId, "server-id-2"));
-
-        // Should not be available:
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "378282246310005", "0005", "12", "2050", "amex", R.drawable.amex_card,
-                CardType.CREDIT, billingAddressId, "server-id-3"));
-        helper.addServerCreditCard(new CreditCard("", "https://example.com", false, true, "Jon Doe",
-                "5555555555554444", "4444", "12", "2050", "mastercard", R.drawable.mc_card,
-                CardType.PREPAID, billingAddressId, "server-id-4"));
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Payments"})
-    public void testUnknownCardTypeIsNotPreselectedButAvailable()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyForInput());
-
-        Assert.assertTrue(
-                mPaymentRequestTestRule.getPaymentInstrumentLabel(0).contains("Discover"));
-
-        mPaymentRequestTestRule.clickInPaymentMethodAndWait(
-                R.id.payments_section, mPaymentRequestTestRule.getReadyForInput());
-        Assert.assertEquals(1, mPaymentRequestTestRule.getNumberOfPaymentInstruments());
-
-        Assert.assertTrue(
-                mPaymentRequestTestRule.getPaymentInstrumentLabel(0).contains("Discover"));
-
-        mPaymentRequestTestRule.clickAndWait(
-                R.id.close_button, mPaymentRequestTestRule.getDismissed());
-    }
-
-    @Test
-    @MediumTest
-    @Feature({"Payments"})
-    public void testCanMakePaymentWithUnknownCardType()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        mPaymentRequestTestRule.openPageAndClickNodeAndWait(
-                "canMakePayment", mPaymentRequestTestRule.getCanMakePaymentQueryResponded());
-        mPaymentRequestTestRule.expectResultContains(new String[] {"true"});
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
index a8cca016..172a934 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -54,7 +53,7 @@
                 "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** The shipping address should not be selected in UI by default. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
index a6d3f75..f97a45ae 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -52,7 +51,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Submit the email and the shipping address to the merchant when the user clicks "Pay." */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
index cda6b1c..5288dc5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,7 +54,7 @@
         // Create an expired credit card
         mCreditCardId = mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "Jon Doe", "4111111111111111", "1111", "1", "2016", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
index d84ac5db..8fbf9afe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -49,7 +48,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
index 72fafb8..b206d0e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -48,7 +47,7 @@
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
index 142a3bc7..f1d38c1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -53,7 +52,7 @@
                 "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Submit the shipping address to the merchant when the user clicks "Pay." */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
index a48656ef..330687e4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -49,7 +48,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
index 39599e07..9b48730a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -50,8 +49,7 @@
                 "US", "310-310-6000", "jon.doe@gmail.com", "en-US"));
         helper.addServerCreditCard(new CreditCard("", "https://example.com", false /* isLocal */,
                 true /* isCached */, "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa",
-                R.drawable.visa_card, CardType.UNKNOWN, "" /* billing address */,
-                "" /* serverId */));
+                R.drawable.visa_card, "" /* billing address */, "" /* serverId */));
     }
 
     /** Click [PAY] and dismiss the card unmask dialog. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
index af427b3..f85070a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -54,14 +53,14 @@
                 "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, mBillingAddressId, "" /* serverId */));
+                mBillingAddressId, "" /* serverId */));
         // The user also has an incomplete address and an incomplete card saved.
         String mIncompleteAddressId = mHelper.setProfile(new AutofillProfile("",
                 "https://example.com", true, "In Complete", "Google", "344 Main St", "CA", "", "",
                 "90291", "", "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "",
                 "4111111111111111", "1111", "18", "2075", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, mIncompleteAddressId, "" /* serverId */));
+                mIncompleteAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
index 3970e5f..3b5e81b84 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -62,7 +61,7 @@
                 "US", "650-253-0000", "", "en-US"));
         mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, mBillingAddressId, "" /* serverId */));
+                mBillingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
index dd203f5..0012910 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -52,7 +51,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Submit the payer name and shipping address to the merchant when the user clicks "Pay." */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
index f0c71a3..d218179 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -51,7 +50,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
 
         // Add the same profile but with a different address.
         helper.setProfile(new AutofillProfile("", "https://example.com", true, "", "Google",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
index 159270f1..5403a37 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -57,7 +56,7 @@
                 "US", "650-253-0000", "jon.doe@gmail.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Click [X] to cancel payment. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
index f370f2c..85673cc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -57,11 +56,11 @@
         // Mastercard card without a billing address.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "5454545454545454", "", "12", "2050", "mastercard", R.drawable.mc_card,
-                CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+                "" /* billingAddressId */, "" /* serverId */));
         // Visa card with complete set of information.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
index 98cf15c..67d311f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,11 +54,11 @@
         // Mastercard card without a billing address.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "5454545454545454", "", "12", "2050", "mastercard", R.drawable.mc_card,
-                CardType.UNKNOWN, "" /* billingAddressId */, "" /* serverId */));
+                "" /* billingAddressId */, "" /* serverId */));
         // Visa card with complete set of information.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
index 556da561..07b0d79 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.WebContents;
 
+import java.util.Arrays;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -95,7 +96,8 @@
     @Feature({"Payments"})
     public void testPaymentWithInstrumentsAppResponseAfterDismissShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        final TestPay app = new TestPay("https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
+        final TestPay app = new TestPay(
+                Arrays.asList("https://bobpay.com"), HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
         PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
             @Override
             public void create(WebContents webContents, Set<String> methodNames,
@@ -125,7 +127,8 @@
     @Feature({"Payments"})
     public void testPaymentAppNoInstrumentsResponseAfterDismissShouldNotCrash()
             throws InterruptedException, ExecutionException, TimeoutException {
-        final TestPay app = new TestPay("https://bobpay.com", NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
+        final TestPay app = new TestPay(
+                Arrays.asList("https://bobpay.com"), NO_INSTRUMENTS, IMMEDIATE_RESPONSE);
         PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
             @Override
             public void create(WebContents webContents, Set<String> methodNames,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
index 54ea441..d969128 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentAppFactory.PaymentAppCreatedCallback;
@@ -30,6 +29,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.WebContents;
 
+import java.util.Arrays;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -56,7 +56,7 @@
         // behind non-autofill payment instruments in payment request.
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     @Test
@@ -67,42 +67,43 @@
         // Install a payment app with Bob Pay and Alice Pay, and another payment app with Charlie
         // Pay.
         final TestPay appA =
-                new TestPay("https://alicepay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        final TestPay appB =
-                new TestPay("https://bobpay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
-        final TestPay appC =
-                new TestPay("https://charliepay.com", HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
+                new TestPay(Arrays.asList("https://alicepay.com", "https://bobpay.com"),
+                        HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
+        final TestPay appB = new TestPay(
+                Arrays.asList("https://charliepay.com"), HAVE_INSTRUMENTS, IMMEDIATE_RESPONSE);
         PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
             @Override
             public void create(WebContents webContents, Set<String> methodNames,
                     PaymentAppCreatedCallback callback) {
                 callback.onPaymentAppCreated(appA);
                 callback.onPaymentAppCreated(appB);
-                callback.onPaymentAppCreated(appC);
                 callback.onAllPaymentAppsCreated();
             }
         });
-        String alicePayId = appA.getAppIdentifier() + "https://alicepay.com";
-        String bobPayId = appB.getAppIdentifier() + "https://bobpay.com";
-        String charliePayId = appC.getAppIdentifier() + "https://charliepay.com";
+        String appAAlicePayId = appA.getAppIdentifier() + "https://alicepay.com";
+        String appABobPayId = appA.getAppIdentifier() + "https://bobpay.com";
+        String appBCharliePayId = appB.getAppIdentifier() + "https://charliepay.com";
 
         // The initial records for all payment methods are zeroes.
-        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(alicePayId));
-        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(bobPayId));
-        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(charliePayId));
-        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(alicePayId));
-        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(bobPayId));
+        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appAAlicePayId));
+        Assert.assertEquals(0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appABobPayId));
         Assert.assertEquals(
-                0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(charliePayId));
+                0, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appBCharliePayId));
+        Assert.assertEquals(
+                0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appAAlicePayId));
+        Assert.assertEquals(
+                0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appABobPayId));
+        Assert.assertEquals(
+                0, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appBCharliePayId));
 
         // Sets Alice Pay use count and use date to 5. Sets Bob Pay use count and use date to 10.
         // Sets Charlie Pay use count and use date to 15.
-        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(alicePayId, 5);
-        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(alicePayId, 5);
-        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(bobPayId, 10);
-        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(bobPayId, 10);
-        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(charliePayId, 15);
-        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(charliePayId, 15);
+        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appAAlicePayId, 5);
+        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appAAlicePayId, 5);
+        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appABobPayId, 10);
+        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appABobPayId, 10);
+        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appBCharliePayId, 15);
+        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appBCharliePayId, 15);
 
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
         mPaymentRequestTestRule.clickInPaymentMethodAndWait(
@@ -125,17 +126,20 @@
                 R.id.button_secondary, mPaymentRequestTestRule.getDismissed());
 
         // Checks the records for all payment instruments haven't been changed.
-        Assert.assertEquals(5, PaymentPreferencesUtil.getPaymentInstrumentUseCount(alicePayId));
-        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentUseCount(bobPayId));
-        Assert.assertEquals(15, PaymentPreferencesUtil.getPaymentInstrumentUseCount(charliePayId));
-        Assert.assertEquals(5, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(alicePayId));
-        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(bobPayId));
+        Assert.assertEquals(5, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appAAlicePayId));
+        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appABobPayId));
         Assert.assertEquals(
-                15, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(charliePayId));
+                15, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appBCharliePayId));
+        Assert.assertEquals(
+                5, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appAAlicePayId));
+        Assert.assertEquals(
+                10, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appABobPayId));
+        Assert.assertEquals(
+                15, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appBCharliePayId));
 
         // Sets Alice Pay use count and use date to 20.
-        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(alicePayId, 20);
-        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(alicePayId, 20);
+        PaymentPreferencesUtil.setPaymentInstrumentUseCountForTest(appAAlicePayId, 20);
+        PaymentPreferencesUtil.setPaymentInstrumentLastUseDate(appAAlicePayId, 20);
 
         mPaymentRequestTestRule.reTriggerUIAndWait("buy", mPaymentRequestTestRule.getReadyToPay());
         mPaymentRequestTestRule.clickInPaymentMethodAndWait(
@@ -147,9 +151,9 @@
         Assert.assertEquals(
                 "https://alicepay.com", mPaymentRequestTestRule.getPaymentInstrumentLabel(0));
         Assert.assertEquals(
-                "https://charliepay.com", mPaymentRequestTestRule.getPaymentInstrumentLabel(1));
+                "https://bobpay.com", mPaymentRequestTestRule.getPaymentInstrumentLabel(1));
         Assert.assertEquals(
-                "https://bobpay.com", mPaymentRequestTestRule.getPaymentInstrumentLabel(2));
+                "https://charliepay.com", mPaymentRequestTestRule.getPaymentInstrumentLabel(2));
         Assert.assertEquals(
                 "Visa\u0020\u0020\u2022\u2006\u2022\u2006\u2022\u2006\u2022\u20061111\nJon Doe",
                 mPaymentRequestTestRule.getPaymentInstrumentLabel(3));
@@ -162,12 +166,16 @@
 
         // Checks Alice Pay use count is increased by one after completing a payment request with
         // it.
-        Assert.assertEquals(21, PaymentPreferencesUtil.getPaymentInstrumentUseCount(alicePayId));
-        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentUseCount(bobPayId));
-        Assert.assertEquals(15, PaymentPreferencesUtil.getPaymentInstrumentUseCount(charliePayId));
-        Assert.assertTrue(PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(alicePayId) > 20);
-        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(bobPayId));
         Assert.assertEquals(
-                15, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(charliePayId));
+                21, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appAAlicePayId));
+        Assert.assertEquals(10, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appABobPayId));
+        Assert.assertEquals(
+                15, PaymentPreferencesUtil.getPaymentInstrumentUseCount(appBCharliePayId));
+        Assert.assertTrue(
+                PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appAAlicePayId) > 20);
+        Assert.assertEquals(
+                10, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appABobPayId));
+        Assert.assertEquals(
+                15, PaymentPreferencesUtil.getPaymentInstrumentLastUseDate(appBCharliePayId));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
index 81b4ffb..3015894 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -52,7 +51,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Submit the phone number and shipping address to the merchant when the user clicks "Pay." */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
index 92aaa94..4f35fb7a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,7 +54,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Alice",
                 "4111111111111111", "1111", "1", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
         helper.deleteProfile(billingAddressId);
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
index b264337..44ee6d60 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -49,7 +48,7 @@
         helper.addServerCreditCard(new CreditCard("4754d21d-8773-40b6-b4be-5f7486be834f",
                 "https://example.com", false /* isLocal */, true /* isCached */, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** Click [PAY] and dismiss the card unmask dialog. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
index 45045e47..903ebe6d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -49,7 +48,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, firstAddressId, "" /* serverId */));
+                firstAddressId, "" /* serverId */));
 
         // The user has a second address.
         String secondAddressId = helper.setProfile(new AutofillProfile("", "https://example.com",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
index 70288d17..611230f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
@@ -15,7 +15,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -48,7 +47,7 @@
                 "", "US", "650-253-0000", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index 5f4d632..5796c98 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -49,7 +48,7 @@
                 "US", "555-555-5555", "", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
index b51c625e..1ff76c0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,7 +54,7 @@
                 "US", "555-555-5555", "jon.doe@google.com", "en-US"));
         helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe",
                 "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, billingAddressId, "" /* serverId */));
+                billingAddressId, "" /* serverId */));
     }
 
     /** If the user switches tabs somehow, the dialog is dismissed. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
index 9bc4fc2..725fa4e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
@@ -15,6 +15,7 @@
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
 
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -456,6 +457,7 @@
         mTestCommon.onCardUnmaskPromptValidationDone(prompt);
     }
 
+
     /**
      * Installs a payment app for testing.
      *
@@ -497,6 +499,12 @@
         mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed, creationSpeed);
     }
 
+    protected void installPaymentApp(final List<String> appMethodNames,
+            final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
+        mTestCommon.installPaymentApp(
+                appMethodNames, instrumentPresence, responseSpeed, creationSpeed);
+    }
+
     @Override
     public void startMainActivityWithURL(String url) throws InterruptedException {
         super.startMainActivityWithURL(url);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
index e1c8ceb..7d845bf3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestCommon.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.payments;
 
+import static java.util.Arrays.asList;
+
 import android.os.Handler;
 import android.view.KeyEvent;
 import android.view.View;
@@ -130,9 +132,8 @@
         mViewCoreRef = new AtomicReference<>();
         mWebContentsRef = new AtomicReference<>();
         mTestFilePath = testFileName.startsWith("data:")
-                ? testFileName
-                : UrlUtils.getIsolatedTestFilePath(
-                          String.format("chrome/test/data/payments/%s", testFileName));
+                ? testFileName : UrlUtils.getIsolatedTestFilePath(
+                        String.format("chrome/test/data/payments/%s", testFileName));
     }
 
     public void startMainActivity() throws InterruptedException {
@@ -899,13 +900,18 @@
         installPaymentApp(methodName, instrumentPresence, responseSpeed, IMMEDIATE_CREATION);
     }
 
-    void installPaymentApp(final String appMethodName, final int instrumentPresence,
-            final int responseSpeed, final int creationSpeed) {
+    void installPaymentApp(
+            String methodName, int instrumentPresence, int responseSpeed, int creationSpeed) {
+        installPaymentApp(asList(methodName), instrumentPresence, responseSpeed, creationSpeed);
+    }
+
+    void installPaymentApp(final List<String> appMethodNames,
+            final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
         PaymentAppFactory.getInstance().addAdditionalFactory(new PaymentAppFactoryAddition() {
             @Override
             public void create(WebContents webContents, Set<String> methodNames,
                     final PaymentAppFactory.PaymentAppCreatedCallback callback) {
-                final TestPay app = new TestPay(appMethodName, instrumentPresence, responseSpeed);
+                final TestPay app = new TestPay(appMethodNames, instrumentPresence, responseSpeed);
                 if (creationSpeed == IMMEDIATE_CREATION) {
                     callback.onPaymentAppCreated(app);
                     callback.onAllPaymentAppsCreated();
@@ -924,13 +930,13 @@
 
     /** A payment app implementation for test. */
     static class TestPay implements PaymentApp {
-        private final String mDefaultMethodName;
+        private final List<String> mMethodNames;
         private final int mInstrumentPresence;
         private final int mResponseSpeed;
         private InstrumentsCallback mCallback;
 
-        TestPay(String defaultMethodName, int instrumentPresence, int responseSpeed) {
-            mDefaultMethodName = defaultMethodName;
+        TestPay(List<String> methodNames, int instrumentPresence, int responseSpeed) {
+            mMethodNames = methodNames;
             mInstrumentPresence = instrumentPresence;
             mResponseSpeed = responseSpeed;
         }
@@ -946,8 +952,10 @@
         void respond() {
             final List<PaymentInstrument> instruments = new ArrayList<>();
             if (mInstrumentPresence == HAVE_INSTRUMENTS) {
-                instruments.add(new TestPayInstrument(
-                        getAppIdentifier(), mDefaultMethodName, mDefaultMethodName));
+                for (String methodName : mMethodNames) {
+                    instruments.add(
+                            new TestPayInstrument(getAppIdentifier(), methodName, methodName));
+                }
             }
             Runnable instrumentsReady = new Runnable() {
                 @Override
@@ -965,9 +973,9 @@
 
         @Override
         public Set<String> getAppMethodNames() {
-            Set<String> result = new HashSet<>();
-            result.add(mDefaultMethodName);
-            return result;
+            Set<String> methodNames = new HashSet<>();
+            methodNames.addAll(mMethodNames);
+            return methodNames;
         }
 
         @Override
@@ -982,26 +990,21 @@
         public String getAppIdentifier() {
             return TestPay.this.toString();
         }
-
-        @Override
-        public int getAdditionalAppTextResourceId() {
-            return 0;
-        }
     }
 
     /** A payment instrument implementation for test. */
     private static class TestPayInstrument extends PaymentInstrument {
-        private final String mDefaultMethodName;
+        private final String mMethodName;
 
-        TestPayInstrument(String appId, String defaultMethodName, String label) {
-            super(appId + defaultMethodName, label, null, null);
-            mDefaultMethodName = defaultMethodName;
+        TestPayInstrument(String appId, String methodName, String label) {
+            super(appId + methodName, label, null, null);
+            mMethodName = methodName;
         }
 
         @Override
         public Set<String> getInstrumentMethodNames() {
             Set<String> result = new HashSet<>();
-            result.add(mDefaultMethodName);
+            result.add(mMethodName);
             return result;
         }
 
@@ -1011,7 +1014,8 @@
                 Map<String, PaymentMethodData> methodData, PaymentItem total,
                 List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers,
                 InstrumentDetailsCallback detailsCallback) {
-            detailsCallback.onInstrumentDetailsReady(mDefaultMethodName, "{\"transaction\": 1337}");
+            detailsCallback.onInstrumentDetailsReady(
+                    mMethodName, "{\"transaction\": 1337}");
         }
 
         @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
index d3bf11a..97dc44dc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -536,6 +537,12 @@
         mTestCommon.installPaymentApp(methodName, instrumentPresence, responseSpeed, creationSpeed);
     }
 
+    protected void installPaymentApp(final List<String> appMethodNames,
+            final int instrumentPresence, final int responseSpeed, final int creationSpeed) {
+        mTestCommon.installPaymentApp(
+                appMethodNames, instrumentPresence, responseSpeed, creationSpeed);
+    }
+
     @Override
     public void onMainActivityStarted()
             throws InterruptedException, ExecutionException, TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
index fa3db8b..4991fc1a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
@@ -55,7 +54,7 @@
                 "US", "555-555-5555", "", "en-US"));
         mCreditCardId = mHelper.setCreditCard(new CreditCard("", "https://example.com", true, true,
                 "Jon Doe", "4111111111111111", "1111", "12", "2050", "visa", R.drawable.visa_card,
-                CardType.UNKNOWN, mBillingAddressId, "" /* serverId */));
+                mBillingAddressId, "" /* serverId */));
         // Set specific use stats for the profile and credit card.
         mHelper.setProfileUseStatsForTesting(mBillingAddressId, 20, 5000);
         mHelper.setCreditCardUseStatsForTesting(mCreditCardId, 1, 5000);
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
index d068de3..5d16701 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
@@ -21,7 +21,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.preferences.Preferences;
@@ -741,7 +740,7 @@
                 boolean isLocal = false;
                 PersonalDataManager.getInstance().addServerCreditCardForTest(new CreditCard("",
                         "https://example.com", isLocal, false, "Jon Doe", "4111111111111111",
-                        "1111", "11", "20", "visa", 0, CardType.UNKNOWN, "" /* billingAddressId */,
+                        "1111", "11", "20", "visa", 0, "" /* billingAddressId */,
                         "025eb937c022489eb8dc78cbaa969218" /* serverId */));
             }
         });
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index 54524a6..25b891f3 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -16,6 +16,7 @@
 #include "ui/gfx/switches.h"
 
 #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING)
+#include "chrome/common/profiling/memlog_sender.h"
 #include "chrome/profiling/profiling_main.h"
 #endif
 
@@ -107,8 +108,13 @@
 #endif  // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
 
 #if BUILDFLAG(ENABLE_OOP_HEAP_PROFILING)
+#if !defined(OS_WIN) || defined(CHROME_MULTIPLE_DLL_BROWSER)
+  // The profiling server is only compiled into the browser process. On Windows,
+  // it should be called only for CHROME_MULTIPLE_DLL_BROWSER.
   if (command_line->HasSwitch(switches::kMemlog))
     return profiling::ProfilingMain(*command_line);
+#endif
+  profiling::InitMemlogSenderIfNecessary(*command_line);
 #endif  // ENABLE_OOP_HEAP_PROFILING
 
 #if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_PACKAGE_MASH_SERVICES)
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index e0f48a3..ccd445d7 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -6099,6 +6099,12 @@
   <message name="IDS_VOICE_INTERACTION_VALUE_PROP_CONTINUE_BUTTION" desc="tmp">
     Continue
   </message>
+  <message name="IDS_WAIT_FOR_CONTAINER_READY_TITLE" desc="tmp">
+    Just a sec
+  </message>
+  <message name="IDS_WAIT_FOR_CONTAINER_READY_INTRO_MESSAGE" desc="tmp">
+    Ask it questions. Tell it to do things. It's your personal Google, always ready to help.
+  </message>
 
   <!-- Print Job Notification -->
   <message name="IDS_PRINT_JOB_PRINTING_NOTIFICATION_TITLE" desc="Title of the printing-in-progress notification.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8fbeb05d..2ebb346 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4975,6 +4975,15 @@
       <message name="IDS_PREVIEWS_INFOBAR_LINK" desc="The text of the link to load the original page from the infobar notifying the user that a preview page has been shown.">
          Show original
       </message>
+      <message name="IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES" desc="The desciption stating how old a preview version of a page is in minutes. This is shown on the infobar notifying the user that a preview page has been shown.">
+         Updated <ph name="MINUTES">$1<ex>30</ex></ph>min ago
+      </message>
+      <message name="IDS_PREVIEWS_INFOBAR_TIMESTAMP_ONE_HOUR" desc="The desciption stating a preview version of a page is one hour old. This is shown on the infobar notifying the user that a preview page has been shown.">
+         Updated 1hr ago
+      </message>
+      <message name="IDS_PREVIEWS_INFOBAR_TIMESTAMP_HOURS" desc="The desciption stating how old a preview version of a page is in hours. This is shown on the infobar notifying the user that a preview page has been shown.">
+         Updated <ph name="HOURS">$1<ex>4</ex></ph>hrs ago
+      </message>
 
       <!-- WebRTC logs -->
       <message name="IDS_WEBRTC_LOGS_TITLE" desc="Title for the chrome://webrtc-logs page.">
@@ -5447,8 +5456,8 @@
         </message>
       </if>
       <if expr="use_titlecase">
-        <message name="IDS_TOOLTIP_SAVE_CREDIT_CARD" desc="In Title Case: The tooltip for the icon that shows the save card bubble">
-          Save Card
+        <message name="IDS_TOOLTIP_SAVE_CREDIT_CARD" desc="In Title Case: The tooltip for the icon that shows the save credit card bubble">
+          Save Credit Card
         </message>
        </if>
       <message name="IDS_TOOLTIP_TRANSLATE" desc="The tooltip for translate">
@@ -7572,8 +7581,8 @@
         <message name="IDS_AUTOFILL_ADDRESSES_GROUP_NAME" desc="The name of the Addresses group of the Autofill dialog.">
           Addresses
         </message>
-        <message name="IDS_AUTOFILL_CREDITCARDS_GROUP_NAME" desc="The name of the Cards group of the Autofill dialog.">
-          Cards
+        <message name="IDS_AUTOFILL_CREDITCARDS_GROUP_NAME" desc="IThe name of the Credit Cards group of the Autofill dialog.">
+          Credit cards
         </message>
         <message name="IDS_AUTOFILL_EDIT_ADDRESS_CAPTION" desc="The caption on the edit Autofill address dialog.">
           Edit address
@@ -7584,14 +7593,14 @@
         <message name="IDS_AUTOFILL_ADD_CONTACT_CAPTION" desc="The caption on the edit Autofill contact dialog for the new entry.">
           Add a contact
         </message>
-        <message name="IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION" desc="The caption on the edit Autofill card dialog. The card can be either credit, debit, or prepaid.">
-          Edit card
+        <message name="IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION" desc="The caption on the edit Autofill credit card dialog.">
+          Edit credit card
         </message>
-        <message name="IDS_AUTOFILL_ADD_CREDITCARD_CAPTION" desc="The caption on the edit Autofill card dialog the new entry. The card can be either credit, debit, or prepaid.">
-          Add a card
+        <message name="IDS_AUTOFILL_ADD_CREDITCARD_CAPTION" desc="The caption on the edit Autofill credit card dialog the new entry.">
+          Add a credit card
         </message>
         <message name="IDS_AUTOFILL_USE_PAYMENTS_DATA" desc="The text for the checkbox that controls the Autofill/Payments integration feature.">
-          Cards and addresses using Google Payments
+          Credit cards and addresses using Google Payments
         </message>
 
         <message name="IDS_AUTOFILL_FIELD_LABEL_EMAIL" desc="The label of the Email entry.">
@@ -7603,8 +7612,8 @@
         <message name="IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD" desc="The label of the Name on card entry.">
           Name on card
         </message>
-        <message name="IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER" desc="The label of the card number entry. This can be either credit, debit, or prepaid card.">
-          Card number
+        <message name="IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER" desc="The label of the Credit card number entry.">
+          Credit card number
         </message>
         <message name="IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_DATE" desc="The label of the Expiration date entry.">
           Expiration date
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index f7307ab8..eed7b44d 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -425,17 +425,17 @@
   <message name="IDS_SETTINGS_CREDIT_CARD_CLEAR" desc="Label for a context menu item clears the locally cached credit card that is also saved on Google Payments. Clicking this will NOT remove the credit card from Google Payments.">
    Clear copy
   </message>
-  <message name="IDS_SETTINGS_EDIT_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when editing a card. This can be either credit, debit, or prepaid card..">
-    Edit card
+  <message name="IDS_SETTINGS_EDIT_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when editing a credit card.">
+    Edit credit card
   </message>
-  <message name="IDS_SETTINGS_ADD_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when entering the information for a new card. This can be either credit, debit, or prepaid card.">
-    Add card
+  <message name="IDS_SETTINGS_ADD_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when entering the information for a new credit card.">
+    Add credit card
   </message>
   <message name="IDS_SETTINGS_NAME_ON_CREDIT_CARD" desc="The title for the input that lets users modify the name on the credit card.">
     Name on card
   </message>
-  <message name="IDS_SETTINGS_CREDIT_CARD_NUMBER" desc="The title for the input that lets users modify the number for a card. This can be either credit, debit, or prepaid card.">
-    Card number
+  <message name="IDS_SETTINGS_CREDIT_CARD_NUMBER" desc="The title for the input that lets users modify the credit card number for a credit card.">
+    Credit card number
   </message>
   <message name="IDS_SETTINGS_CREDIT_CARD_EXPIRATION_DATE" desc="Label for the expiration date fields of a credit card that has been or is being saved.">
     Expiration date
@@ -446,8 +446,8 @@
   <message name="IDS_SETTINGS_CREDIT_CARD_EXPIRATION_YEAR" desc="Accessibility label on the year drop down to let users know the field corresponds to the expiration year">
     Expiration year
   </message>
-  <message name="IDS_SETTINGS_CREDIT_CARD_EXPIRED" desc="The error message that is shown when user attempts to enter or save an expired card.">
-    Your card is expired
+  <message name="IDS_SETTINGS_CREDIT_CARD_EXPIRED" desc="The error message that is shown when user attempts to enter or save an expired credit card.">
+    Your credit card is expired
   </message>
   <message name="IDS_SETTINGS_PASSWORDS" desc="Name for the password section and toggle">
     Manage passwords
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index c649944..26e5f878 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -124,6 +124,7 @@
   "+third_party/WebKit/public/platform/modules/payments/payment_app.mojom.h",
   "+third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
+  "+third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h",
   "+third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h",
   "+third_party/WebKit/public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h",
   "+third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 99b5c2c5..3819af3 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2490,12 +2490,12 @@
          chromeos::switches::kEnableEncryptionMigration,
          chromeos::switches::kDisableEncryptionMigration)},
 #endif  // OS_CHROMEOS
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && defined(GOOGLE_CHROME_BUILD)
+#if !defined(OS_ANDROID) && defined(GOOGLE_CHROME_BUILD)
     {"enable-google-branded-context-menu",
      flag_descriptions::kGoogleBrandedContextMenuName,
      flag_descriptions::kGoogleBrandedContextMenuDescription, kOsDesktop,
      SINGLE_VALUE_TYPE(switches::kEnableGoogleBrandedContextMenu)},
-#endif  // !OS_ANDROID && !OS_IOS && GOOGLE_CHROME_BUILD
+#endif  // !OS_ANDROID && GOOGLE_CHROME_BUILD
 #if defined(OS_MACOSX)
     {"enable-fullscreen-in-tab-detaching",
      flag_descriptions::kTabDetachingInFullscreenName,
@@ -2685,7 +2685,7 @@
      flag_descriptions::kCrossProcessGuestViewIsolationName,
      flag_descriptions::kCrossProcessGuestViewIsolationDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kGuestViewCrossProcessFrames)},
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
     {"media-remoting", flag_descriptions::kMediaRemotingName,
      flag_descriptions::kMediaRemotingDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kMediaRemoting)},
@@ -2726,9 +2726,9 @@
 #endif  // OS_ANDROID
 
 #if defined(OS_CHROMEOS)
-    {ui::devtools::kEnableUiDevTools, flag_descriptions::kUiDevToolsName,
+    {ui_devtools::kEnableUiDevTools, flag_descriptions::kUiDevToolsName,
      flag_descriptions::kUiDevToolsDescription, kOsCrOS,
-     SINGLE_VALUE_TYPE(ui::devtools::kEnableUiDevTools)},
+     SINGLE_VALUE_TYPE(ui_devtools::kEnableUiDevTools)},
 #endif  // defined(OS_CHROMEOS)
 
     {"enable-autofill-credit-card-last-used-date-display",
@@ -2978,7 +2978,7 @@
      flag_descriptions::kEnableHeapProfilingDescription, kOsAll,
      MULTI_VALUE_TYPE(kEnableHeapProfilingChoices)},
 
-#if defined(TOOLKIT_VIEWS) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
     {"show-cert-link", flag_descriptions::kShowCertLinkOnPageInfoName,
      flag_descriptions::kShowCertLinkOnPageInfoDescription, kOsDesktop,
      SINGLE_VALUE_TYPE(switches::kShowCertLink)},
@@ -3047,7 +3047,7 @@
      FEATURE_VALUE_TYPE(features::kD3DVsync)},
 #endif  // defined(OS_WIN)
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
     {"use-google-local-ntp", flag_descriptions::kUseGoogleLocalNtpName,
      flag_descriptions::kUseGoogleLocalNtpDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kUseGoogleLocalNtp)},
@@ -3056,7 +3056,7 @@
      flag_descriptions::kOneGoogleBarOnLocalNtpName,
      flag_descriptions::kOneGoogleBarOnLocalNtpDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kOneGoogleBarOnLocalNtp)},
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif  // !defined(OS_ANDROID)
 
 #if defined(OS_MACOSX)
     {"mac-rtl", flag_descriptions::kMacRTLName,
@@ -3071,12 +3071,12 @@
      SINGLE_DISABLE_VALUE_TYPE(switches::kDisableNewVirtualKeyboardBehavior)},
 #endif  // defined(OS_CHROMEOS)
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
     {"enable-picture-in-picture",
      flag_descriptions::kEnablePictureInPictureName,
      flag_descriptions::kEnablePictureInPictureDescription, kOsDesktop,
      SINGLE_VALUE_TYPE(switches::kEnablePictureInPicture)},
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif  // !defined(OS_ANDROID)
     {"browser-side-navigation", flag_descriptions::kBrowserSideNavigationName,
      flag_descriptions::kBrowserSideNavigationDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kBrowserSideNavigation)},
@@ -3146,7 +3146,7 @@
   }
 
   // enable-ui-devtools is only available on for non Stable channels.
-  if (!strcmp(ui::devtools::kEnableUiDevTools, entry.internal_name) &&
+  if (!strcmp(ui_devtools::kEnableUiDevTools, entry.internal_name) &&
       channel == version_info::Channel::STABLE) {
     return true;
   }
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
index 064d1bf8..41f846b 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -26,6 +26,7 @@
 #include "components/favicon_base/favicon_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/manifest_icon_selector.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/manifest.h"
@@ -97,7 +98,9 @@
   DCHECK(minimum_splash_image_size_in_px <= ideal_splash_image_size_in_px);
 
   // Send a message to the renderer to retrieve information about the page.
-  Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id()));
+  content::RenderFrameHost* main_frame = web_contents->GetMainFrame();
+  main_frame->Send(
+      new ChromeFrameMsg_GetWebApplicationInfo(main_frame->GetRoutingID()));
 }
 
 void AddToHomescreenDataFetcher::OnDidGetWebApplicationInfo(
@@ -166,14 +169,15 @@
 }
 
 bool AddToHomescreenDataFetcher::OnMessageReceived(
-    const IPC::Message& message) {
+    const IPC::Message& message,
+    content::RenderFrameHost* sender) {
   if (!is_waiting_for_web_application_info_)
     return false;
 
   bool handled = true;
 
   IPC_BEGIN_MESSAGE_MAP(AddToHomescreenDataFetcher, message)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo,
+    IPC_MESSAGE_HANDLER(ChromeFrameHostMsg_DidGetWebApplicationInfo,
                         OnDidGetWebApplicationInfo)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
index fa237db..4dc6b26 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.h
@@ -96,7 +96,8 @@
   ~AddToHomescreenDataFetcher() override;
 
   // WebContentsObserver:
-  bool OnMessageReceived(const IPC::Message& message) override;
+  bool OnMessageReceived(const IPC::Message& message,
+                         content::RenderFrameHost* sender) override;
 
   // Called if either InstallableManager or the favicon fetch takes too long.
   void OnDataTimedout();
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index aaa3649..875e77d 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -43,16 +43,16 @@
 #include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
 #include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
 
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
 namespace autofill {
 namespace {
 
-using ::base::android::ConvertJavaStringToUTF8;
-using ::base::android::ConvertUTF16ToJavaString;
-using ::base::android::ConvertUTF8ToJavaString;
-using ::base::android::JavaParamRef;
-using ::base::android::ScopedJavaGlobalRef;
-using ::base::android::ScopedJavaLocalRef;
-
 Profile* GetProfile() {
   return ProfileManager::GetActiveUserProfile()->GetOriginalProfile();
 }
@@ -95,9 +95,10 @@
     profile->SetRawInfo(type, ConvertJavaStringToUTF16(jstr));
 }
 
-void PopulateNativeProfileFromJava(const JavaParamRef<jobject>& jprofile,
-                                   JNIEnv* env,
-                                   AutofillProfile* profile) {
+void PopulateNativeProfileFromJava(
+    const JavaParamRef<jobject>& jprofile,
+    JNIEnv* env,
+    AutofillProfile* profile) {
   profile->set_origin(
       ConvertJavaStringToUTF8(Java_AutofillProfile_getOrigin(env, jprofile)));
   profile->SetInfo(
@@ -152,13 +153,14 @@
       ConvertUTF8ToJavaString(env,
                               payment_request_data.basic_card_issuer_network),
       ResourceMapper::MapFromChromiumId(payment_request_data.icon_resource_id),
-      card.card_type(), ConvertUTF8ToJavaString(env, card.billing_address_id()),
+      ConvertUTF8ToJavaString(env, card.billing_address_id()),
       ConvertUTF8ToJavaString(env, card.server_id()));
 }
 
-void PopulateNativeCreditCardFromJava(const jobject& jcard,
-                                      JNIEnv* env,
-                                      CreditCard* card) {
+void PopulateNativeCreditCardFromJava(
+    const jobject& jcard,
+    JNIEnv* env,
+    CreditCard* card) {
   card->set_origin(
       ConvertJavaStringToUTF8(Java_CreditCard_getOrigin(env, jcard)));
   card->SetRawInfo(
@@ -178,11 +180,6 @@
   card->set_server_id(
       ConvertJavaStringToUTF8(Java_CreditCard_getServerId(env, jcard)));
 
-  jint card_type = Java_CreditCard_getCardType(env, jcard);
-  DCHECK_GE(CreditCard::CARD_TYPE_PREPAID, card_type);
-  DCHECK_LE(CreditCard::CARD_TYPE_UNKNOWN, card_type);
-  card->set_card_type(static_cast<CreditCard::CardType>(card_type));
-
   // Only set the guid if it is an existing card (java guid not empty).
   // Otherwise, keep the generated one.
   std::string guid =
@@ -377,7 +374,8 @@
     const JavaParamRef<jobject>& unused_obj,
     const JavaParamRef<jobject>& jprofile) {
   std::string guid = ConvertJavaStringToUTF8(
-      env, Java_AutofillProfile_getGUID(env, jprofile).obj());
+      env,
+      Java_AutofillProfile_getGUID(env, jprofile).obj());
 
   AutofillProfile profile;
   PopulateNativeProfileFromJava(jprofile, env, &profile);
@@ -501,7 +499,7 @@
     const JavaParamRef<jobject>& unused_obj,
     const JavaParamRef<jstring>& jguid) {
   CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
-      ConvertJavaStringToUTF8(env, jguid));
+          ConvertJavaStringToUTF8(env, jguid));
   if (!card)
     return ScopedJavaLocalRef<jobject>();
 
@@ -522,8 +520,9 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& unused_obj,
     const JavaParamRef<jobject>& jcard) {
-  std::string guid =
-      ConvertJavaStringToUTF8(env, Java_CreditCard_getGUID(env, jcard).obj());
+  std::string guid = ConvertJavaStringToUTF8(
+       env,
+       Java_CreditCard_getGUID(env, jcard).obj());
 
   CreditCard card;
   PopulateNativeCreditCardFromJava(jcard, env, &card);
@@ -569,7 +568,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& unused_obj,
     const base::android::JavaParamRef<jobject>& jcard) {
-  std::unique_ptr<CreditCard> card = base::MakeUnique<CreditCard>();
+  std::unique_ptr<CreditCard> card(new CreditCard);
   PopulateNativeCreditCardFromJava(jcard, env, card.get());
   card->set_record_type(CreditCard::MASKED_SERVER_CARD);
   personal_data_manager_->AddServerCreditCardForTest(std::move(card));
@@ -597,11 +596,11 @@
     const JavaParamRef<jobject>& jweb_contents,
     const JavaParamRef<jobject>& jcard,
     const JavaParamRef<jobject>& jdelegate) {
-  std::unique_ptr<CreditCard> card = base::MakeUnique<CreditCard>();
+  std::unique_ptr<CreditCard> card(new CreditCard);
   PopulateNativeCreditCardFromJava(jcard, env, card.get());
   // Self-deleting object.
-  (new FullCardRequester())
-      ->GetFullCard(env, jweb_contents, jdelegate, std::move(card));
+  (new FullCardRequester())->GetFullCard(
+      env, jweb_contents, jdelegate, std::move(card));
 }
 
 void PersonalDataManagerAndroid::OnPersonalDataChanged() {
@@ -816,7 +815,7 @@
   std::unique_ptr<std::vector<ServerFieldType>> suggested_fields;
   size_t minimal_fields_shown = 2;
   if (address_only) {
-    suggested_fields = base::MakeUnique<std::vector<ServerFieldType>>();
+    suggested_fields.reset(new std::vector<ServerFieldType>);
     if (include_name_in_label)
       suggested_fields->push_back(NAME_FULL);
     if (include_organization_in_label)
diff --git a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc
index b9281da..7e40824 100644
--- a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc
+++ b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/json/json_reader.h"
 #include "base/macros.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
@@ -60,6 +61,11 @@
       bool is_uploading,
       prefs::PreviousSaveCreditCardPromptUserDecision
           previous_save_credit_card_prompt_user_decision);
+  std::unique_ptr<ConfirmInfoBarDelegate> CreateDelegateWithLegalMessage(
+      bool is_uploading,
+      std::string legal_message_string,
+      prefs::PreviousSaveCreditCardPromptUserDecision
+          previous_save_credit_card_prompt_user_decision);
 
   std::unique_ptr<TestPersonalDataManager> personal_data_;
 
@@ -101,9 +107,26 @@
     bool is_uploading,
     prefs::PreviousSaveCreditCardPromptUserDecision
         previous_save_credit_card_prompt_user_decision) {
-  base::HistogramTester histogram_tester;
+  return CreateDelegateWithLegalMessage(
+      is_uploading, "", previous_save_credit_card_prompt_user_decision);
+}
+
+std::unique_ptr<ConfirmInfoBarDelegate>
+AutofillSaveCardInfoBarDelegateMobileTest::CreateDelegateWithLegalMessage(
+    bool is_uploading,
+    std::string legal_message_string,
+    prefs::PreviousSaveCreditCardPromptUserDecision
+        previous_save_credit_card_prompt_user_decision) {
   CreditCard credit_card;
   std::unique_ptr<base::DictionaryValue> legal_message;
+  if (!legal_message_string.empty()) {
+    std::unique_ptr<base::Value> value(
+        base::JSONReader::Read(legal_message_string));
+    EXPECT_TRUE(value);
+    base::DictionaryValue* dictionary;
+    EXPECT_TRUE(value->GetAsDictionary(&dictionary));
+    legal_message = dictionary->CreateDeepCopy();
+  }
   std::unique_ptr<ConfirmInfoBarDelegate> delegate(
       new AutofillSaveCardInfoBarDelegateMobile(
           is_uploading, credit_card, std::move(legal_message),
@@ -125,9 +148,6 @@
                 prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE);
       break;
   }
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.CreditCardInfoBar" + destination + previous_response,
-      AutofillMetrics::INFOBAR_SHOWN, 1);
   return delegate;
 }
 
@@ -135,17 +155,29 @@
 TEST_F(AutofillSaveCardInfoBarDelegateMobileTest, Metrics_Local) {
   ::testing::InSequence dummy;
 
+  // Infobar is shown.
+  {
+    base::HistogramTester histogram_tester;
+    std::unique_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate(
+        /* is_uploading= */ false,
+        prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE));
+
+    histogram_tester.ExpectUniqueSample("Autofill.CreditCardInfoBar.Local",
+                                        AutofillMetrics::INFOBAR_SHOWN, 1);
+  }
+
   // Accept the infobar.
   {
     std::unique_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate(
         /* is_uploading= */ false,
-        prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE));
+        prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED));
     EXPECT_CALL(*personal_data_, SaveImportedCreditCard(_));
 
     base::HistogramTester histogram_tester;
     EXPECT_TRUE(infobar->Accept());
-    histogram_tester.ExpectUniqueSample("Autofill.CreditCardInfoBar.Local",
-                                        AutofillMetrics::INFOBAR_ACCEPTED, 1);
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.CreditCardInfoBar.Local.PreviouslyDenied",
+        AutofillMetrics::INFOBAR_ACCEPTED, 1);
   }
 
   // Cancel the infobar.
@@ -192,6 +224,59 @@
 TEST_F(AutofillSaveCardInfoBarDelegateMobileTest, Metrics_Server) {
   ::testing::InSequence dummy;
 
+  // Infobar is shown.
+  {
+    base::HistogramTester histogram_tester;
+    std::unique_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate(
+        /* is_uploading= */ true,
+        prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE));
+
+    histogram_tester.ExpectUniqueSample("Autofill.CreditCardInfoBar.Server",
+                                        AutofillMetrics::INFOBAR_SHOWN, 1);
+  }
+
+  // Infobar is still shown when the legal message is successfully parsed.
+  {
+    base::HistogramTester histogram_tester;
+    std::string good_legal_message =
+        "{"
+        "  \"line\" : [ {"
+        "     \"template\": \"This is the entire message.\""
+        "  } ]"
+        "}";
+    std::unique_ptr<ConfirmInfoBarDelegate> infobar(
+        CreateDelegateWithLegalMessage(
+            /* is_uploading= */ true, std::move(good_legal_message),
+            prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED));
+
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.CreditCardInfoBar.Server.PreviouslyDenied",
+        AutofillMetrics::INFOBAR_SHOWN, 1);
+  }
+
+  // Infobar is not shown because the provided legal message is invalid.
+  {
+    base::HistogramTester histogram_tester;
+    // Legal message is invalid because it's missing the url.
+    std::string bad_legal_message =
+        "{"
+        "  \"line\" : [ {"
+        "     \"template\": \"Panda {0}.\","
+        "     \"template_parameter\": [ {"
+        "        \"display_text\": \"bear\""
+        "     } ]"
+        "  } ]"
+        "}";
+    std::unique_ptr<ConfirmInfoBarDelegate> infobar(
+        CreateDelegateWithLegalMessage(
+            /* is_uploading= */ true, std::move(bad_legal_message),
+            prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED));
+
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.CreditCardInfoBar.Server.PreviouslyDenied",
+        AutofillMetrics::INFOBAR_NOT_SHOWN_INVALID_LEGAL_MESSAGE, 1);
+  }
+
   // Accept the infobar.
   {
     std::unique_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate(
@@ -201,8 +286,9 @@
 
     base::HistogramTester histogram_tester;
     EXPECT_TRUE(infobar->Accept());
-    histogram_tester.ExpectUniqueSample("Autofill.CreditCardInfoBar.Server",
-                                        AutofillMetrics::INFOBAR_ACCEPTED, 1);
+    histogram_tester.ExpectUniqueSample(
+        "Autofill.CreditCardInfoBar.Server.PreviouslyDenied",
+        AutofillMetrics::INFOBAR_ACCEPTED, 1);
   }
 
   // Cancel the infobar.
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index c9c6d7c..5f9cd96 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -469,18 +469,14 @@
   ProfileManager* pm = profile_manager();
   std::vector<Profile*> profiles(pm->GetLoadedProfiles());
   scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter());
-  const bool pref_service_enabled =
-      base::FeatureList::IsEnabled(features::kPrefService);
   std::vector<scoped_refptr<base::SequencedTaskRunner>> profile_writer_runners;
   for (size_t i = 0; i < profiles.size(); ++i) {
     Profile* profile = profiles[i];
     profile->SetExitType(Profile::EXIT_SESSION_ENDED);
     if (profile->GetPrefs()) {
       profile->GetPrefs()->CommitPendingWrite();
-      if (pref_service_enabled) {
-        rundown_counter->Post(content::BrowserThread::GetTaskRunnerForThread(
-                                  content::BrowserThread::IO)
-                                  .get());
+      if (profile->GetPrefServiceTaskRunner()) {
+        rundown_counter->Post(profile->GetPrefServiceTaskRunner().get());
         profile_writer_runners.push_back(profile->GetIOTaskRunner());
       } else {
         rundown_counter->Post(profile->GetIOTaskRunner().get());
@@ -527,7 +523,7 @@
   // http://crbug.com/318527.
   const base::TimeTicks end_time = base::TimeTicks::Now() + kEndSessionTimeout;
   const bool timed_out = !rundown_counter->TimedWaitUntil(end_time);
-  if (timed_out || !pref_service_enabled)
+  if (timed_out || !base::FeatureList::IsEnabled(features::kPrefService))
     return;
 
   scoped_refptr<RundownTaskCounter> profile_write_rundown_counter(
diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h
index f4cfa59c..b00bac9 100644
--- a/chrome/browser/chrome_browser_main.h
+++ b/chrome/browser/chrome_browser_main.h
@@ -145,7 +145,7 @@
 
   ChromeBrowserFieldTrials browser_field_trials_;
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
   std::unique_ptr<WebUsbDetector> web_usb_detector_;
 #endif
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index ae7e6c6..f6c6bcb 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -840,9 +840,16 @@
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
-void CreateUsbDeviceManager(RenderFrameHost* render_frame_host,
-                            const service_manager::BindSourceInfo& source_info,
-                            device::mojom::UsbDeviceManagerRequest request) {
+void CreateUsbDeviceManager(const service_manager::BindSourceInfo& source_info,
+                            device::mojom::UsbDeviceManagerRequest request,
+                            content::RenderFrameHost* render_frame_host) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  if (render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs(
+          extensions::kExtensionScheme)) {
+    return;
+  }
+#endif
+
   WebContents* web_contents =
       WebContents::FromRenderFrameHost(render_frame_host);
   if (!web_contents) {
@@ -856,9 +863,16 @@
 }
 
 void CreateWebUsbChooserService(
-    RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    device::mojom::UsbChooserServiceRequest request) {
+    device::mojom::UsbChooserServiceRequest request,
+    content::RenderFrameHost* render_frame_host) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  if (render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs(
+          extensions::kExtensionScheme)) {
+    return;
+  }
+#endif
+
   WebContents* web_contents =
       WebContents::FromRenderFrameHost(render_frame_host);
   if (!web_contents) {
@@ -1605,26 +1619,23 @@
 }
 
 #if defined(OS_ANDROID)
-void ForwardInstalledAppProviderRequest(
-    base::WeakPtr<service_manager::InterfaceProvider> interface_provider,
+template <typename Interface>
+void ForwardToJavaFrameRegistry(
     const service_manager::BindSourceInfo& source_info,
-    blink::mojom::InstalledAppProviderRequest request) {
-  if (!interface_provider ||
-      ChromeOriginTrialPolicy().IsFeatureDisabled("InstalledApp")) {
-    return;
-  }
-  interface_provider->GetInterface(std::move(request));
+    mojo::InterfaceRequest<Interface> request,
+    content::RenderFrameHost* render_frame_host) {
+  render_frame_host->GetJavaInterfaces()->GetInterface(std::move(request));
 }
 
-void ForwardShareServiceRequest(
-    base::WeakPtr<service_manager::InterfaceProvider> interface_provider,
+template <typename Interface>
+void ForwardToJavaWebContentsRegistry(
     const service_manager::BindSourceInfo& source_info,
-    blink::mojom::ShareServiceRequest request) {
-  if (!interface_provider ||
-      ChromeOriginTrialPolicy().IsFeatureDisabled("WebShare")) {
-    return;
-  }
-  interface_provider->GetInterface(std::move(request));
+    mojo::InterfaceRequest<Interface> request,
+    content::RenderFrameHost* render_frame_host) {
+  content::WebContents* contents =
+      content::WebContents::FromRenderFrameHost(render_frame_host);
+  if (contents)
+    contents->GetJavaInterfaces()->GetInterface(std::move(request));
 }
 #endif
 
@@ -3007,79 +3018,22 @@
 #endif  // BUILDFLAG(ENABLE_MOJO_MEDIA)
 }
 
-void ChromeContentBrowserClient::ExposeInterfacesToFrame(
-    service_manager::BinderRegistry* registry,
-    content::RenderFrameHost* render_frame_host) {
-  if (base::FeatureList::IsEnabled(features::kWebUsb)
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-      &&
-      !render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs(
-          extensions::kExtensionScheme)
-#endif
-          ) {
-    registry->AddInterface(
-        base::Bind(&CreateUsbDeviceManager, render_frame_host));
-    registry->AddInterface(
-        base::Bind(&CreateWebUsbChooserService, render_frame_host));
+void ChromeContentBrowserClient::BindInterfaceRequestFromFrame(
+    content::RenderFrameHost* render_frame_host,
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  if (!frame_interfaces_.get() && !frame_interfaces_parameterized_.get())
+    InitFrameInterfaces();
+
+  if (frame_interfaces_parameterized_->CanBindInterface(interface_name)) {
+    frame_interfaces_parameterized_->BindInterface(source_info, interface_name,
+                                                   std::move(interface_pipe),
+                                                   render_frame_host);
+  } else if (frame_interfaces_->CanBindInterface(interface_name)) {
+    frame_interfaces_->BindInterface(source_info, interface_name,
+                                     std::move(interface_pipe));
   }
-
-  registry->AddInterface<bluetooth::mojom::AdapterFactory>(
-      base::Bind(&bluetooth::AdapterFactory::Create));
-
-  if (!render_frame_host->GetParent()) {
-    // Register mojo CredentialManager interface only for main frame.
-    registry->AddInterface(
-        base::Bind(&ChromePasswordManagerClient::BindCredentialManager,
-                   render_frame_host));
-    // Register mojo ContentTranslateDriver interface only for main frame.
-    registry->AddInterface(base::Bind(
-        &ChromeTranslateClient::BindContentTranslateDriver, render_frame_host));
-  }
-
-  registry->AddInterface(
-      base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver,
-                 render_frame_host));
-
-  registry->AddInterface(
-      base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
-                     BindPasswordManagerDriver,
-                 render_frame_host));
-
-  registry->AddInterface(
-      base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
-                     BindSensitiveInputVisibilityService,
-                 render_frame_host));
-
-#if defined(OS_ANDROID)
-  registry->AddInterface(
-      render_frame_host->GetJavaInterfaces()
-          ->CreateInterfaceFactory<payments::mojom::PaymentRequest>());
-  registry->AddInterface(
-      base::Bind(&ForwardInstalledAppProviderRequest,
-                 render_frame_host->GetJavaInterfaces()->GetWeakPtr()));
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host);
-  if (web_contents) {
-    registry->AddInterface(
-        base::Bind(&ForwardShareServiceRequest,
-                   web_contents->GetJavaInterfaces()->GetWeakPtr()));
-  }
-#else
-  if (base::FeatureList::IsEnabled(features::kWebPayments)) {
-    content::WebContents* web_contents =
-        content::WebContents::FromRenderFrameHost(render_frame_host);
-    if (web_contents) {
-      registry->AddInterface(base::Bind(payments::CreatePaymentRequest,
-                                        render_frame_host, web_contents));
-    }
-  }
-#endif
-
-#if defined(OS_LINUX) || defined(OS_WIN)
-  if (!ChromeOriginTrialPolicy().IsFeatureDisabled("WebShare")) {
-    registry->AddInterface(base::Bind(&ShareServiceImpl::Create));
-  }
-#endif
 }
 
 void ChromeContentBrowserClient::BindInterfaceRequest(
@@ -3398,6 +3352,59 @@
   }
 }
 
+void ChromeContentBrowserClient::InitFrameInterfaces() {
+  frame_interfaces_ = base::MakeUnique<service_manager::BinderRegistry>();
+  frame_interfaces_parameterized_ = base::MakeUnique<
+      service_manager::BinderRegistryWithParams<content::RenderFrameHost*>>();
+
+  if (base::FeatureList::IsEnabled(features::kWebUsb)) {
+    frame_interfaces_parameterized_->AddInterface(
+        base::Bind(&CreateUsbDeviceManager));
+    frame_interfaces_parameterized_->AddInterface(
+        base::Bind(&CreateWebUsbChooserService));
+  }
+
+  frame_interfaces_->AddInterface<bluetooth::mojom::AdapterFactory>(
+      base::Bind(&bluetooth::AdapterFactory::Create));
+
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&ChromePasswordManagerClient::BindCredentialManager));
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&ChromeTranslateClient::BindContentTranslateDriver));
+
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver));
+
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
+                     BindPasswordManagerDriver));
+
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&password_manager::ContentPasswordManagerDriverFactory::
+                     BindSensitiveInputVisibilityService));
+
+#if defined(OS_ANDROID)
+  frame_interfaces_parameterized_->AddInterface(base::Bind(
+      &ForwardToJavaWebContentsRegistry<blink::mojom::InstalledAppProvider>));
+  frame_interfaces_parameterized_->AddInterface(
+      base::Bind(&ForwardToJavaFrameRegistry<payments::mojom::PaymentRequest>));
+#else
+  if (base::FeatureList::IsEnabled(features::kWebPayments)) {
+    frame_interfaces_parameterized_->AddInterface(
+        base::Bind(&payments::CreatePaymentRequest));
+  }
+#endif
+
+  if (!ChromeOriginTrialPolicy().IsFeatureDisabled("WebShare")) {
+#if defined(OS_ANDROID)
+    frame_interfaces_parameterized_->AddInterface(base::Bind(
+        &ForwardToJavaWebContentsRegistry<blink::mojom::ShareService>));
+#elif defined(OS_LINUX) || defined(OS_WIN)
+    frame_interfaces_->AddInterface(base::Bind(&ShareServiceImpl::Create));
+#endif
+  }
+}
+
 #if BUILDFLAG(ENABLE_WEBRTC)
 void ChromeContentBrowserClient::MaybeCopyDisableWebRtcEncryptionSwitch(
     base::CommandLine* to_command_line,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index dcb08879..df9919aa 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -280,9 +280,11 @@
   void ExposeInterfacesToMediaService(
       service_manager::BinderRegistry* registry,
       content::RenderFrameHost* render_frame_host) override;
-  void ExposeInterfacesToFrame(
-      service_manager::BinderRegistry* registry,
-      content::RenderFrameHost* render_frame_host) override;
+  void BindInterfaceRequestFromFrame(
+      content::RenderFrameHost* render_frame_host,
+      const service_manager::BindSourceInfo& source_info,
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle interface_pipe) override;
   void BindInterfaceRequest(
       const service_manager::BindSourceInfo& source_info,
       const std::string& interface_name,
@@ -330,6 +332,9 @@
   friend class DisableWebRtcEncryptionFlagTest;
   friend class InProcessBrowserTest;
 
+  // Populate |frame_interfaces_|.
+  void InitFrameInterfaces();
+
 #if BUILDFLAG(ENABLE_WEBRTC)
   // Copies disable WebRTC encryption switch depending on the channel.
   static void MaybeCopyDisableWebRtcEncryptionSwitch(
@@ -382,6 +387,11 @@
 
   scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service_;
 
+  std::unique_ptr<service_manager::BinderRegistry> frame_interfaces_;
+  std::unique_ptr<
+      service_manager::BinderRegistryWithParams<content::RenderFrameHost*>>
+      frame_interfaces_parameterized_;
+
   base::WeakPtrFactory<ChromeContentBrowserClient> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClient);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f5ebb2fb..67d6bfc 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -956,6 +956,9 @@
     "login/screens/voice_interaction_value_prop_screen.cc",
     "login/screens/voice_interaction_value_prop_screen.h",
     "login/screens/voice_interaction_value_prop_screen_view.h",
+    "login/screens/wait_for_container_ready_screen.cc",
+    "login/screens/wait_for_container_ready_screen.h",
+    "login/screens/wait_for_container_ready_screen_view.h",
     "login/screens/wrong_hwid_screen.cc",
     "login/screens/wrong_hwid_screen.h",
     "login/screens/wrong_hwid_screen_view.h",
diff --git a/chrome/browser/chromeos/login/oobe_screen.cc b/chrome/browser/chromeos/login/oobe_screen.cc
index d140857..0add6c67 100644
--- a/chrome/browser/chromeos/login/oobe_screen.cc
+++ b/chrome/browser/chromeos/login/oobe_screen.cc
@@ -46,6 +46,7 @@
     "ad-password-change",
     "encryption-migration",          // SCREEN_ENCRYPTION_MIGRATION
     "voice-interaction-value-prop",  // SCREEN_VOICE_INTERACTION_VALUE_PROP
+    "wait-for-container-ready",      // SCREEN_WAIT_FOR_CONTAINTER_READY
     "login",                         // SCREEN_SPECIAL_LOGIN
     "oobe",                          // SCREEN_SPECIAL_OOBE
     "test:nowindow",                 // SCREEN_TEST_NO_WINDOW
diff --git a/chrome/browser/chromeos/login/oobe_screen.h b/chrome/browser/chromeos/login/oobe_screen.h
index bdacc3e..e1877f48 100644
--- a/chrome/browser/chromeos/login/oobe_screen.h
+++ b/chrome/browser/chromeos/login/oobe_screen.h
@@ -47,6 +47,7 @@
   SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE,
   SCREEN_ENCRYPTION_MIGRATION,
   SCREEN_VOICE_INTERACTION_VALUE_PROP,
+  SCREEN_WAIT_FOR_CONTAINER_READY,
 
   // Special "first screen" that initiates login flow.
   SCREEN_SPECIAL_LOGIN,
diff --git a/chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.cc b/chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.cc
index 0e6c56d..168fffb 100644
--- a/chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.cc
+++ b/chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.cc
@@ -54,6 +54,7 @@
 void ArcTermsOfServiceScreen::OnViewDestroyed(
     ArcTermsOfServiceScreenView* view) {
   DCHECK_EQ(view, view_);
+  view_->RemoveObserver(this);
   view_ = nullptr;
 }
 
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.cc b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
index 0acb7054..711b3808 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.cc
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
@@ -64,6 +64,8 @@
       return "VOICE_INTERACTION_VALUE_PROP_SKIPPED";
     case ScreenExitCode::VOICE_INTERACTION_VALUE_PROP_ACCEPTED:
       return "VOICE_INTERACTION_VALUE_PROP_ACCEPTED";
+    case ScreenExitCode::WAIT_FOR_CONTAINER_READY_FINISHED:
+      return "WAIT_FOR_CONTAINER_READY_FINISHED";
     case ScreenExitCode::EXIT_CODES_COUNT:
     default:
       NOTREACHED();
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.h b/chrome/browser/chromeos/login/screens/screen_exit_code.h
index 7742e348b..7b87545 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.h
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.h
@@ -53,6 +53,7 @@
   ENCRYPTION_MIGRATION_SKIPPED = 26,
   VOICE_INTERACTION_VALUE_PROP_SKIPPED = 27,
   VOICE_INTERACTION_VALUE_PROP_ACCEPTED = 28,
+  WAIT_FOR_CONTAINER_READY_FINISHED = 29,
   EXIT_CODES_COUNT  // not a real code, must be the last
 };
 
diff --git a/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.cc b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.cc
new file mode 100644
index 0000000..031fcdd
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.cc
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h"
+
+#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen_view.h"
+
+namespace chromeos {
+
+WaitForContainerReadyScreen::WaitForContainerReadyScreen(
+    BaseScreenDelegate* base_screen_delegate,
+    WaitForContainerReadyScreenView* view)
+    : BaseScreen(base_screen_delegate,
+                 OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY),
+      view_(view) {
+  DCHECK(view_);
+  if (view_)
+    view_->Bind(this);
+}
+
+WaitForContainerReadyScreen::~WaitForContainerReadyScreen() {
+  if (view_)
+    view_->Unbind();
+}
+
+void WaitForContainerReadyScreen::Show() {
+  if (!view_)
+    return;
+
+  view_->Show();
+}
+
+void WaitForContainerReadyScreen::Hide() {
+  if (view_)
+    view_->Hide();
+}
+
+void WaitForContainerReadyScreen::OnViewDestroyed(
+    WaitForContainerReadyScreenView* view) {
+  if (view_ == view)
+    view_ = nullptr;
+}
+
+void WaitForContainerReadyScreen::OnContainerReady() {
+  Finish(ScreenExitCode::WAIT_FOR_CONTAINER_READY_FINISHED);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h
new file mode 100644
index 0000000..2901882
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/login/screens/base_screen.h"
+
+namespace chromeos {
+
+class WaitForContainerReadyScreenView;
+class BaseScreenDelegate;
+
+class WaitForContainerReadyScreen : public BaseScreen {
+ public:
+  WaitForContainerReadyScreen(BaseScreenDelegate* base_screen_delegate,
+                              WaitForContainerReadyScreenView* view);
+  ~WaitForContainerReadyScreen() override;
+
+  // BaseScreen:
+  void Show() override;
+  void Hide() override;
+
+  // Called when view is destroyed so there's no dead reference to it.
+  void OnViewDestroyed(WaitForContainerReadyScreenView* view_);
+
+  // Called when the container is ready, exit the screen.
+  void OnContainerReady();
+
+ private:
+  WaitForContainerReadyScreenView* view_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaitForContainerReadyScreen);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen_view.h b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen_view.h
new file mode 100644
index 0000000..a9f67cd
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/wait_for_container_ready_screen_view.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_VIEW_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_VIEW_H_
+
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+
+namespace chromeos {
+
+class WaitForContainerReadyScreen;
+
+// Interface for dependency injection between WaitForContainerReadyScreen
+// and its WebUI representation.
+class WaitForContainerReadyScreenView {
+ public:
+  constexpr static OobeScreen kScreenId =
+      OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY;
+
+  virtual ~WaitForContainerReadyScreenView() {}
+
+  virtual void Bind(WaitForContainerReadyScreen* screen) = 0;
+  virtual void Unbind() = 0;
+  virtual void Show() = 0;
+  virtual void Hide() = 0;
+
+ protected:
+  WaitForContainerReadyScreenView() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WaitForContainerReadyScreenView);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WAIT_FOR_CONTAINER_READY_SCREEN_VIEW_H_
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 6389ac8..da28bd5 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -55,6 +55,7 @@
 #include "chrome/browser/chromeos/login/screens/update_screen.h"
 #include "chrome/browser/chromeos/login/screens/user_image_screen.h"
 #include "chrome/browser/chromeos/login/screens/voice_interaction_value_prop_screen.h"
+#include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h"
 #include "chrome/browser/chromeos/login/screens/wrong_hwid_screen.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
@@ -436,6 +437,9 @@
   } else if (screen == OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP) {
     return new VoiceInteractionValuePropScreen(
         this, oobe_ui_->GetVoiceInteractionValuePropScreenView());
+  } else if (screen == OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY) {
+    return new WaitForContainerReadyScreen(
+        this, oobe_ui_->GetWaitForContainerReadyScreenView());
   }
 
   return nullptr;
@@ -644,6 +648,12 @@
   }
 }
 
+void WizardController::ShowWaitForContainerReadyScreen() {
+  UpdateStatusAreaVisibilityForScreen(
+      OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY);
+  SetCurrentScreen(GetScreen(OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY));
+}
+
 void WizardController::SkipToLoginForTesting(
     const LoginScreenContext& context) {
   VLOG(1) << "SkipToLoginForTesting.";
@@ -855,8 +865,12 @@
     ShowArcTermsOfServiceScreen();
     return;
   }
-  StartVoiceInteractionSetupWizard();
+  ShowWaitForContainerReadyScreen();
+}
+
+void WizardController::OnWaitForContainerReadyFinished() {
   OnOobeFlowFinished();
+  StartVoiceInteractionSetupWizard();
 }
 
 void WizardController::OnControllerPairingFinished() {
@@ -1124,6 +1138,8 @@
     ShowEncryptionMigrationScreen();
   } else if (screen == OobeScreen::SCREEN_VOICE_INTERACTION_VALUE_PROP) {
     ShowVoiceInteractionValuePropScreen();
+  } else if (screen == OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY) {
+    ShowWaitForContainerReadyScreen();
   } else if (screen != OobeScreen::SCREEN_TEST_NO_WINDOW) {
     if (is_out_of_box_) {
       time_oobe_started_ = base::Time::Now();
@@ -1238,6 +1254,9 @@
     case ScreenExitCode::VOICE_INTERACTION_VALUE_PROP_ACCEPTED:
       OnVoiceInteractionValuePropAccepted();
       break;
+    case ScreenExitCode::WAIT_FOR_CONTAINER_READY_FINISHED:
+      OnWaitForContainerReadyFinished();
+      break;
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index e39bdd64..20d66f63 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -153,6 +153,7 @@
   void ShowDeviceDisabledScreen();
   void ShowEncryptionMigrationScreen();
   void ShowVoiceInteractionValuePropScreen();
+  void ShowWaitForContainerReadyScreen();
 
   // Shows images login screen.
   void ShowLoginScreen(const LoginScreenContext& context);
@@ -182,6 +183,7 @@
   void OnVoiceInteractionValuePropAccepted();
   void OnControllerPairingFinished();
   void OnAutoEnrollmentCheckCompleted();
+  void OnWaitForContainerReadyFinished();
   void OnOobeFlowFinished();
 
   // Callback invoked once it has been determined whether the device is disabled
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index e183986..4d1c9e3 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -1348,8 +1348,8 @@
 // TODO(fukino): Add tests for encryption migration UI.
 // http://crbug.com/706017
 
-// TODO(updowndota): Add tests for Voice Interaction value prop flow.
-static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 29,
+// TODO(updowndota): Add tests for Voice Interaction OptIn flow.
+static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 30,
               "tests for new control flow are missing");
 
 }  // namespace chromeos
diff --git a/chrome/browser/component_updater/recovery_improved_component_installer.cc b/chrome/browser/component_updater/recovery_improved_component_installer.cc
index 3fdf6652..8559141 100644
--- a/chrome/browser/component_updater/recovery_improved_component_installer.cc
+++ b/chrome/browser/component_updater/recovery_improved_component_installer.cc
@@ -16,11 +16,11 @@
 namespace component_updater {
 
 // The SHA256 of the SubjectPublicKeyInfo used to sign the component CRX.
-// The component id is: iddcipcljjhfegcfaaaapdilddpplalp
+// The component id is: gjpmebpgbhcamgdgjcmnjfhggjpgcimm
 constexpr uint8_t kPublicKeySHA256[32] = {
-    0x83, 0x32, 0x8f, 0x2b, 0x99, 0x75, 0x46, 0x25, 0x00, 0x00, 0xf3,
-    0x8b, 0x33, 0xff, 0xb0, 0xbf, 0xea, 0xea, 0x19, 0xb3, 0x38, 0xfb,
-    0xdc, 0xb3, 0x28, 0x90, 0x5f, 0xe2, 0xbe, 0x28, 0x89, 0x11};
+    0x69, 0xfc, 0x41, 0xf6, 0x17, 0x20, 0xc6, 0x36, 0x92, 0xcd, 0x95,
+    0x76, 0x69, 0xf6, 0x28, 0xcc, 0xbe, 0x98, 0x4b, 0x93, 0x17, 0xd6,
+    0x9c, 0xb3, 0x64, 0x0c, 0x0d, 0x25, 0x61, 0xc5, 0x80, 0x1d};
 
 RecoveryImprovedInstallerTraits::RecoveryImprovedInstallerTraits(
     PrefService* prefs)
diff --git a/chrome/browser/download/download_commands.h b/chrome/browser/download/download_commands.h
index 06fb554..e107574 100644
--- a/chrome/browser/download/download_commands.h
+++ b/chrome/browser/download/download_commands.h
@@ -42,8 +42,7 @@
   bool IsCommandVisible(Command command) const;
   void ExecuteCommand(Command command);
 
-#if defined(OS_WIN) || defined(OS_LINUX) || \
-    (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
   bool IsDownloadPdf() const;
   bool CanOpenPdfInSystemViewer() const;
 #endif
diff --git a/chrome/browser/extensions/bookmark_app_helper_browsertest.cc b/chrome/browser/extensions/bookmark_app_helper_browsertest.cc
index 065080e..09a2f51 100644
--- a/chrome/browser/extensions/bookmark_app_helper_browsertest.cc
+++ b/chrome/browser/extensions/bookmark_app_helper_browsertest.cc
@@ -52,7 +52,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppHelper);
 };
 
-// Intercepts the ChromeViewHostMsg_DidGetWebApplicationInfo that would usually
+// Intercepts the ChromeFrameHostMsg_DidGetWebApplicationInfo that would usually
 // get sent to extensions::TabHelper to create a BookmarkAppHelper that lets us
 // detect when icons are downloaded and the dialog is ready to show.
 class WebAppReadyMsgWatcher : public content::BrowserMessageFilter {
@@ -96,14 +96,14 @@
   // BrowserMessageFilter:
   void OverrideThreadForMessage(const IPC::Message& message,
                                 content::BrowserThread::ID* thread) override {
-    if (message.type() == ChromeViewHostMsg_DidGetWebApplicationInfo::ID)
+    if (message.type() == ChromeFrameHostMsg_DidGetWebApplicationInfo::ID)
       *thread = content::BrowserThread::UI;
   }
 
   bool OnMessageReceived(const IPC::Message& message) override {
     bool handled = true;
     IPC_BEGIN_MESSAGE_MAP(WebAppReadyMsgWatcher, message)
-      IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo,
+      IPC_MESSAGE_HANDLER(ChromeFrameHostMsg_DidGetWebApplicationInfo,
                           OnDidGetWebApplicationInfo)
       IPC_MESSAGE_UNHANDLED(handled = false)
     IPC_END_MESSAGE_MAP()
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index 0f077ca..05c9ff4 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -332,20 +332,12 @@
     ExtensionActionAPI::Get(context)->ClearAllValuesForTab(web_contents());
 }
 
-bool TabHelper::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(TabHelper, message)
-    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidGetWebApplicationInfo,
-                        OnDidGetWebApplicationInfo)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
 bool TabHelper::OnMessageReceived(const IPC::Message& message,
-                                  content::RenderFrameHost* render_frame_host) {
+                                  content::RenderFrameHost* sender) {
   bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(TabHelper, message, render_frame_host)
+  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(TabHelper, message, sender)
+    IPC_MESSAGE_HANDLER(ChromeFrameHostMsg_DidGetWebApplicationInfo,
+                        OnDidGetWebApplicationInfo)
     IPC_MESSAGE_HANDLER(ExtensionHostMsg_GetAppInstallState,
                         OnGetAppInstallState)
     IPC_MESSAGE_HANDLER(ExtensionHostMsg_ContentScriptsExecuting,
@@ -366,7 +358,8 @@
   new_helper->extension_app_icon_ = extension_app_icon_;
 }
 
-void TabHelper::OnDidGetWebApplicationInfo(const WebApplicationInfo& info) {
+void TabHelper::OnDidGetWebApplicationInfo(content::RenderFrameHost* sender,
+                                           const WebApplicationInfo& info) {
   web_app_info_ = info;
 
   NavigationEntry* entry =
@@ -624,7 +617,9 @@
   pending_web_app_action_ = action;
   last_committed_nav_entry_unique_id_ = entry->GetUniqueID();
 
-  Send(new ChromeViewMsg_GetWebApplicationInfo(routing_id()));
+  content::RenderFrameHost* main_frame = web_contents()->GetMainFrame();
+  main_frame->Send(
+      new ChromeFrameMsg_GetWebApplicationInfo(main_frame->GetRoutingID()));
 }
 
 void TabHelper::Observe(int type,
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h
index c0df70eb..be71783 100644
--- a/chrome/browser/extensions/tab_helper.h
+++ b/chrome/browser/extensions/tab_helper.h
@@ -32,6 +32,10 @@
 #include "extensions/common/stack_frame.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
+namespace content {
+class RenderFrameHost;
+}
+
 namespace gfx {
 class Image;
 }
@@ -142,9 +146,8 @@
   void RenderFrameCreated(content::RenderFrameHost* host) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
-  bool OnMessageReceived(const IPC::Message& message) override;
   bool OnMessageReceived(const IPC::Message& message,
-                         content::RenderFrameHost* render_frame_host) override;
+                         content::RenderFrameHost* sender) override;
   void DidCloneToNewWebContents(
       content::WebContents* old_web_contents,
       content::WebContents* new_web_contents) override;
@@ -166,7 +169,8 @@
       DoInlineInstallCallback callback) override;
 
   // Message handlers.
-  void OnDidGetWebApplicationInfo(const WebApplicationInfo& info);
+  void OnDidGetWebApplicationInfo(content::RenderFrameHost* sender,
+                                  const WebApplicationInfo& info);
   void OnGetAppInstallState(content::RenderFrameHost* host,
                             const GURL& requestor_url,
                             int return_route_id,
diff --git a/chrome/browser/favicon/content_favicon_driver_browsertest.cc b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
index 88b7852..601e391 100644
--- a/chrome/browser/favicon/content_favicon_driver_browsertest.cc
+++ b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
@@ -279,7 +279,7 @@
       ui_test_utils::BROWSER_TEST_NONE);
   waiter.Wait();
 
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
   EXPECT_TRUE(delegate->was_requested());
 #else
   EXPECT_FALSE(delegate->was_requested());
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 885a66f..fbd5255 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1578,7 +1578,7 @@
 
 #endif  // defined(OS_WIN)
 
-#if defined(TOOLKIT_VIEWS) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
 
 const char kShowCertLinkOnPageInfoName[] = "Show certificate link";
 
@@ -1586,7 +1586,7 @@
     "Add a link from the Page Info bubble to the certificate viewer for HTTPS "
     "sites.";
 
-#endif  // defined(TOOLKIT_VIEWS) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#endif  // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
 
 #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID)
 
@@ -3191,7 +3191,7 @@
 
 #endif  // defined(OS_WIN)
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 
 const char kAccountConsistencyName[] =
     "Identity consistency between browser and cookie jar";
@@ -3213,7 +3213,7 @@
     "Show a OneGoogleBar on the local New Tab page if Google is the default "
     "search engine.";
 
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif  // !defined(OS_ANDROID)
 
 #if defined(OS_MACOSX)
 extern const char kMacRTLName[] = "Enable RTL";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index c2d9e56..24a390d 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1397,7 +1397,7 @@
 
 // Desktop --------------------------------------------------------------------
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 
 extern const char kEnableNewAppMenuIconName[];
 extern const char kEnableNewAppMenuIconDescription[];
@@ -1507,12 +1507,12 @@
 
 #endif  // defined(USE_ASH)
 
-#if defined(TOOLKIT_VIEWS) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
 
 extern const char kShowCertLinkOnPageInfoName[];
 extern const char kShowCertLinkOnPageInfoDescription[];
 
-#endif  // defined(TOOLKIT_VIEWS) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#endif  // defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
 
 #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID)
 
diff --git a/chrome/browser/media/cast_remoting_connector.cc b/chrome/browser/media/cast_remoting_connector.cc
index 6b52d3f..b419c46 100644
--- a/chrome/browser/media/cast_remoting_connector.cc
+++ b/chrome/browser/media/cast_remoting_connector.cc
@@ -166,11 +166,11 @@
 
 namespace {
 RemotingSinkCapabilities GetFeatureEnabledCapabilities() {
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
   if (base::FeatureList::IsEnabled(features::kMediaRemoting)) {
     return RemotingSinkCapabilities::RENDERING_ONLY;
   }
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif
   return RemotingSinkCapabilities::NONE;
 }
 }  // namespace
diff --git a/chrome/browser/media/router/mock_screen_availability_listener.h b/chrome/browser/media/router/mock_screen_availability_listener.h
index 55fa94463..3abdee4 100644
--- a/chrome/browser/media/router/mock_screen_availability_listener.h
+++ b/chrome/browser/media/router/mock_screen_availability_listener.h
@@ -18,7 +18,8 @@
 
   GURL GetAvailabilityUrl() const override;
 
-  MOCK_METHOD1(OnScreenAvailabilityChanged, void(bool available));
+  MOCK_METHOD1(OnScreenAvailabilityChanged,
+               void(blink::mojom::ScreenAvailability));
 
   MOCK_METHOD0(OnScreenAvailabilityNotSupported, void());
 
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer.cc b/chrome/browser/media/router/presentation_media_sinks_observer.cc
index 48de88b..ee37df9 100644
--- a/chrome/browser/media/router/presentation_media_sinks_observer.cc
+++ b/chrome/browser/media/router/presentation_media_sinks_observer.cc
@@ -17,7 +17,7 @@
     const url::Origin& origin)
     : MediaSinksObserver(router, source, origin),
       listener_(listener),
-      previous_availablity_(UNKNOWN) {
+      previous_availability_(blink::mojom::ScreenAvailability::UNKNOWN) {
   DCHECK(router);
   DCHECK(listener_);
 }
@@ -27,17 +27,20 @@
 
 void PresentationMediaSinksObserver::OnSinksReceived(
     const std::vector<MediaSink>& result) {
-  Availability current_availability = result.empty() ? UNAVAILABLE : AVAILABLE;
+  blink::mojom::ScreenAvailability current_availability =
+      result.empty() ? blink::mojom::ScreenAvailability::UNAVAILABLE
+                     : blink::mojom::ScreenAvailability::AVAILABLE;
 
   DVLOG(1) << "PresentationMediaSinksObserver::OnSinksReceived: "
            << source().ToString() << " "
            << (result.empty() ? "unavailable" : "available");
 
   // Don't send if new result is same as previous.
-  if (previous_availablity_ != current_availability)
-    listener_->OnScreenAvailabilityChanged(current_availability == AVAILABLE);
+  if (previous_availability_ == current_availability)
+    return;
 
-  previous_availablity_ = current_availability;
+  listener_->OnScreenAvailabilityChanged(current_availability);
+  previous_availability_ = current_availability;
 }
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer.h b/chrome/browser/media/router/presentation_media_sinks_observer.h
index b8960027..17e28ee 100644
--- a/chrome/browser/media/router/presentation_media_sinks_observer.h
+++ b/chrome/browser/media/router/presentation_media_sinks_observer.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "chrome/browser/media/router/media_sinks_observer.h"
 #include "content/public/browser/presentation_service_delegate.h"
+#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h"
 
 namespace content {
 class PresentationScreenAvailabilityListener;
@@ -46,10 +47,8 @@
   }
 
  private:
-  enum Availability { UNKNOWN, AVAILABLE, UNAVAILABLE };
-
   content::PresentationScreenAvailabilityListener* listener_;
-  Availability previous_availablity_;
+  blink::mojom::ScreenAvailability previous_availability_;
 
   DISALLOW_COPY_AND_ASSIGN(PresentationMediaSinksObserver);
 };
diff --git a/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc b/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc
index 12dac7a2..23d390f6 100644
--- a/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc
+++ b/chrome/browser/media/router/presentation_media_sinks_observer_unittest.cc
@@ -56,17 +56,23 @@
   std::vector<MediaSink> result;
   result.push_back(MediaSink("sinkId", "Sink", MediaSink::IconType::CAST));
 
-  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(true)).Times(1);
+  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(
+                             blink::mojom::ScreenAvailability::AVAILABLE))
+      .Times(1);
   observer_->OnSinksReceived(result);
 }
 
 TEST_F(PresentationMediaSinksObserverTest, NoAvailableScreens) {
-  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(false)).Times(1);
+  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(
+                             blink::mojom::ScreenAvailability::UNAVAILABLE))
+      .Times(1);
   observer_->OnSinksReceived(std::vector<MediaSink>());
 }
 
 TEST_F(PresentationMediaSinksObserverTest, ConsecutiveResults) {
-  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(false)).Times(1);
+  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(
+                             blink::mojom::ScreenAvailability::UNAVAILABLE))
+      .Times(1);
   observer_->OnSinksReceived(std::vector<MediaSink>());
   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&listener_));
 
@@ -78,7 +84,9 @@
   std::vector<MediaSink> result;
   result.push_back(MediaSink("sinkId", "Sink", MediaSink::IconType::CAST));
 
-  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(true)).Times(1);
+  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(
+                             blink::mojom::ScreenAvailability::AVAILABLE))
+      .Times(1);
   observer_->OnSinksReceived(result);
   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&listener_));
 
@@ -88,7 +96,9 @@
   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&listener_));
 
   // |listener_| should get result since it changed to false.
-  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(false)).Times(1);
+  EXPECT_CALL(listener_, OnScreenAvailabilityChanged(
+                             blink::mojom::ScreenAvailability::UNAVAILABLE))
+      .Times(1);
   observer_->OnSinksReceived(std::vector<MediaSink>());
   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&listener_));
 }
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc
index af973069..748db78 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -218,7 +218,8 @@
     content::PresentationScreenAvailabilityListener* listener) {
   MediaSource source(GetMediaSourceFromListener(listener));
   if (!IsValidPresentationUrl(source.url())) {
-    listener->OnScreenAvailabilityChanged(false);
+    listener->OnScreenAvailabilityChanged(
+        blink::mojom::ScreenAvailability::UNAVAILABLE);
     return false;
   }
 
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
index e1ec054..d153af6 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
@@ -323,7 +323,8 @@
 
 TEST_F(PresentationServiceDelegateImplTest, AddListenerForInvalidUrl) {
   MockScreenAvailabilityListener listener(GURL("unsupported-url://foo"));
-  EXPECT_CALL(listener, OnScreenAvailabilityChanged(false));
+  EXPECT_CALL(listener, OnScreenAvailabilityChanged(
+                            blink::mojom::ScreenAvailability::UNAVAILABLE));
   EXPECT_FALSE(delegate_impl_->AddScreenAvailabilityListener(
       main_frame_process_id_, main_frame_routing_id_, &listener));
   EXPECT_CALL(router_, RegisterMediaSinksObserver(_)).Times(0);
diff --git a/chrome/browser/media/webrtc/webrtc_log_list.cc b/chrome/browser/media/webrtc/webrtc_log_list.cc
index 56d8f27..4187086 100644
--- a/chrome/browser/media/webrtc/webrtc_log_list.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_list.cc
@@ -7,10 +7,9 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
-#include "content/public/browser/browser_thread.h"
 
 namespace {
 
@@ -24,8 +23,8 @@
                                                Profile* profile) {
   base::FilePath log_list_path = GetWebRtcLogListFileForDirectory(
       GetWebRtcLogDirectoryForProfile(profile->GetPath()));
-  return new UploadList(
-      delegate, log_list_path, content::BrowserThread::GetBlockingPool());
+  return new UploadList(delegate, log_list_path,
+                        base::CreateTaskRunnerWithTraits({base::MayBlock()}));
 }
 
 // static
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 11dd8dc..fae150e 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -359,6 +359,12 @@
 
 void ChromeNetworkDelegate::OnNetworkBytesSent(net::URLRequest* request,
                                                int64_t bytes_sent) {
+#if !defined(OS_ANDROID)
+  // Note: Currently, OnNetworkBytesSent is only implemented for HTTP jobs,
+  // not FTP or other types, so those kinds of bytes will not be reported here.
+  task_manager::TaskManagerInterface::OnRawBytesSent(*request, bytes_sent);
+#endif  // !defined(OS_ANDROID)
+
   ReportDataUsageStats(request, bytes_sent, 0 /* rx_bytes */);
 }
 
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
index c36249a..d67c1dd4 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -60,7 +60,8 @@
 void OnLoFiResponseReceivedOnUI(content::WebContents* web_contents) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   PreviewsInfoBarDelegate::Create(
-      web_contents, previews::PreviewsType::LOFI, true /* is_data_saver_user */,
+      web_contents, previews::PreviewsType::LOFI,
+      base::Time() /* previews_freshness */, true /* is_data_saver_user */,
       base::Bind(&AddPreviewNavigationToBlackListCallback,
                  web_contents->GetBrowserContext(),
                  web_contents->GetController()
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index a7d1344..020082f 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -238,6 +238,10 @@
   explicit NotificationPlatformBridgeLinuxImpl(scoped_refptr<dbus::Bus> bus)
       : bus_(bus) {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    // While the tasks in NotificationPlatformBridgeLinux merely need
+    // to run in sequence, many APIs in ::dbus are required to be
+    // called from the same thread (https://crbug.com/130984), so
+    // |task_runner_| is created as the single-threaded flavor.
     task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
         {base::MayBlock(), base::TaskPriority::USER_BLOCKING});
     registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc
index 135e6e62..25b437f 100644
--- a/chrome/browser/offline_pages/background_loader_offliner.cc
+++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -321,9 +321,10 @@
                         static_cast<int>(navigation_handle->GetNetErrorCode()));
     page_load_state_ = RETRIABLE;
   } else {
-    if (!navigation_handle->GetResponseHeaders())
-      return;
-    int status_code = navigation_handle->GetResponseHeaders()->response_code();
+    int status_code = 200;  // Default to OK.
+    // No response header can imply intermediate navigation state.
+    if (navigation_handle->GetResponseHeaders())
+      status_code = navigation_handle->GetResponseHeaders()->response_code();
     // 2XX and 3XX are ok because they indicate success or redirection.
     // We track 301 because it's MOVED_PERMANENTLY and usually accompanies an
     // error page with new address.
diff --git a/chrome/browser/offline_pages/background_loader_offliner_unittest.cc b/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
index 7388d51..c21d677a 100644
--- a/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
+++ b/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
@@ -563,6 +563,22 @@
   EXPECT_EQ(Offliner::RequestStatus::LOADING_FAILED, request_status());
 }
 
+TEST_F(BackgroundLoaderOfflinerTest, DoesNotCrashWithNullResponseHeaders) {
+  base::Time creation_time = base::Time::Now();
+  SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time,
+                          kUserRequested);
+  EXPECT_TRUE(offliner()->LoadAndSave(request, completion_callback(),
+                                      progress_callback()));
+
+  // Called after calling LoadAndSave so we have web_contents to work with.
+  std::unique_ptr<content::NavigationHandle> handle(
+      content::NavigationHandle::CreateNavigationHandleForTesting(
+          kHttpUrl, offliner()->web_contents()->GetMainFrame(), true,
+          net::Error::OK));
+  // Call DidFinishNavigation with handle.
+  offliner()->DidFinishNavigation(handle.get());
+}
+
 TEST_F(BackgroundLoaderOfflinerTest, OffliningPreviewsStatusOffHistogram) {
   base::Time creation_time = base::Time::Now();
   SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time,
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 04445195..b85147d 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -56,6 +56,7 @@
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/web_contents.h"
@@ -692,9 +693,13 @@
 
 // static
 void ChromePasswordManagerClient::BindCredentialManager(
-    content::RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    password_manager::mojom::CredentialManagerRequest request) {
+    password_manager::mojom::CredentialManagerRequest request,
+    content::RenderFrameHost* render_frame_host) {
+  // Only valid for the main frame.
+  if (render_frame_host->GetParent())
+    return;
+
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   DCHECK(web_contents);
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index dc920d3..ff90c85 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -123,9 +123,9 @@
   void SetTestObserver(autofill::PasswordGenerationPopupObserver* observer);
 
   static void BindCredentialManager(
-      content::RenderFrameHost* render_frame_host,
       const service_manager::BindSourceInfo& source_info,
-      password_manager::mojom::CredentialManagerRequest request);
+      password_manager::mojom::CredentialManagerRequest request,
+      content::RenderFrameHost* render_frame_host);
 
   // A helper method to determine whether a save/update bubble can be shown
   // on this |url|.
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index eb0011af..23fc12c 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -574,8 +574,9 @@
 
   // This call should not crash.
   ChromePasswordManagerClient::BindCredentialManager(
-      web_contents->GetMainFrame(), service_manager::BindSourceInfo(),
-      password_manager::mojom::CredentialManagerRequest());
+      service_manager::BindSourceInfo(),
+      password_manager::mojom::CredentialManagerRequest(),
+      web_contents->GetMainFrame());
 }
 
 TEST_F(ChromePasswordManagerClientTest, CanShowBubbleOnURL) {
diff --git a/chrome/browser/payments/payment_request_factory.cc b/chrome/browser/payments/payment_request_factory.cc
index e74a33b..72c38c2 100644
--- a/chrome/browser/payments/payment_request_factory.cc
+++ b/chrome/browser/payments/payment_request_factory.cc
@@ -13,11 +13,13 @@
 
 namespace payments {
 
-void CreatePaymentRequest(content::RenderFrameHost* render_frame_host,
-                          content::WebContents* web_contents,
-                          const service_manager::BindSourceInfo& source_info,
-                          mojom::PaymentRequestRequest request) {
-  DCHECK(web_contents);
+void CreatePaymentRequest(const service_manager::BindSourceInfo& source_info,
+                          mojom::PaymentRequestRequest request,
+                          content::RenderFrameHost* render_frame_host) {
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(render_frame_host);
+  if (!web_contents)
+    return;
   PaymentRequestWebContentsManager::GetOrCreateForWebContents(web_contents)
       ->CreatePaymentRequest(
           render_frame_host, web_contents,
diff --git a/chrome/browser/payments/payment_request_factory.h b/chrome/browser/payments/payment_request_factory.h
index c1d176a..80ab1c5 100644
--- a/chrome/browser/payments/payment_request_factory.h
+++ b/chrome/browser/payments/payment_request_factory.h
@@ -10,7 +10,6 @@
 
 namespace content {
 class RenderFrameHost;
-class WebContents;
 }
 
 namespace payments {
@@ -19,10 +18,9 @@
 // |request| was initiated by the frame hosted by |render_frame_host|, which is
 // inside of |web_contents|. This function is called every time a new instance
 // of PaymentRequest is created in the renderer.
-void CreatePaymentRequest(content::RenderFrameHost* render_frame_host,
-                          content::WebContents* web_contents,
-                          const service_manager::BindSourceInfo& source_info,
-                          mojom::PaymentRequestRequest request);
+void CreatePaymentRequest(const service_manager::BindSourceInfo& source_info,
+                          mojom::PaymentRequestRequest request,
+                          content::RenderFrameHost* render_frame_host);
 
 }  // namespace payments
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 37b9739..ca84ba77 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -270,7 +270,7 @@
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 #include "chrome/browser/ui/webui/md_history_ui.h"
 #include "chrome/browser/ui/webui/settings/md_settings_ui.h"
 #endif
@@ -623,7 +623,7 @@
   RegisterChromeLauncherUserPrefs(registry);
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
   MdHistoryUI::RegisterProfilePrefs(registry);
   settings::MdSettingsUI::RegisterProfilePrefs(registry);
 #endif
diff --git a/chrome/browser/prefs/session_startup_pref.cc b/chrome/browser/prefs/session_startup_pref.cc
index 1b569b0..1f1a9a193 100644
--- a/chrome/browser/prefs/session_startup_pref.cc
+++ b/chrome/browser/prefs/session_startup_pref.cc
@@ -45,7 +45,7 @@
 // static
 void SessionStartupPref::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-#if defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
   uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS;
 #else
   uint32_t flags = user_prefs::PrefRegistrySyncable::SYNCABLE_PREF;
diff --git a/chrome/browser/previews/previews_infobar_delegate.cc b/chrome/browser/previews/previews_infobar_delegate.cc
index e5947ca..110f2088 100644
--- a/chrome/browser/previews/previews_infobar_delegate.cc
+++ b/chrome/browser/previews/previews_infobar_delegate.cc
@@ -4,9 +4,15 @@
 
 #include "chrome/browser/previews/previews_infobar_delegate.h"
 
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram.h"
 #include "base/optional.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/android/android_theme_resources.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
@@ -16,6 +22,8 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/infobars/core/infobar.h"
+#include "components/network_time/network_time_tracker.h"
+#include "components/previews/core/previews_features.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -101,6 +109,7 @@
 void PreviewsInfoBarDelegate::Create(
     content::WebContents* web_contents,
     previews::PreviewsType previews_type,
+    base::Time previews_freshness,
     bool is_data_saver_user,
     const OnDismissPreviewsInfobarCallback& on_dismiss_callback) {
   PreviewsInfoBarTabHelper* infobar_tab_helper =
@@ -116,7 +125,8 @@
     return;
 
   std::unique_ptr<PreviewsInfoBarDelegate> delegate(new PreviewsInfoBarDelegate(
-      web_contents, previews_type, is_data_saver_user, on_dismiss_callback));
+      web_contents, previews_type, previews_freshness, is_data_saver_user,
+      on_dismiss_callback));
 
 #if defined(OS_ANDROID)
   std::unique_ptr<infobars::InfoBar> infobar_ptr(
@@ -144,10 +154,12 @@
 PreviewsInfoBarDelegate::PreviewsInfoBarDelegate(
     content::WebContents* web_contents,
     previews::PreviewsType previews_type,
+    base::Time previews_freshness,
     bool is_data_saver_user,
     const OnDismissPreviewsInfobarCallback& on_dismiss_callback)
     : ConfirmInfoBarDelegate(),
       previews_type_(previews_type),
+      previews_freshness_(previews_freshness),
       infobar_dismissed_action_(INFOBAR_DISMISSED_BY_TAB_CLOSURE),
       message_text_(l10n_util::GetStringUTF16(
           is_data_saver_user ? IDS_PREVIEWS_INFOBAR_SAVED_DATA_TITLE
@@ -180,7 +192,18 @@
 }
 
 base::string16 PreviewsInfoBarDelegate::GetMessageText() const {
+// Android has a custom infobar that calls GetTimestampText() and adds the
+// timestamp in a separate description view. Other OS's can enable previews
+// for debugging purposes and don't have a custom infobar with a description
+// view, so the timestamp should be appended to the message.
+#if defined(OS_ANDROID)
   return message_text_;
+#else
+  base::string16 timestamp = GetTimestampText();
+  if (timestamp.empty())
+    return message_text_;
+  return message_text_ + base::ASCIIToUTF16(" ") + timestamp;
+#endif
 }
 
 int PreviewsInfoBarDelegate::GetButtons() const {
@@ -214,5 +237,48 @@
 }
 
 base::string16 PreviewsInfoBarDelegate::GetTimestampText() const {
-  return base::string16();
+  if (previews_freshness_.is_null())
+    return base::string16();
+  if (!base::FeatureList::IsEnabled(
+          previews::features::kStalePreviewsTimestamp)) {
+    return base::string16();
+  }
+
+  int min_staleness_in_minutes = base::GetFieldTrialParamByFeatureAsInt(
+      previews::features::kStalePreviewsTimestamp, "min_staleness_in_minutes",
+      0);
+  int max_staleness_in_minutes = base::GetFieldTrialParamByFeatureAsInt(
+      previews::features::kStalePreviewsTimestamp, "max_staleness_in_minutes",
+      0);
+
+  if (min_staleness_in_minutes == 0 || max_staleness_in_minutes == 0)
+    return base::string16();
+
+  base::Time network_time;
+  if (g_browser_process->network_time_tracker()->GetNetworkTime(&network_time,
+                                                                nullptr) !=
+      network_time::NetworkTimeTracker::NETWORK_TIME_AVAILABLE) {
+    // When network time has not been initialized yet, simply rely on the
+    // machine's current time.
+    network_time = base::Time::Now();
+  }
+
+  int staleness_in_minutes = (network_time - previews_freshness_).InMinutes();
+  // TODO(megjablon): record metrics for out of bounds staleness.
+  if (staleness_in_minutes < min_staleness_in_minutes)
+    return base::string16();
+  if (staleness_in_minutes > max_staleness_in_minutes)
+    return base::string16();
+
+  if (staleness_in_minutes < 60) {
+    return l10n_util::GetStringFUTF16(
+        IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES,
+        base::IntToString16(staleness_in_minutes));
+  } else if (staleness_in_minutes < 120) {
+    return l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_ONE_HOUR);
+  } else {
+    return l10n_util::GetStringFUTF16(
+        IDS_PREVIEWS_INFOBAR_TIMESTAMP_HOURS,
+        base::IntToString16(staleness_in_minutes / 60));
+  }
 }
diff --git a/chrome/browser/previews/previews_infobar_delegate.h b/chrome/browser/previews/previews_infobar_delegate.h
index 0979c07e..47245ea 100644
--- a/chrome/browser/previews/previews_infobar_delegate.h
+++ b/chrome/browser/previews/previews_infobar_delegate.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/strings/string16.h"
+#include "base/time/time.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/previews/core/previews_experiments.h"
 
@@ -41,10 +42,12 @@
   static void Create(
       content::WebContents* web_contents,
       previews::PreviewsType previews_type,
+      base::Time previews_freshness,
       bool is_data_saver_user,
       const OnDismissPreviewsInfobarCallback& on_dismiss_callback);
 
   // ConfirmInfoBarDelegate overrides:
+  int GetIconId() const override;
   base::string16 GetMessageText() const override;
   base::string16 GetLinkText() const override;
 
@@ -54,18 +57,21 @@
   PreviewsInfoBarDelegate(
       content::WebContents* web_contents,
       previews::PreviewsType previews_type,
+      base::Time previews_freshness,
       bool is_data_saver_user,
       const OnDismissPreviewsInfobarCallback& on_dismiss_callback);
 
   // ConfirmInfoBarDelegate overrides:
   infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
-  int GetIconId() const override;
   bool ShouldExpire(const NavigationDetails& details) const override;
   void InfoBarDismissed() override;
   int GetButtons() const override;
   bool LinkClicked(WindowOpenDisposition disposition) override;
 
   previews::PreviewsType previews_type_;
+  // The time at which the preview associated with this infobar was created. A
+  // value of zero means that the creation time is unknown.
+  const base::Time previews_freshness_;
   mutable PreviewsInfoBarAction infobar_dismissed_action_;
 
   const base::string16 message_text_;
diff --git a/chrome/browser/previews/previews_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
index d18bee15..107da1d9 100644
--- a/chrome/browser/previews/previews_infobar_delegate_unittest.cc
+++ b/chrome/browser/previews/previews_infobar_delegate_unittest.cc
@@ -9,11 +9,15 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/optional.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chrome/browser/android/android_theme_resources.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/loader/chrome_navigation_data.h"
@@ -22,6 +26,7 @@
 #include "chrome/browser/previews/previews_infobar_tab_helper.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
@@ -32,9 +37,12 @@
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_delegate.h"
+#include "components/network_time/network_time_test_utils.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/previews/core/previews_experiments.h"
+#include "components/previews/core/previews_features.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/variations/variations_associated_data.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/reload_type.h"
@@ -111,6 +119,9 @@
 
 class PreviewsInfoBarDelegateUnitTest : public ChromeRenderViewHostTestHarness {
  protected:
+  PreviewsInfoBarDelegateUnitTest()
+      : field_trial_list_(new base::FieldTrialList(nullptr)) {}
+
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     InfoBarService::CreateForWebContents(web_contents());
@@ -139,17 +150,23 @@
         base::WrapUnique(new data_reduction_proxy::DataStore()),
         base::ThreadTaskRunnerHandle::Get(),
         base::ThreadTaskRunnerHandle::Get());
+
+    TestingBrowserProcess::GetGlobal()->SetLocalState(
+        drp_test_context_->pref_service());
+    network_time::NetworkTimeTracker::RegisterPrefs(registry);
   }
 
   void TearDown() override {
     drp_test_context_->DestroySettings();
     ChromeRenderViewHostTestHarness::TearDown();
+    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
   }
 
-  ConfirmInfoBarDelegate* CreateInfoBar(previews::PreviewsType type,
-                                        bool is_data_saver_user) {
+  PreviewsInfoBarDelegate* CreateInfoBar(previews::PreviewsType type,
+                                         base::Time previews_freshness,
+                                         bool is_data_saver_user) {
     PreviewsInfoBarDelegate::Create(
-        web_contents(), type, is_data_saver_user,
+        web_contents(), type, previews_freshness, is_data_saver_user,
         base::Bind(&PreviewsInfoBarDelegateUnitTest::OnDismissPreviewsInfobar,
                    base::Unretained(this)));
 
@@ -157,9 +174,27 @@
         InfoBarService::FromWebContents(web_contents());
     EXPECT_EQ(1U, infobar_service->infobar_count());
 
-    return infobar_service->infobar_at(0)
-        ->delegate()
-        ->AsConfirmInfoBarDelegate();
+    return static_cast<PreviewsInfoBarDelegate*>(
+        infobar_service->infobar_at(0)->delegate());
+  }
+
+  void EnableStalePreviewsTimestamp() {
+    const std::string kTrialName = "TrialName";
+    const std::string kGroupName = "GroupName";
+
+    std::map<std::string, std::string> variation_params;
+    variation_params["min_staleness_in_minutes"] = "2";
+    variation_params["max_staleness_in_minutes"] = "1440";
+
+    base::AssociateFieldTrialParams(kTrialName, kGroupName, variation_params);
+    base::FieldTrial* field_trial =
+        base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+
+    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    feature_list->RegisterFieldTrialOverride(
+        previews::features::kStalePreviewsTimestamp.name,
+        base::FeatureList::OVERRIDE_ENABLE_FEATURE, field_trial);
+    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
   }
 
   void OnDismissPreviewsInfobar(bool user_opt_out) {
@@ -174,18 +209,21 @@
       drp_test_context_;
 
   base::Optional<bool> user_opt_out_;
+  std::unique_ptr<base::FieldTrialList> field_trial_list_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestNavigationDismissal) {
   base::HistogramTester tester;
 
-  CreateInfoBar(previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                true /* is_data_saver_user */);
 
   // Try showing a second infobar. Another should not be shown since the page
   // has not navigated.
   PreviewsInfoBarDelegate::Create(
       web_contents(), previews::PreviewsType::LOFI,
-      true /* is_data_saver_user */,
+      base::Time() /* previews_freshness */, true /* is_data_saver_user */,
       PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback());
   EXPECT_EQ(1U, infobar_service()->infobar_count());
 
@@ -207,13 +245,14 @@
   // Navigate to test URL, so we can reload later.
   NavigateAndCommit(GURL(kTestUrl));
 
-  CreateInfoBar(previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                true /* is_data_saver_user */);
 
   // Try showing a second infobar. Another should not be shown since the page
   // has not navigated.
   PreviewsInfoBarDelegate::Create(
       web_contents(), previews::PreviewsType::LOFI,
-      true /* is_data_saver_user */,
+      base::Time() /* previews_freshness */, true /* is_data_saver_user */,
       PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback());
   EXPECT_EQ(1U, infobar_service()->infobar_count());
 
@@ -243,8 +282,9 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestUserDismissal) {
   base::HistogramTester tester;
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                    true /* is_data_saver_user */);
 
   // Simulate dismissing the infobar.
   infobar->InfoBarDismissed();
@@ -262,7 +302,8 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestTabClosedDismissal) {
   base::HistogramTester tester;
 
-  CreateInfoBar(previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                true /* is_data_saver_user */);
 
   // Delete the infobar without any other infobar actions.
   infobar_service()->infobar_at(0)->RemoveSelf();
@@ -285,7 +326,8 @@
   };
   for (const auto test : tests) {
     drp_test_context_->config()->ResetLoFiStatusForTest();
-    base::FieldTrialList field_trial_list(nullptr);
+    field_trial_list_.reset();
+    field_trial_list_.reset(new base::FieldTrialList(nullptr));
     if (test.using_previews_blacklist) {
       base::FieldTrialList::CreateFieldTrial(
           "DataReductionProxyPreviewsBlackListTransition", "Enabled_");
@@ -295,8 +337,9 @@
     web_contents()->GetController().Reload(content::ReloadType::NORMAL, true);
     content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
 
-    ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-        previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+    ConfirmInfoBarDelegate* infobar =
+        CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                      true /* is_data_saver_user */);
 
     // Simulate clicking the infobar link.
     if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB))
@@ -325,8 +368,9 @@
 
   NavigateAndCommit(GURL(kTestUrl));
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LITE_PAGE, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(),
+                    true /* is_data_saver_user */);
 
   // Simulate clicking the infobar link.
   if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB))
@@ -353,8 +397,9 @@
 }
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, InfobarTestShownOncePerNavigation) {
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                    true /* is_data_saver_user */);
 
   // Simulate dismissing the infobar.
   infobar->InfoBarDismissed();
@@ -363,7 +408,7 @@
 
   PreviewsInfoBarDelegate::Create(
       web_contents(), previews::PreviewsType::LOFI,
-      true /* is_data_saver_user */,
+      base::Time() /* previews_freshness */, true /* is_data_saver_user */,
       PreviewsInfoBarDelegate::OnDismissPreviewsInfobarCallback());
 
   // Infobar should not be shown again since a navigation hasn't happened.
@@ -371,14 +416,16 @@
 
   // Navigate and show infobar again.
   NavigateAndCommit(GURL(kTestUrl));
-  CreateInfoBar(previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                true /* is_data_saver_user */);
 }
 
 TEST_F(PreviewsInfoBarDelegateUnitTest, LoFiInfobarTest) {
   base::HistogramTester tester;
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LOFI, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LOFI, base::Time(),
+                    true /* is_data_saver_user */);
 
   tester.ExpectUniqueSample(kUMAPreviewsInfoBarActionLoFi,
                             PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1);
@@ -400,8 +447,9 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTest) {
   base::HistogramTester tester;
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LITE_PAGE, true /* is_data_saver_user */);
+  PreviewsInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(),
+                    true /* is_data_saver_user */);
 
   tester.ExpectUniqueSample(kUMAPreviewsInfoBarActionLitePage,
                             PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1);
@@ -414,6 +462,7 @@
             infobar->GetMessageText());
   ASSERT_EQ(l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_LINK),
             infobar->GetLinkText());
+  ASSERT_EQ(base::string16(), infobar->GetTimestampText());
 #if defined(OS_ANDROID)
   ASSERT_EQ(IDR_ANDROID_INFOBAR_PREVIEWS, infobar->GetIconId());
 #else
@@ -424,8 +473,9 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, OfflineInfobarNonDataSaverUserTest) {
   base::HistogramTester tester;
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::OFFLINE, false /* is_data_saver_user */);
+  PreviewsInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(),
+                    false /* is_data_saver_user */);
 
   tester.ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline,
                             PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1);
@@ -438,6 +488,7 @@
             infobar->GetMessageText());
   ASSERT_EQ(l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_LINK),
             infobar->GetLinkText());
+  ASSERT_EQ(base::string16(), infobar->GetTimestampText());
 #if defined(OS_ANDROID)
   ASSERT_EQ(IDR_ANDROID_INFOBAR_PREVIEWS, infobar->GetIconId());
 #else
@@ -448,8 +499,9 @@
 TEST_F(PreviewsInfoBarDelegateUnitTest, OfflineInfobarDataSaverUserTest) {
   base::HistogramTester tester;
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::OFFLINE, true /* is_data_saver_user */);
+  PreviewsInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(),
+                    true /* is_data_saver_user */);
 
   tester.ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline,
                             PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1);
@@ -462,6 +514,7 @@
             infobar->GetMessageText());
   ASSERT_EQ(l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_LINK),
             infobar->GetLinkText());
+  ASSERT_EQ(base::string16(), infobar->GetTimestampText());
 #if defined(OS_ANDROID)
   ASSERT_EQ(IDR_ANDROID_INFOBAR_PREVIEWS, infobar->GetIconId());
 #else
@@ -477,8 +530,9 @@
 
   NavigateAndCommit(GURL(kTestUrl));
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::OFFLINE, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::OFFLINE, base::Time(),
+                    true /* is_data_saver_user */);
 
   tester.ExpectUniqueSample(kUMAPreviewsInfoBarActionOffline,
                             PreviewsInfoBarDelegate::INFOBAR_SHOWN, 1);
@@ -508,8 +562,9 @@
 
   NavigateAndCommit(GURL(kTestUrl));
 
-  ConfirmInfoBarDelegate* infobar = CreateInfoBar(
-      previews::PreviewsType::LITE_PAGE, true /* is_data_saver_user */);
+  ConfirmInfoBarDelegate* infobar =
+      CreateInfoBar(previews::PreviewsType::LITE_PAGE, base::Time(),
+                    true /* is_data_saver_user */);
 
   // Simulate clicking the infobar link.
   if (infobar->LinkClicked(WindowOpenDisposition::CURRENT_TAB))
@@ -552,3 +607,48 @@
                     ->pingback_client()
                     ->OptOutsSizeForTesting());
 }
+
+TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTimestampMintuesTest) {
+  EnableStalePreviewsTimestamp();
+
+  int staleness_in_minutes = 5;
+
+  PreviewsInfoBarDelegate* infobar = CreateInfoBar(
+      previews::PreviewsType::LITE_PAGE,
+      base::Time::Now() - base::TimeDelta::FromMinutes(staleness_in_minutes),
+      true /* is_data_saver_user */);
+
+  ASSERT_EQ(
+      l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_MINUTES,
+                                 base::IntToString16(staleness_in_minutes)),
+      infobar->GetTimestampText());
+}
+
+TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTimestampHourTest) {
+  EnableStalePreviewsTimestamp();
+
+  int staleness_in_minutes = 65;
+
+  PreviewsInfoBarDelegate* infobar = CreateInfoBar(
+      previews::PreviewsType::LITE_PAGE,
+      base::Time::Now() - base::TimeDelta::FromMinutes(staleness_in_minutes),
+      true /* is_data_saver_user */);
+
+  ASSERT_EQ(l10n_util::GetStringUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_ONE_HOUR),
+            infobar->GetTimestampText());
+}
+
+TEST_F(PreviewsInfoBarDelegateUnitTest, PreviewInfobarTimestampHoursTest) {
+  EnableStalePreviewsTimestamp();
+
+  int staleness_in_hours = 2;
+
+  PreviewsInfoBarDelegate* infobar = CreateInfoBar(
+      previews::PreviewsType::LITE_PAGE,
+      base::Time::Now() - base::TimeDelta::FromHours(staleness_in_hours),
+      true /* is_data_saver_user */);
+
+  ASSERT_EQ(l10n_util::GetStringFUTF16(IDS_PREVIEWS_INFOBAR_TIMESTAMP_HOURS,
+                                       base::IntToString16(staleness_in_hours)),
+            infobar->GetTimestampText());
+}
diff --git a/chrome/browser/previews/previews_infobar_tab_helper.cc b/chrome/browser/previews/previews_infobar_tab_helper.cc
index 7dcd7d3c..41dd2ff 100644
--- a/chrome/browser/previews/previews_infobar_tab_helper.cc
+++ b/chrome/browser/previews/previews_infobar_tab_helper.cc
@@ -105,6 +105,7 @@
                 web_contents()->GetBrowserContext());
     PreviewsInfoBarDelegate::Create(
         web_contents(), previews::PreviewsType::OFFLINE,
+        base::Time() /* previews_freshness */,
         data_reduction_proxy_settings &&
             data_reduction_proxy_settings->IsDataReductionProxyEnabled(),
         base::Bind(&AddPreviewNavigationCallback, browser_context_,
@@ -118,8 +119,10 @@
   const net::HttpResponseHeaders* headers =
       navigation_handle->GetResponseHeaders();
   if (headers && data_reduction_proxy::IsLitePagePreview(*headers)) {
+    base::Time previews_freshness;
+    headers->GetDateValue(&previews_freshness);
     PreviewsInfoBarDelegate::Create(
-        web_contents(), previews::PreviewsType::LITE_PAGE,
+        web_contents(), previews::PreviewsType::LITE_PAGE, previews_freshness,
         true /* is_data_saver_user */,
         base::Bind(&AddPreviewNavigationCallback, browser_context_,
                    navigation_handle->GetRedirectChain()[0],
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 33eb014..fd936c7 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -387,8 +387,10 @@
     info.factory = base::Bind(
         &prefs::CreatePrefService, chrome::ExpectedPrefStores(),
         make_scoped_refptr(content::BrowserThread::GetBlockingPool()));
-    info.task_runner = content::BrowserThread::GetTaskRunnerForThread(
-        content::BrowserThread::IO);
+    info.task_runner = base::CreateSequencedTaskRunnerWithTraits(
+        {base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
+         base::TaskPriority::USER_VISIBLE});
+    pref_service_task_runner_ = info.task_runner;
     services->insert(std::make_pair(prefs::mojom::kServiceName, info));
   }
 }
@@ -499,6 +501,11 @@
   return profile_->GetLastSessionExitType();
 }
 
+scoped_refptr<base::SequencedTaskRunner>
+OffTheRecordProfileImpl::GetPrefServiceTaskRunner() {
+  return pref_service_task_runner_;
+}
+
 #if defined(OS_CHROMEOS)
 void OffTheRecordProfileImpl::ChangeAppLocale(const std::string& locale,
                                               AppLocaleChangedVia) {
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 6574d6c..e720786 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -80,6 +80,7 @@
   bool WasCreatedByVersionOrLater(const std::string& version) override;
   void SetExitType(ExitType exit_type) override;
   ExitType GetLastSessionExitType() override;
+  scoped_refptr<base::SequencedTaskRunner> GetPrefServiceTaskRunner() override;
 
 #if defined(OS_CHROMEOS)
   void ChangeAppLocale(const std::string& locale, AppLocaleChangedVia) override;
@@ -139,6 +140,7 @@
   Profile* profile_;
 
   std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_;
+  scoped_refptr<base::SequencedTaskRunner> pref_service_task_runner_;
 
 #if !defined(OS_ANDROID)
   std::unique_ptr<content::HostZoomMap::Subscription> track_zoom_subscription_;
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index dbbfa07e..c743a8b 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -303,6 +303,10 @@
   // Returns how the last session was shutdown.
   virtual ExitType GetLastSessionExitType() = 0;
 
+  // Returns the SequencedTaskRunner the pref service runs on.
+  virtual scoped_refptr<base::SequencedTaskRunner>
+  GetPrefServiceTaskRunner() = 0;
+
   // Stop sending accessibility events until ResumeAccessibilityEvents().
   // Calls to Pause nest; no events will be sent until the number of
   // Resume calls matches the number of Pause calls received.
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 1dddc38..00b1849 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -715,9 +715,7 @@
     profile->SetExitType(Profile::EXIT_CRASHED);
     profile->GetPrefs()->CommitPendingWrite();
     if (base::FeatureList::IsEnabled(features::kPrefService)) {
-      FlushTaskRunner(content::BrowserThread::GetTaskRunnerForThread(
-                          content::BrowserThread::IO)
-                          .get());
+      FlushTaskRunner(profile->GetPrefServiceTaskRunner().get());
     }
     FlushTaskRunner(profile->GetIOTaskRunner().get());
 
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index e885f56..7b62b17 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -389,7 +389,7 @@
 #endif
 
   registry->RegisterStringPref(prefs::kSupervisedUserId, std::string());
-#if defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
   uint32_t home_page_flags = PrefRegistry::NO_REGISTRATION_FLAGS;
 #else
   uint32_t home_page_flags = user_prefs::PrefRegistrySyncable::SYNCABLE_PREF;
@@ -979,6 +979,11 @@
   return last_session_exit_type_;
 }
 
+scoped_refptr<base::SequencedTaskRunner>
+ProfileImpl::GetPrefServiceTaskRunner() {
+  return pref_service_task_runner_;
+}
+
 PrefService* ProfileImpl::GetPrefs() {
   return const_cast<PrefService*>(
       static_cast<const ProfileImpl*>(this)->GetPrefs());
@@ -1126,8 +1131,10 @@
     info.factory = base::Bind(
         &prefs::CreatePrefService, chrome::ExpectedPrefStores(),
         make_scoped_refptr(content::BrowserThread::GetBlockingPool()));
-    info.task_runner = content::BrowserThread::GetTaskRunnerForThread(
-        content::BrowserThread::IO);
+    info.task_runner = base::CreateSequencedTaskRunnerWithTraits(
+        {base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
+         base::TaskPriority::USER_VISIBLE});
+    pref_service_task_runner_ = info.task_runner;
     services->insert(std::make_pair(prefs::mojom::kServiceName, info));
   }
 
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 0b5e691..68132ca 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -145,6 +145,7 @@
   bool WasCreatedByVersionOrLater(const std::string& version) override;
   void SetExitType(ExitType exit_type) override;
   ExitType GetLastSessionExitType() override;
+  scoped_refptr<base::SequencedTaskRunner> GetPrefServiceTaskRunner() override;
 
 #if defined(OS_CHROMEOS)
   void ChangeAppLocale(const std::string& locale, AppLocaleChangedVia) override;
@@ -233,6 +234,7 @@
   // first.
   scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry_;
   std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_;
+  scoped_refptr<base::SequencedTaskRunner> pref_service_task_runner_;
   // See comment in GetOffTheRecordPrefs. Field exists so something owns the
   // dummy.
   std::unique_ptr<sync_preferences::PrefServiceSyncable> dummy_otr_prefs_;
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index b40ced7d..bf0157257 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -127,7 +127,7 @@
 #include "components/user_manager/user_manager.h"
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 #include "chrome/browser/profiles/profile_statistics.h"
 #include "chrome/browser/profiles/profile_statistics_factory.h"
 #endif
@@ -335,7 +335,7 @@
 }
 #endif
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 void SignOut(SigninManager* signin_manager) {
   signin_manager->SignOut(
       signin_metrics::AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN,
@@ -1556,12 +1556,12 @@
     bool has_entry = storage.GetProfileAttributesWithPath(profile->GetPath(),
                                                           &entry);
     if (has_entry) {
-#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID) && !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)
+#if !defined(OS_ANDROID) && !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 &&
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.html b/chrome/browser/resources/chromeos/login/custom_elements_login.html
index 7ee55095..88995fb2 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_login.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_login.html
@@ -24,6 +24,7 @@
 <include src="oobe_reset.html">
 <include src="oobe_reset_confirmation_overlay.html">
 <include src="oobe_voice_interaction_value_prop.html">
+<include src="oobe_wait_for_container_ready.html">
 <include src="encryption_migration.html">
 
 <script src="chrome://oobe/custom_elements.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.js b/chrome/browser/resources/chromeos/login/custom_elements_login.js
index b1d2df30..43dd318 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_login.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_login.js
@@ -25,3 +25,4 @@
 // <include src="oobe_reset_confirmation_overlay.js">
 // <include src="encryption_migration.js">
 // <include src="oobe_voice_interaction_value_prop.js">
+// <include src="oobe_wait_for_container_ready.js">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
index 10976d8..eef4400 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -27,6 +27,7 @@
 <include src="oobe_welcome_dialog.html">
 <include src="oobe_welcome.html">
 <include src="oobe_voice_interaction_value_prop.html">
+<include src="oobe_wait_for_container_ready.html">
 <include src="offline_ad_login.html">
 <include src="active_directory_password_change.html">
 <include src="arc_terms_of_service.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
index 8edd2792..d10c60e 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -40,3 +40,4 @@
 // <include src="active_directory_password_change.js">
 // <include src="arc_terms_of_service.js">
 // <include src="oobe_voice_interaction_value_prop.js">
+// <include src="oobe_wait_for_container_ready.js">
diff --git a/chrome/browser/resources/chromeos/login/login.js b/chrome/browser/resources/chromeos/login/login.js
index 0b54a70..18af9ca 100644
--- a/chrome/browser/resources/chromeos/login/login.js
+++ b/chrome/browser/resources/chromeos/login/login.js
@@ -53,6 +53,7 @@
       login.ActiveDirectoryPasswordChangeScreen.register(/* lazyInit= */ true);
       login.EncryptionMigrationScreen.register();
       login.VoiceInteractionValuePropScreen.register();
+      login.WaitForContainerReadyScreen.register();
 
       cr.ui.Bubble.decorate($('bubble'));
       login.HeaderBar.decorate($('login-header-bar'));
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
index 2f3923c5..f0cdb4e66 100644
--- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
+++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
@@ -20,6 +20,7 @@
 <link rel="stylesheet" href="oobe_screen_auto_enrollment_check.css">
 <link rel="stylesheet" href="oobe_screen_user_image.css">
 <link rel="stylesheet" href="oobe_screen_voice_interaction_value_prop.css">
+<link rel="stylesheet" href="oobe_screen_wait_for_container_ready.css">
 
 <link rel="stylesheet" href="screen_app_launch_splash.css">
 <link rel="stylesheet" href="screen_arc_kiosk_splash.css">
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.js b/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
index 5c77bef2..9da4f9a2 100644
--- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
+++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
@@ -17,6 +17,7 @@
 // <include src="oobe_screen_terms_of_service.js">
 // <include src="oobe_screen_user_image.js">
 // <include src="oobe_screen_voice_interaction_value_prop.js">
+// <include src="oobe_screen_wait_for_container_ready.js">
 
 // <include src="screen_app_launch_splash.js">
 // <include src="screen_arc_kiosk_splash.js">
diff --git a/chrome/browser/resources/chromeos/login/login_screens.html b/chrome/browser/resources/chromeos/login/login_screens.html
index c2dd13e..85a72af 100644
--- a/chrome/browser/resources/chromeos/login/login_screens.html
+++ b/chrome/browser/resources/chromeos/login/login_screens.html
@@ -4,6 +4,7 @@
 <include src="oobe_screen_terms_of_service.html">
 <include src="oobe_screen_user_image.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
+<include src="oobe_screen_wait_for_container_ready.html">
 <include src="../../../../../ui/login/account_picker/screen_account_picker.html">
 <include src="screen_arc_terms_of_service.html">
 <include src="screen_error_message.html">
diff --git a/chrome/browser/resources/chromeos/login/md_login.js b/chrome/browser/resources/chromeos/login/md_login.js
index 6bd75aa..52ef267 100644
--- a/chrome/browser/resources/chromeos/login/md_login.js
+++ b/chrome/browser/resources/chromeos/login/md_login.js
@@ -53,6 +53,7 @@
       login.ActiveDirectoryPasswordChangeScreen.register(/* lazyInit= */ true);
       login.EncryptionMigrationScreen.register();
       login.VoiceInteractionValuePropScreen.register();
+      login.WaitForContainerReadyScreen.register();
 
       cr.ui.Bubble.decorate($('bubble'));
       login.HeaderBar.decorate($('login-header-bar'));
diff --git a/chrome/browser/resources/chromeos/login/md_login_screens.html b/chrome/browser/resources/chromeos/login/md_login_screens.html
index 48c3aab..06db7cf 100644
--- a/chrome/browser/resources/chromeos/login/md_login_screens.html
+++ b/chrome/browser/resources/chromeos/login/md_login_screens.html
@@ -4,6 +4,7 @@
 <include src="oobe_screen_terms_of_service.html">
 <include src="oobe_screen_user_image.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
+<include src="oobe_screen_wait_for_container_ready.html">
 <include src="../../../../../ui/login/account_picker/md_screen_account_picker.html">
 <include src="screen_arc_terms_of_service.html">
 <include src="screen_error_message.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index 1e4b50a..dff22fb 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -135,6 +135,7 @@
       login.DeviceDisabledScreen.register();
       login.ActiveDirectoryPasswordChangeScreen.register(/* lazyInit= */ true);
       login.VoiceInteractionValuePropScreen.register();
+      login.WaitForContainerReadyScreen.register();
 
       cr.ui.Bubble.decorate($('bubble'));
       login.HeaderBar.decorate($('login-header-bar'));
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.html b/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.html
index f32e62f6..6a53ee5 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.html
@@ -3,7 +3,7 @@
      found in the LICENSE file. -->
 
 <div class="step faded hidden no-logo" id="voice-interaction-value-prop"
-    role="group">
+    role="group" hidden>
   <voice-interaction-value-prop-md
       id="voice-interaction-value-prop-md">
   </voice-interaction-value-prop-md>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.js b/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.js
index 3fdcd5ed..e2f77741 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_voice_interaction_value_prop.js
@@ -11,6 +11,14 @@
     function() {
       return {
 
+        /**
+         * Returns a control which should receive an initial focus.
+         */
+        get defaultControl() {
+          return $('voice-interaction-value-prop-md')
+              .getElement('continueButton');
+        },
+
         /** @Override */
         onBeforeShow: function(data) {
           var valueView = $('voice-interaction-value-prop-md')
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.css b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.css
new file mode 100644
index 0000000..1e0016e1
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.css
@@ -0,0 +1,10 @@
+/* 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. */
+
+#wait-for-container-ready {
+  display: flex;
+  flex-flow: column;
+  font-size: 16px;
+  width: 768px;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.html b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.html
new file mode 100644
index 0000000..74b770a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.html
@@ -0,0 +1,11 @@
+<!-- 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. -->
+
+<div class="step faded hidden no-logo" id="wait-for-container-ready"
+    role="group" hidden>
+  <wait-for-container-ready-md
+      id="wait-for-container-ready-md">
+  </wait-for-container-ready-md>
+</div>
+
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.js b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.js
new file mode 100644
index 0000000..55d90f7
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_wait_for_container_ready.js
@@ -0,0 +1,18 @@
+// 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.
+
+/**
+ * @fileoverview Oobe Wait For Container Ready screen implementation.
+ */
+
+login.createScreen(
+    'WaitForContainerReadyScreen', 'wait-for-container-ready', function() {
+      return {
+
+        /** @Override */
+        onBeforeShow: function(data) {
+          Oobe.getInstance().headerHidden = true;
+        }
+      };
+    });
diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html
index 2252e13..4f51fab 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screens.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screens.html
@@ -12,6 +12,7 @@
 <include src="oobe_screen_user_image.html">
 <include src="oobe_screen_hid_detection.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
+<include src="oobe_screen_wait_for_container_ready.html">
 <include src="../../../../../ui/login/account_picker/screen_account_picker.html">
 <include src="screen_error_message.html">
 <include src="screen_arc_terms_of_service.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.html b/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.html
index 1312074..54fce2d7 100644
--- a/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.html
+++ b/chrome/browser/resources/chromeos/login/oobe_voice_interaction_value_prop.html
@@ -18,7 +18,7 @@
         <oobe-text-button id="noThanksButton" border on-tap="onNoThanksTap_">
           <div i18n-content="voiceInteractionValuePropNoThanksButton"></div>
         </oobe-text-button>
-        <oobe-text-button inverse on-tap="onContinueTap_">
+        <oobe-text-button id="continueButton" inverse on-tap="onContinueTap_">
           <div i18n-content="voiceInteractionValuePropContinueButton"></div>
         </oobe-text-button>
       </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.css b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.css
new file mode 100644
index 0000000..f522f0ff
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.css
@@ -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. */
+
+.header {
+  margin-top: 15px;
+}
+
+.subtitle {
+  line-height: 20px;
+}
+
+paper-progress {
+  --paper-progress-active-color: rgb(66, 133, 244);
+  --paper-progress-container-color: #e6e6e6;
+  --paper-progress-secondary-color: rgb(66, 133, 244);
+  display: block;
+  padding: 48px 0 0 0;
+  width: 100%;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html
new file mode 100644
index 0000000..1ff662c3
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.html
@@ -0,0 +1,25 @@
+<!-- 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. -->
+
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
+
+<dom-module id="wait-for-container-ready-md">
+  <template>
+    <link rel="stylesheet" href="oobe_wait_for_container_ready.css">
+    <link rel="stylesheet" href="oobe_dialog_parameters.css">
+    <oobe-dialog id="waitForContainerReadyDialog" role="dialog" hide-shadow>
+      <iron-icon src="https://www.gstatic.com/opa-chromeos/oobe/images/assistant_logo.png" class="oobe-icon">
+      </iron-icon>
+      <div class="header">
+        <h1 class="title" i18n-content="waitForContainerReadyTitle"></h1>
+        <div class="subtitle">
+          <div i18n-content="waitForContainerReadyIntroMessage"></div>
+        </div>
+        <div class="content">
+          <paper-progress class="slow" indeterminate></paper-progress>
+        </div>
+      </div>
+    </oobe-dialog>
+  </template>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.js b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.js
new file mode 100644
index 0000000..9fd2bb9
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_wait_for_container_ready.js
@@ -0,0 +1,10 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying material design wait for
+ * container ready screen.
+ */
+
+Polymer({is: 'wait-for-container-ready-md'});
diff --git a/chrome/browser/resources/settings/device_page/compiled_resources2.gyp b/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
index 81bca0c6..f93da31 100644
--- a/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/device_page/compiled_resources2.gyp
@@ -108,7 +108,7 @@
       'target_name': 'night_light_slider',
       'dependencies': [
         '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-inky-focus-behavior-extracted',
         '../prefs/compiled_resources2.gyp:prefs_behavior',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/settings/device_page/night_light_slider.html b/chrome/browser/resources/settings/device_page/night_light_slider.html
index a9dde6f9..78a92c7 100644
--- a/chrome/browser/resources/settings/device_page/night_light_slider.html
+++ b/chrome/browser/resources/settings/device_page/night_light_slider.html
@@ -1,7 +1,7 @@
 <html><head>
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-inky-focus-behavior.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
 </head><body><dom-module id="night-light-slider">
   <template>
@@ -29,22 +29,29 @@
       }
 
       .knob {
-        background: rgb(51, 103, 214);
-        border-radius: 6px;
-        height: 12px;
-        left: 0;
-        margin-left: -6px;
-        margin-top: -5px;
+        height: 32px;
+        margin-left: -16px;
+        margin-top: -15px;
         position: absolute;
-        width: 12px;
-        z-index: 3;
+        width: 32px;
       }
 
       .knob:focus {
-        box-shadow: 0 0 5pt 5pt rgb(204, 217, 245);
         outline: none;
       }
 
+      .knob-inner {
+        background: var(--google-blue-700);
+        border-radius: 6px;
+        height: 12px;
+        left: 0;
+        margin-left: 10px;
+        margin-top: 10px;
+        position: absolute;
+        width: 12px;
+        z-index: 3;
+      }
+
       .expanded-knob {
         transform: scale(1.5);
         z-index: 3;
@@ -58,7 +65,7 @@
       }
 
       .progress {
-        background: rgb(51, 103, 214);
+        background: var(--google-blue-700);
         height: 100%;
         position: absolute;
         z-index: 1;
@@ -69,7 +76,7 @@
       }
 
       .label {
-        background: rgb(51, 103, 214);
+        background: var(--google-blue-700);
         border-radius: 14px;
         color: white;
         font-family: Roboto-Bold;
@@ -123,6 +130,10 @@
         top: 5px;
         width: 5em;
       }
+
+      paper-ripple {
+        color: var(--google-blue-700);
+      }
     </style>
 
     <div id="sliderContainer">
@@ -144,9 +155,15 @@
         <div id="markersContainer">
         </div>
         <div id="startKnob" class="knob" tabindex="1" on-down="startDrag_"
-            on-up="endDrag_" on-track="continueDrag_"></div>
+            on-up="endDrag_" on-track="continueDrag_" on-focus="onFocus_"
+            on-blur="onBlur_">
+          <div class="knob-inner" tabindex="-1"></div>
+        </div>
         <div id="endKnob" class="knob" tabindex="2" on-down="startDrag_"
-            on-up="endDrag_" on-track="continueDrag_"></div>
+            on-up="endDrag_" on-track="continueDrag_" on-focus="onFocus_"
+            on-blur="onBlur_">
+          <div class="knob-inner" tabindex="-1"></div>
+        </div>
       </div>
       <div id="legendContainer">
         <div style="left: 0%;">[[getLocaleTimeString_(18, 0)]]</div>
@@ -155,6 +172,7 @@
         <div style="left: 75%;">[[getLocaleTimeString_(12, 0)]]</div>
         <div style="left: 100%;">[[getLocaleTimeString_(18, 0)]]</div>
       </div>
+      <div id="dummyRippleContainer" hidden></div>
     </div>
 
   </template>
diff --git a/chrome/browser/resources/settings/device_page/night_light_slider.js b/chrome/browser/resources/settings/device_page/night_light_slider.js
index 48aeaec..3c84b86 100644
--- a/chrome/browser/resources/settings/device_page/night_light_slider.js
+++ b/chrome/browser/resources/settings/device_page/night_light_slider.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+(function() {
+
 /**
  * @fileoverview
  * night-light-slider is used to set the custom automatic schedule of the
@@ -18,37 +20,23 @@
   is: 'night-light-slider',
 
   behaviors: [
-    I18nBehavior,
     PrefsBehavior,
     Polymer.IronA11yKeysBehavior,
+    Polymer.PaperInkyFocusBehavior,
   ],
 
   properties: {
     /**
-     * The object currently being dragged. Either the start or end knobs.
-     * @type {?Object}
-     * @private
-     */
-    dragObject_: {
-      type: Object,
-      value: null,
-    },
-
-    /**
      * The start knob time as a string to be shown on the start label bubble.
      * @private
      */
-    startTime_: {
-      type: String,
-    },
+    startTime_: String,
 
     /**
      * The end knob time as a string to be shown on the end label bubble.
      * @private
      */
-    endTime_: {
-      type: String,
-    },
+    endTime_: String,
   },
 
   observers: [
@@ -61,6 +49,14 @@
     'right': 'onRightKey_',
   },
 
+  /**
+   * The object currently being dragged. Either the start or end knobs.
+   * @type {?Object}
+   * @private
+   */
+  dragObject_: null,
+
+  /** @override */
   ready: function() {
     // Build the legend markers.
     var markersContainer = this.$.markersContainer;
@@ -71,6 +67,7 @@
       markersContainer.appendChild(marker);
       marker.style.left = (i * 100 / HOURS_PER_DAY) + '%';
     }
+
     this.async(function() {
       // Read the initial prefs values and refresh the slider.
       this.customTimesChanged_();
@@ -111,7 +108,19 @@
    */
   startDrag_: function(event) {
     event.preventDefault();
-    this.dragObject_ = event.target;
+
+    // Only handle start or end knobs. Use the "knob-inner" divs just to display
+    // the knobs.
+    if (event.target == this.$.startKnob ||
+        event.target == this.$.startKnob.firstElementChild) {
+      this.dragObject_ = this.$.startKnob;
+    } else if (event.target == this.$.endKnob ||
+               event.target == this.$.endKnob.firstElementChild) {
+      this.dragObject_ = this.$.endKnob;
+    } else {
+      return;
+    }
+
     this.setExpanded_(true);
 
     // Focus is only given to the knobs by means of keyboard tab navigations.
@@ -449,4 +458,68 @@
 
     this.incrementPref_(knobPref, 1);
   },
-});
\ No newline at end of file
+
+  /**
+   * @return {boolean} Whether either of the two knobs is focused.
+   * @private
+   */
+  isEitherKnobFocused_: function() {
+    var activeElement = this.shadowRoot.activeElement;
+    return activeElement == this.$.startKnob || activeElement == this.$.endKnob;
+  },
+
+  /**
+   * Overrides _createRipple() from PaperInkyFocusBehavior to create the ripple
+   * only on a knob if it's focused, or on a dummy hidden element so that it
+   * doesn't show.
+   * @private
+   */
+  _createRipple: function() {
+    if (this.isEitherKnobFocused_()) {
+      this._rippleContainer = this.shadowRoot.activeElement;
+    } else {
+      // We can't just skip the ripple creation and return early with null here.
+      // The code inherited from PaperInkyFocusBehavior expects that this
+      // function returns a ripple element. So to avoid crashes, we'll setup the
+      // ripple to be created under a hidden element.
+      this._rippleContainer = this.$.dummyRippleContainer;
+    }
+
+    return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this);
+  },
+
+  /**
+   * Handles focus events on the start and end knobs.
+   * @private
+   */
+  onFocus_: function() {
+    this.ensureRipple();
+
+    if (this.hasRipple()) {
+      this._ripple.style.display = '';
+      this._ripple.holdDown = true;
+    }
+  },
+
+  /**
+   * Handles blur events on the start and end knobs.
+   * @private
+   */
+  onBlur_: function() {
+    if (this.hasRipple()) {
+      this._ripple.remove();
+      this._ripple = null;
+    }
+  },
+
+  /** @private */
+  _focusedChanged: function(receivedFocusFromKeyboard) {
+    // Overrides the _focusedChanged() from the PaperInkyFocusBehavior so that
+    // it does nothing. This function is called only once for the entire
+    // night-light-slider element even when focus is moved between the two
+    // knobs. This doesn't allow us to decide on which knob the ripple will be
+    // created. Hence we handle focus and blur explicitly above.
+  }
+});
+
+})();
\ No newline at end of file
diff --git a/chrome/browser/spellchecker/spellcheck_factory.cc b/chrome/browser/spellchecker/spellcheck_factory.cc
index 9d94c21c..a8669938 100644
--- a/chrome/browser/spellchecker/spellcheck_factory.cc
+++ b/chrome/browser/spellchecker/spellcheck_factory.cc
@@ -78,7 +78,7 @@
       l10n_util::GetStringUTF8(IDS_SPELLCHECK_DICTIONARY));
   user_prefs->RegisterBooleanPref(
       spellcheck::prefs::kSpellCheckUseSpellingService, false);
-#if defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
   uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS;
 #else
   uint32_t flags = user_prefs::PrefRegistrySyncable::SYNCABLE_PREF;
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.cc b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
index a26a7c1..9697c08 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
@@ -150,6 +150,7 @@
 void ChromeExpectCTReporter::OnExpectCTFailed(
     const net::HostPortPair& host_port_pair,
     const GURL& report_uri,
+    base::Time expiration,
     const net::X509Certificate* validated_certificate_chain,
     const net::X509Certificate* served_certificate_chain,
     const net::SignedCertificateTimestampAndStatusList&
@@ -160,13 +161,11 @@
   if (!base::FeatureList::IsEnabled(features::kExpectCTReporting))
     return;
 
-  // TODO(estark): De-duplicate reports so that the same report isn't
-  // sent too often in some period of time.
-
   base::DictionaryValue report;
   report.SetString("hostname", host_port_pair.host());
   report.SetInteger("port", host_port_pair.port());
   report.SetString("date-time", TimeToISO8601(base::Time::Now()));
+  report.SetString("effective-expiration-date", TimeToISO8601(expiration));
   report.Set("served-certificate-chain",
              GetPEMEncodedChainAsList(served_certificate_chain));
   report.Set("validated-certificate-chain",
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.h b/chrome/browser/ssl/chrome_expect_ct_reporter.h
index b0663e7..f45d9ad5 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.h
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.h
@@ -28,6 +28,7 @@
   // net::ExpectCTReporter:
   void OnExpectCTFailed(const net::HostPortPair& host_port_pair,
                         const GURL& report_uri,
+                        base::Time expiration,
                         const net::X509Certificate* validated_certificate_chain,
                         const net::X509Certificate* served_certificate_chain,
                         const net::SignedCertificateTimestampAndStatusList&
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
index 5c39c39f..776aec22 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
@@ -236,6 +236,7 @@
 // |ssl_info|.
 void CheckExpectCTReport(const std::string& serialized_report,
                          const net::HostPortPair& host_port,
+                         const std::string& expiration,
                          const net::SSLInfo& ssl_info) {
   std::unique_ptr<base::Value> value(base::JSONReader::Read(serialized_report));
   ASSERT_TRUE(value);
@@ -251,6 +252,11 @@
   EXPECT_TRUE(report_dict->GetInteger("port", &report_port));
   EXPECT_EQ(host_port.port(), report_port);
 
+  std::string report_expiration;
+  EXPECT_TRUE(
+      report_dict->GetString("effective-expiration-date", &report_expiration));
+  EXPECT_EQ(expiration, report_expiration);
+
   const base::ListValue* report_served_certificate_chain = nullptr;
   ASSERT_TRUE(report_dict->GetList("served-certificate-chain",
                                    &report_served_certificate_chain));
@@ -322,13 +328,14 @@
   void SendReport(ChromeExpectCTReporter* reporter,
                   const net::HostPortPair& host_port,
                   const GURL& report_uri,
+                  base::Time expiration,
                   const net::SSLInfo& ssl_info) {
     base::RunLoop run_loop;
     network_delegate_.set_url_request_destroyed_callback(
         run_loop.QuitClosure());
-    reporter->OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(),
-                               ssl_info.unverified_cert.get(),
-                               ssl_info.signed_certificate_timestamps);
+    reporter->OnExpectCTFailed(
+        host_port, report_uri, expiration, ssl_info.cert.get(),
+        ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
     run_loop.Run();
   }
 
@@ -367,8 +374,8 @@
   net::HostPortPair host_port("example.test", 443);
   GURL report_uri("http://example-report.test");
 
-  reporter.OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(),
-                            ssl_info.unverified_cert.get(),
+  reporter.OnExpectCTFailed(host_port, report_uri, base::Time(),
+                            ssl_info.cert.get(), ssl_info.unverified_cert.get(),
                             ssl_info.signed_certificate_timestamps);
   EXPECT_TRUE(sender->latest_report_uri().is_empty());
   EXPECT_TRUE(sender->latest_serialized_report().empty());
@@ -389,7 +396,8 @@
   EXPECT_TRUE(sender->latest_report_uri().is_empty());
   EXPECT_TRUE(sender->latest_serialized_report().empty());
 
-  reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), nullptr, nullptr,
+  reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), base::Time(), nullptr,
+                            nullptr,
                             net::SignedCertificateTimestampAndStatusList());
   EXPECT_TRUE(sender->latest_report_uri().is_empty());
   EXPECT_TRUE(sender->latest_serialized_report().empty());
@@ -415,7 +423,7 @@
   GURL report_uri(
       net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED));
 
-  SendReport(&reporter, host_port, report_uri, ssl_info);
+  SendReport(&reporter, host_port, report_uri, base::Time(), ssl_info);
 
   histograms.ExpectTotalCount(kFailureHistogramName, 1);
   histograms.ExpectBucketCount(kFailureHistogramName,
@@ -487,15 +495,21 @@
   net::HostPortPair host_port("example.test", 443);
   GURL report_uri("http://example-report.test");
 
+  const char kExpirationTimeStr[] = "2017-01-01T00:00:00.000Z";
+  base::Time expiration;
+  ASSERT_TRUE(
+      base::Time::FromUTCExploded({2017, 1, 0, 1, 0, 0, 0, 0}, &expiration));
+
   // Check that the report is sent and contains the correct information.
-  reporter.OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(),
-                            ssl_info.unverified_cert.get(),
+  reporter.OnExpectCTFailed(host_port, report_uri, expiration,
+                            ssl_info.cert.get(), ssl_info.unverified_cert.get(),
                             ssl_info.signed_certificate_timestamps);
   EXPECT_EQ(report_uri, sender->latest_report_uri());
   EXPECT_FALSE(sender->latest_serialized_report().empty());
   EXPECT_EQ("application/json; charset=utf-8", sender->latest_content_type());
-  ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport(
-      sender->latest_serialized_report(), host_port, ssl_info));
+  ASSERT_NO_FATAL_FAILURE(
+      CheckExpectCTReport(sender->latest_serialized_report(), host_port,
+                          kExpirationTimeStr, ssl_info));
 
   histograms.ExpectTotalCount(kFailureHistogramName, 0);
   histograms.ExpectTotalCount(kSendHistogramName, 1);
diff --git a/chrome/browser/task_manager/providers/browser_process_task_unittest.cc b/chrome/browser/task_manager/providers/browser_process_task_unittest.cc
index 15fbc672b..45ff115f 100644
--- a/chrome/browser/task_manager/providers/browser_process_task_unittest.cc
+++ b/chrome/browser/task_manager/providers/browser_process_task_unittest.cc
@@ -75,14 +75,12 @@
   EXPECT_EQ(Task::BROWSER, provided_task_->GetType());
   EXPECT_EQ(0, provided_task_->GetChildProcessUniqueID());
   const int received_bytes = 1024;
-  EXPECT_FALSE(provided_task_->ReportsNetworkUsage());
-  EXPECT_EQ(-1, provided_task_->network_usage());
+  EXPECT_EQ(0, provided_task_->network_usage_rate());
   provided_task_->OnNetworkBytesRead(received_bytes);
   // Do a refresh with a 1-second update time.
   provided_task_->Refresh(base::TimeDelta::FromSeconds(1),
                           REFRESH_TYPE_NETWORK_USAGE);
-  EXPECT_TRUE(provided_task_->ReportsNetworkUsage());
-  EXPECT_EQ(received_bytes, provided_task_->network_usage());
+  EXPECT_EQ(received_bytes, provided_task_->network_usage_rate());
 }
 
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/child_process_task_unittest.cc b/chrome/browser/task_manager/providers/child_process_task_unittest.cc
index e055753..9a9c1fe 100644
--- a/chrome/browser/task_manager/providers/child_process_task_unittest.cc
+++ b/chrome/browser/task_manager/providers/child_process_task_unittest.cc
@@ -131,7 +131,6 @@
   EXPECT_FALSE(task->ReportsSqliteMemory());
   EXPECT_FALSE(task->ReportsV8Memory());
   EXPECT_FALSE(task->ReportsWebCacheStats());
-  EXPECT_FALSE(task->ReportsNetworkUsage());
 
   // Make sure that the conversion from PID to Handle inside
   // |GetTaskOfUrlRequest()| is working properly.
@@ -143,8 +142,7 @@
   found_task->Refresh(base::TimeDelta::FromSeconds(1),
                       REFRESH_TYPE_NETWORK_USAGE);
 
-  EXPECT_TRUE(task->ReportsNetworkUsage());
-  EXPECT_EQ(bytes_read, task->network_usage());
+  EXPECT_EQ(bytes_read, task->network_usage_rate());
 
   // Clearing the observer won't notify us of any tasks removals even though
   // tasks will be actually deleted.
diff --git a/chrome/browser/task_manager/providers/task.cc b/chrome/browser/task_manager/providers/task.cc
index a49032f..1306017 100644
--- a/chrome/browser/task_manager/providers/task.cc
+++ b/chrome/browser/task_manager/providers/task.cc
@@ -30,8 +30,12 @@
            base::ProcessHandle handle,
            base::ProcessId process_id)
     : task_id_(g_last_id++),
-      network_usage_(-1),
-      current_byte_count_(-1),
+      last_refresh_cumulative_bytes_sent_(0),
+      last_refresh_cumulative_bytes_read_(0),
+      cumulative_bytes_sent_(0),
+      cumulative_bytes_read_(0),
+      network_sent_rate_(0),
+      network_read_rate_(0),
       title_(title),
       rappor_sample_name_(rappor_sample),
       icon_(icon ? *icon : gfx::ImageSkia()),
@@ -70,24 +74,32 @@
 
 void Task::Refresh(const base::TimeDelta& update_interval,
                    int64_t refresh_flags) {
-  if ((refresh_flags & REFRESH_TYPE_NETWORK_USAGE) == 0)
+  if ((refresh_flags & REFRESH_TYPE_NETWORK_USAGE) == 0 ||
+      update_interval == base::TimeDelta())
     return;
 
-  if (current_byte_count_ == -1)
-    return;
+  int64_t current_cycle_read_byte_count =
+      cumulative_bytes_read_ - last_refresh_cumulative_bytes_read_;
+  network_read_rate_ =
+      (current_cycle_read_byte_count * base::TimeDelta::FromSeconds(1)) /
+      update_interval;
 
-  network_usage_ =
-      (current_byte_count_ * base::TimeDelta::FromSeconds(1)) / update_interval;
+  int64_t current_cycle_sent_byte_count =
+      cumulative_bytes_sent_ - last_refresh_cumulative_bytes_sent_;
+  network_sent_rate_ =
+      (current_cycle_sent_byte_count * base::TimeDelta::FromSeconds(1)) /
+      update_interval;
 
-  // Reset the current byte count for this task.
-  current_byte_count_ = 0;
+  last_refresh_cumulative_bytes_read_ = cumulative_bytes_read_;
+  last_refresh_cumulative_bytes_sent_ = cumulative_bytes_sent_;
 }
 
 void Task::OnNetworkBytesRead(int64_t bytes_read) {
-  if (current_byte_count_ == -1)
-    current_byte_count_ = 0;
+  cumulative_bytes_read_ += bytes_read;
+}
 
-  current_byte_count_ += bytes_read;
+void Task::OnNetworkBytesSent(int64_t bytes_sent) {
+  cumulative_bytes_sent_ += bytes_sent;
 }
 
 void Task::GetTerminationStatus(base::TerminationStatus* out_status,
@@ -147,8 +159,4 @@
   return -1;
 }
 
-bool Task::ReportsNetworkUsage() const {
-  return network_usage_ != -1;
-}
-
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/task.h b/chrome/browser/task_manager/providers/task.h
index a3e91cee..e72fae90 100644
--- a/chrome/browser/task_manager/providers/task.h
+++ b/chrome/browser/task_manager/providers/task.h
@@ -85,9 +85,14 @@
 
   // Will receive this notification through the task manager from
   // |ChromeNetworkDelegate::OnNetworkBytesReceived()|. The task will add to the
-  // |current_byte_count_| in this refresh cycle.
+  // |cummulative_read_bytes_|.
   void OnNetworkBytesRead(int64_t bytes_read);
 
+  // Will receive this notification through the task manager from
+  // |ChromeNetworkDelegate::OnNetworkBytesSent()|. The task will add to the
+  // |cummulative_sent_bytes_| in this refresh cycle.
+  void OnNetworkBytesSent(int64_t bytes_sent);
+
   // Returns the task type.
   virtual Type GetType() const = 0;
 
@@ -138,11 +143,22 @@
   // Returns the keep-alive counter if the Task is an event page, -1 otherwise.
   virtual int GetKeepaliveCount() const;
 
-  // Checking whether the task reports network usage.
-  bool ReportsNetworkUsage() const;
-
   int64_t task_id() const { return task_id_; }
-  int64_t network_usage() const { return network_usage_; }
+
+  // Returns the instantaneous rate, in bytes per second, of network usage
+  // (sent and received), as measured over the last refresh cycle.
+  int64_t network_usage_rate() const {
+    return network_sent_rate_ + network_read_rate_;
+  }
+
+  // Returns the cumulative number of bytes of network use (sent and received)
+  // over the tasks lifetime. It is calculated independently of refreshes and
+  // is based on the current |cumulative_bytes_read_| and
+  // |cumulative_bytes_sent_|.
+  int64_t cumulative_network_usage() const {
+    return cumulative_bytes_sent_ + cumulative_bytes_read_;
+  }
+
   const base::string16& title() const { return title_; }
   const std::string& rappor_sample_name() const { return rappor_sample_name_; }
   const gfx::ImageSkia& icon() const { return icon_; }
@@ -160,14 +176,31 @@
   // The unique ID of this task.
   const int64_t task_id_;
 
-  // The task's network usage in the current refresh cycle measured in bytes per
-  // second. A value of -1 means this task doesn't report network usage data.
-  int64_t network_usage_;
+  // The sum of all bytes that have been uploaded from this task calculated at
+  // the last refresh.
+  int64_t last_refresh_cumulative_bytes_sent_;
 
-  // The current network bytes received by this task during the current refresh
-  // cycle. A value of -1 means this task has never been notified of any network
-  // usage.
-  int64_t current_byte_count_;
+  // The sum of all bytes that have been downloaded from this task calculated
+  // at the last refresh.
+  int64_t last_refresh_cumulative_bytes_read_;
+
+  // A continuously updating sum of all bytes that have been uploaded from this
+  // task. It is assigned to |last_refresh_cumulative_bytes_sent_| at the end
+  // of a refresh.
+  int64_t cumulative_bytes_sent_;
+
+  // A continuously updating sum of all bytes that have been downloaded from
+  // this task. It is assigned to |last_refresh_cumulative_bytes_sent_| at the
+  // end of a refresh.
+  int64_t cumulative_bytes_read_;
+
+  // The upload rate (in bytes per second) for this task during the latest
+  // refresh.
+  int64_t network_sent_rate_;
+
+  // The download rate (in bytes per second) for this task during the latest
+  // refresh.
+  int64_t network_read_rate_;
 
   // The title of the task.
   base::string16 title_;
diff --git a/chrome/browser/task_manager/sampling/task_group.cc b/chrome/browser/task_manager/sampling/task_group.cc
index ce846005..2250522 100644
--- a/chrome/browser/task_manager/sampling/task_group.cc
+++ b/chrome/browser/task_manager/sampling/task_group.cc
@@ -91,7 +91,8 @@
       cpu_usage_(0.0),
       gpu_memory_(-1),
       memory_state_(base::MemoryState::UNKNOWN),
-      per_process_network_usage_(-1),
+      per_process_network_usage_rate_(-1),
+      cumulative_per_process_network_usage_(0),
 #if defined(OS_WIN)
       gdi_current_handles_(-1),
       gdi_peak_handles_(-1),
@@ -155,7 +156,6 @@
                         int64_t refresh_flags) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!empty());
-
   expected_on_bg_done_flags_ = refresh_flags & kBackgroundRefreshTypesMask;
   // If a refresh type was recently disabled, we need to account for that too.
   current_on_bg_done_flags_ &= expected_on_bg_done_flags_;
@@ -165,12 +165,15 @@
   const bool network_usage_refresh_enabled =
       TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_NETWORK_USAGE,
                                                     refresh_flags);
-  per_process_network_usage_ = network_usage_refresh_enabled ? 0 : -1;
+
+  per_process_network_usage_rate_ = network_usage_refresh_enabled ? 0 : -1;
+  cumulative_per_process_network_usage_ = 0;
   for (Task* task : tasks_) {
     task->Refresh(update_interval, refresh_flags);
-
-    if (network_usage_refresh_enabled && task->ReportsNetworkUsage())
-      per_process_network_usage_ += task->network_usage();
+    if (network_usage_refresh_enabled) {
+      per_process_network_usage_rate_ += task->network_usage_rate();
+      cumulative_per_process_network_usage_ += task->cumulative_network_usage();
+    }
   }
 
   // 2- Refresh GPU memory (if enabled).
diff --git a/chrome/browser/task_manager/sampling/task_group.h b/chrome/browser/task_manager/sampling/task_group.h
index 7768367..6e84a61 100644
--- a/chrome/browser/task_manager/sampling/task_group.h
+++ b/chrome/browser/task_manager/sampling/task_group.h
@@ -80,8 +80,11 @@
   int64_t gpu_memory() const { return gpu_memory_; }
   bool gpu_memory_has_duplicates() const { return gpu_memory_has_duplicates_; }
   base::MemoryState memory_state() const { return memory_state_; }
-  int64_t per_process_network_usage() const {
-    return per_process_network_usage_;
+  int64_t per_process_network_usage_rate() const {
+    return per_process_network_usage_rate_;
+  }
+  int64_t cumulative_per_process_network_usage() const {
+    return cumulative_per_process_network_usage_;
   }
   bool is_backgrounded() const { return is_backgrounded_; }
 
@@ -162,7 +165,12 @@
   base::MemoryState memory_state_;
   // The network usage in bytes per second as the sum of all network usages of
   // the individual tasks sharing the same process.
-  int64_t per_process_network_usage_;
+  int64_t per_process_network_usage_rate_;
+
+  // A continuously updating sum of all bytes that have been downloaded and
+  // uploaded by all tasks in this process.
+  int64_t cumulative_per_process_network_usage_;
+
 #if defined(OS_WIN)
   // Windows GDI and USER Handles.
   int64_t gdi_current_handles_;
diff --git a/chrome/browser/task_manager/sampling/task_group_unittest.cc b/chrome/browser/task_manager/sampling/task_group_unittest.cc
index 19e640b1..8852e46a 100644
--- a/chrome/browser/task_manager/sampling/task_group_unittest.cc
+++ b/chrome/browser/task_manager/sampling/task_group_unittest.cc
@@ -166,4 +166,355 @@
   EXPECT_TRUE(task_group_.AreBackgroundCalculationsDone());
 }
 
+// Test the task has correct network usage rate when zero bytes read and sent.
+TEST_F(TaskGroupTest, NetworkBytesSentReadZero) {
+  const int zero_bytes = 0;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesRead(zero_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(zero_bytes, fake_task.network_usage_rate());
+  fake_task.OnNetworkBytesSent(zero_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(zero_bytes, fake_task.network_usage_rate());
+}
+
+// Test the task has correct network usage rate when only having read bytes.
+TEST_F(TaskGroupTest, NetworkBytesRead) {
+  const int read_bytes = 1024;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesRead(read_bytes);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(read_bytes, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+}
+
+// Test the task has correct network usage rate when only having sent bytes.
+TEST_F(TaskGroupTest, NetworkBytesSent) {
+  const int sent_bytes = 1023;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesSent(sent_bytes);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(sent_bytes, fake_task.cumulative_network_usage());
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(sent_bytes, fake_task.network_usage_rate());
+  EXPECT_EQ(sent_bytes, fake_task.cumulative_network_usage());
+}
+
+// Test the task has correct network usage rate when only having read bytes and
+// having a non 1s refresh time.
+TEST_F(TaskGroupTest, NetworkBytesRead2SecRefresh) {
+  const int refresh_secs = 2;
+  const int read_bytes = 1024 * refresh_secs;  // for integer division
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesRead(read_bytes);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+  fake_task.Refresh(base::TimeDelta::FromSeconds(refresh_secs),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(read_bytes / refresh_secs, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+}
+
+// Test the task has correct network usage rate when only having sent bytes and
+// having a non 1s refresh time.
+TEST_F(TaskGroupTest, NetworkBytesSent2SecRefresh) {
+  const int refresh_secs = 2;
+  const int sent_bytes = 1023 * refresh_secs;  // for integer division
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesSent(sent_bytes);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(sent_bytes, fake_task.cumulative_network_usage());
+  fake_task.Refresh(base::TimeDelta::FromSeconds(refresh_secs),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(sent_bytes / refresh_secs, fake_task.network_usage_rate());
+  EXPECT_EQ(sent_bytes, fake_task.cumulative_network_usage());
+}
+
+// Tests the task has correct usage on receiving and then sending bytes.
+TEST_F(TaskGroupTest, NetworkBytesReadThenSent) {
+  const int read_bytes = 124;
+  const int sent_bytes = 1027;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesRead(read_bytes);
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+  fake_task.OnNetworkBytesSent(sent_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(read_bytes + sent_bytes, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes + sent_bytes, fake_task.cumulative_network_usage());
+}
+
+// Tests the task has correct usage rate on sending and then receiving bytes.
+TEST_F(TaskGroupTest, NetworkBytesSentThenRead) {
+  const int read_bytes = 1025;
+  const int sent_bytes = 10;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesSent(sent_bytes);
+  fake_task.OnNetworkBytesRead(read_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(read_bytes + sent_bytes, fake_task.network_usage_rate());
+}
+
+// Tests that the network usage rate goes to 0 after reading bytes then a
+// refresh with no traffic and that cumulative is still correct.
+TEST_F(TaskGroupTest, NetworkBytesReadRefreshNone) {
+  const int read_bytes = 1024;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesRead(read_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  // Refresh to zero out the usage rate.
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(read_bytes, fake_task.cumulative_network_usage());
+}
+
+// Tests that the network usage rate goes to 0 after sending bytes then a
+// refresh with no traffic and that cumulative is still correct.
+TEST_F(TaskGroupTest, NetworkBytesSentRefreshNone) {
+  const int sent_bytes = 1024;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  fake_task.OnNetworkBytesSent(sent_bytes);
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  // Refresh to zero out the usage rate.
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(sent_bytes, fake_task.cumulative_network_usage());
+}
+
+// Tests that the network usage rate goes to 0 after a refresh with no traffic
+// and that cumulative is still correct.
+TEST_F(TaskGroupTest, NetworkBytesTransferredRefreshNone) {
+  const int read_bytes = 1024;
+  const int sent_bytes = 1;
+  const int number_of_cycles = 2;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task.OnNetworkBytesRead(read_bytes);
+    fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+    fake_task.OnNetworkBytesSent(sent_bytes);
+    fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+  }
+  // Refresh to zero out the usage rate.
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ((read_bytes + sent_bytes) * number_of_cycles,
+            fake_task.cumulative_network_usage());
+}
+
+// Tests that 2 tasks in 1 task group that both read bytes have correct usage
+// rates and correct cumulative network usage.
+TEST_F(TaskGroupTest, NetworkBytesReadAsGroup) {
+  const int read_bytes1 = 1024;
+  const int read_bytes2 = 789;
+  const int number_of_cycles = 2;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task1.OnNetworkBytesRead(read_bytes1);
+    fake_task2.OnNetworkBytesRead(read_bytes2);
+    task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                        base::TimeDelta::FromSeconds(1),
+                        REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ(read_bytes1 + read_bytes2,
+              task_group_.per_process_network_usage_rate());
+  }
+
+  EXPECT_EQ((read_bytes1 + read_bytes2) * number_of_cycles,
+            task_group_.cumulative_per_process_network_usage());
+}
+
+// Tests that the network usage rate does not get affected until a refresh is
+// called and that the cumulative is as up to date as possible
+TEST_F(TaskGroupTest, NetworkBytesTransferredRefreshOutOfOrder) {
+  const int read_bytes = 1024;
+  const int sent_bytes = 1;
+  const int number_of_cycles = 4;
+  int number_of_bytes_transferred = 0;
+  FakeTask fake_task(base::Process::Current().Pid(), Task::RENDERER);
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task.OnNetworkBytesRead(read_bytes * i);
+    number_of_bytes_transferred += read_bytes * i;
+    EXPECT_EQ(number_of_bytes_transferred,
+              fake_task.cumulative_network_usage());
+    fake_task.OnNetworkBytesSent(sent_bytes * i);
+    number_of_bytes_transferred += sent_bytes * i;
+    EXPECT_EQ(number_of_bytes_transferred,
+              fake_task.cumulative_network_usage());
+    if (i > 0) {
+      EXPECT_EQ((read_bytes + sent_bytes) * (i - 1),
+                fake_task.network_usage_rate());
+    }
+    fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ((read_bytes + sent_bytes) * i, fake_task.network_usage_rate());
+  }
+  // Refresh to zero out the usage rate.
+  fake_task.Refresh(base::TimeDelta::FromSeconds(1),
+                    REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, fake_task.network_usage_rate());
+  EXPECT_EQ(number_of_bytes_transferred, fake_task.cumulative_network_usage());
+}
+
+// Tests that 2 tasks in 1 task group that both sent bytes have correct usage
+// rates and correct cumulative network usage.
+TEST_F(TaskGroupTest, NetworkBytesSentAsGroup) {
+  const int sent_bytes1 = 1123;
+  const int sent_bytes2 = 778;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+
+  fake_task1.OnNetworkBytesSent(sent_bytes1);
+  fake_task2.OnNetworkBytesSent(sent_bytes2);
+  task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                      base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(sent_bytes1 + sent_bytes2,
+            task_group_.per_process_network_usage_rate());
+
+  fake_task1.OnNetworkBytesSent(sent_bytes1);
+  fake_task2.OnNetworkBytesSent(sent_bytes2);
+  task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                      base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+
+  EXPECT_EQ((sent_bytes1 + sent_bytes2) * 2,
+            task_group_.cumulative_per_process_network_usage());
+}
+
+// Tests that 2 tasks in 1  task group that have one sending and one reading
+// have correct usage rates for the group and correct cumulative network usage.
+TEST_F(TaskGroupTest, NetworkBytesTransferredAsGroup) {
+  const int sent_bytes = 1023;
+  const int read_bytes = 678;
+  const int number_of_cycles = 2;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task1.OnNetworkBytesSent(sent_bytes);
+    fake_task2.OnNetworkBytesRead(read_bytes);
+    task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                        base::TimeDelta::FromSeconds(1),
+                        REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ(sent_bytes + read_bytes,
+              task_group_.per_process_network_usage_rate());
+  }
+
+  EXPECT_EQ((read_bytes + sent_bytes) * number_of_cycles,
+            task_group_.cumulative_per_process_network_usage());
+}
+
+// Tests that after two tasks in a task group read bytes that a refresh will
+// zero out network usage rate while maintaining the correct cumulative network
+// usage
+TEST_F(TaskGroupTest, NetworkBytesReadAsGroupThenNone) {
+  const int read_bytes1 = 1013;
+  const int read_bytes2 = 679;
+  const int number_of_cycles = 2;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task1.OnNetworkBytesRead(read_bytes1);
+    fake_task2.OnNetworkBytesRead(read_bytes2);
+    task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                        base::TimeDelta::FromSeconds(1),
+                        REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ(read_bytes1 + read_bytes2,
+              task_group_.per_process_network_usage_rate());
+  }
+  task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                      base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, task_group_.per_process_network_usage_rate());
+  EXPECT_EQ((read_bytes1 + read_bytes2) * number_of_cycles,
+            task_group_.cumulative_per_process_network_usage());
+}
+
+// Tests that after two tasks in a task group send bytes that a refresh will
+// zero out network usage rate while maintaining the correct cumulative network
+// usage
+TEST_F(TaskGroupTest, NetworkBytesSentAsGroupThenNone) {
+  const int sent_bytes1 = 1023;
+  const int sent_bytes2 = 678;
+  const int number_of_cycles = 2;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task1.OnNetworkBytesSent(sent_bytes1);
+    fake_task2.OnNetworkBytesSent(sent_bytes2);
+    task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                        base::TimeDelta::FromSeconds(1),
+                        REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ(sent_bytes1 + sent_bytes2,
+              task_group_.per_process_network_usage_rate());
+  }
+  task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                      base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, task_group_.per_process_network_usage_rate());
+  EXPECT_EQ((sent_bytes1 + sent_bytes2) * number_of_cycles,
+            task_group_.cumulative_per_process_network_usage());
+}
+
+// Tests that after two tasks in a task group transferred bytes that a refresh
+// will zero out network usage rate while maintaining the correct cumulative
+// network usage
+TEST_F(TaskGroupTest, NetworkBytesTransferredAsGroupThenNone) {
+  const int read_bytes = 321;
+  const int sent_bytes = 987;
+  const int number_of_cycles = 3;
+  FakeTask fake_task1(base::Process::Current().Pid(), Task::RENDERER);
+  FakeTask fake_task2(base::Process::Current().Pid(), Task::RENDERER);
+
+  task_group_.AddTask(&fake_task1);
+  task_group_.AddTask(&fake_task2);
+
+  for (int i = 0; i < number_of_cycles; i++) {
+    fake_task1.OnNetworkBytesRead(read_bytes);
+    fake_task2.OnNetworkBytesSent(sent_bytes);
+    task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                        base::TimeDelta::FromSeconds(1),
+                        REFRESH_TYPE_NETWORK_USAGE);
+    EXPECT_EQ(read_bytes + sent_bytes,
+              task_group_.per_process_network_usage_rate());
+  }
+  task_group_.Refresh(gpu::VideoMemoryUsageStats(),
+                      base::TimeDelta::FromSeconds(1),
+                      REFRESH_TYPE_NETWORK_USAGE);
+  EXPECT_EQ(0, task_group_.per_process_network_usage_rate());
+  EXPECT_EQ((read_bytes + sent_bytes) * number_of_cycles,
+            task_group_.cumulative_per_process_network_usage());
+}
+
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc
index ca2dbb8b..9cae990 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.cc
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -228,11 +228,20 @@
 }
 
 int64_t TaskManagerImpl::GetNetworkUsage(TaskId task_id) const {
-  return GetTaskByTaskId(task_id)->network_usage();
+  return GetTaskByTaskId(task_id)->network_usage_rate();
+}
+
+int64_t TaskManagerImpl::GetCumulativeNetworkUsage(TaskId task_id) const {
+  return GetTaskByTaskId(task_id)->cumulative_network_usage();
 }
 
 int64_t TaskManagerImpl::GetProcessTotalNetworkUsage(TaskId task_id) const {
-  return GetTaskGroupByTaskId(task_id)->per_process_network_usage();
+  return GetTaskGroupByTaskId(task_id)->per_process_network_usage_rate();
+}
+
+int64_t TaskManagerImpl::GetCumulativeProcessTotalNetworkUsage(
+    TaskId task_id) const {
+  return GetTaskGroupByTaskId(task_id)->cumulative_per_process_network_usage();
 }
 
 int64_t TaskManagerImpl::GetSqliteMemoryUsed(TaskId task_id) const {
@@ -446,13 +455,13 @@
 }
 
 // static
-void TaskManagerImpl::OnMultipleBytesReadUI(
-    std::vector<BytesReadParam>* params) {
+void TaskManagerImpl::OnMultipleBytesTransferredUI(
+    std::vector<BytesTransferredParam>* params) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(params);
 
-  for (BytesReadParam& param : *params) {
-    if (!GetInstance()->UpdateTasksWithBytesRead(param)) {
+  for (BytesTransferredParam& param : *params) {
+    if (!GetInstance()->UpdateTasksWithBytesTransferred(param)) {
       // We can't match a task to the notification.  That might mean the
       // tab that started a download was closed, or the request may have had
       // no originating task associated with it in the first place.
@@ -461,8 +470,7 @@
 
       param.origin_pid = 0;
       param.child_id = param.route_id = -1;
-
-      GetInstance()->UpdateTasksWithBytesRead(param);
+      GetInstance()->UpdateTasksWithBytesTransferred(param);
     }
   }
 }
@@ -530,13 +538,15 @@
   return nullptr;
 }
 
-bool TaskManagerImpl::UpdateTasksWithBytesRead(const BytesReadParam& param) {
+bool TaskManagerImpl::UpdateTasksWithBytesTransferred(
+    const BytesTransferredParam& param) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   Task* task =
       GetTaskByPidOrRoute(param.origin_pid, param.child_id, param.route_id);
   if (task) {
-    task->OnNetworkBytesRead(param.byte_count);
+    task->OnNetworkBytesRead(param.byte_read_count);
+    task->OnNetworkBytesSent(param.byte_sent_count);
     return true;
   }
 
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.h b/chrome/browser/task_manager/sampling/task_manager_impl.h
index b4834943..5e1ef98 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.h
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.h
@@ -74,7 +74,9 @@
                             base::TerminationStatus* out_status,
                             int* out_error_code) const override;
   int64_t GetNetworkUsage(TaskId task_id) const override;
+  int64_t GetCumulativeNetworkUsage(TaskId task_id) const override;
   int64_t GetProcessTotalNetworkUsage(TaskId task_id) const override;
+  int64_t GetCumulativeProcessTotalNetworkUsage(TaskId task_id) const override;
   int64_t GetSqliteMemoryUsed(TaskId task_id) const override;
   bool GetV8Memory(TaskId task_id,
                    int64_t* allocated,
@@ -94,9 +96,11 @@
   void TaskRemoved(Task* task) override;
   void TaskUnresponsive(Task* task) override;
 
-  // The notification method on the UI thread when multiple bytes are read
-  // from URLRequests. This will be called by the |io_thread_helper_|
-  static void OnMultipleBytesReadUI(std::vector<BytesReadParam>* params);
+  // The notification method on the UI thread when multiple bytes are
+  // transferred from URLRequests. This will be called by the
+  // |io_thread_helper_|
+  static void OnMultipleBytesTransferredUI(
+      std::vector<BytesTransferredParam>* params);
 
  private:
   friend struct base::LazyInstanceTraitsBase<TaskManagerImpl>;
@@ -119,7 +123,7 @@
   // false otherwise, at which point the caller must explicitly match these
   // bytes to the browser process by calling this method again with
   // |param.origin_pid = 0| and |param.child_id = param.route_id = -1|.
-  bool UpdateTasksWithBytesRead(const BytesReadParam& param);
+  bool UpdateTasksWithBytesTransferred(const BytesTransferredParam& param);
 
   TaskGroup* GetTaskGroupByTaskId(TaskId task_id) const;
   Task* GetTaskByTaskId(TaskId task_id) const;
diff --git a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc
index ae01667..63c53974 100644
--- a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc
+++ b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.cc
@@ -59,8 +59,23 @@
                                                int64_t bytes_read) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  if (g_io_thread_helper)
-    g_io_thread_helper->OnNetworkBytesRead(request, bytes_read);
+  if (g_io_thread_helper) {
+    int64_t bytes_sent = 0;
+    g_io_thread_helper->OnNetworkBytesTransferred(request, bytes_read,
+                                                  bytes_sent);
+  }
+}
+
+// static
+void TaskManagerIoThreadHelper::OnRawBytesSent(const net::URLRequest& request,
+                                               int64_t bytes_sent) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  if (g_io_thread_helper) {
+    int64_t bytes_read = 0;
+    g_io_thread_helper->OnNetworkBytesTransferred(request, bytes_read,
+                                                  bytes_sent);
+  }
 }
 
 TaskManagerIoThreadHelper::TaskManagerIoThreadHelper() : weak_factory_(this) {
@@ -71,24 +86,25 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 }
 
-void TaskManagerIoThreadHelper::OnMultipleBytesReadIO() {
+void TaskManagerIoThreadHelper::OnMultipleBytesTransferredIO() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  DCHECK(!bytes_read_buffer_.empty());
+  DCHECK(!bytes_transferred_buffer_.empty());
 
-  std::vector<BytesReadParam>* bytes_read_buffer =
-      new std::vector<BytesReadParam>();
-  bytes_read_buffer_.swap(*bytes_read_buffer);
+  std::vector<BytesTransferredParam>* bytes_read_buffer =
+      new std::vector<BytesTransferredParam>();
+  bytes_transferred_buffer_.swap(*bytes_read_buffer);
 
   content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&TaskManagerImpl::OnMultipleBytesReadUI,
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&TaskManagerImpl::OnMultipleBytesTransferredUI,
                  base::Owned(bytes_read_buffer)));
 }
 
-void TaskManagerIoThreadHelper::OnNetworkBytesRead(
-    const net::URLRequest& request, int64_t bytes_read) {
+void TaskManagerIoThreadHelper::OnNetworkBytesTransferred(
+    const net::URLRequest& request,
+    int64_t bytes_read,
+    int64_t bytes_sent) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   // Only net::URLRequestJob instances created by the ResourceDispatcherHost
@@ -107,7 +123,7 @@
   // plugins - for renderer or browser initiated requests it will be zero.
   int origin_pid = info ? info->GetOriginPID() : 0;
 
-  if (bytes_read_buffer_.empty()) {
+  if (bytes_transferred_buffer_.empty()) {
     // Schedule a task to process the received bytes requests a second from now.
     // We're trying to calculate the tasks' network usage speed as bytes per
     // second so we collect as many requests during one seconds before the below
@@ -115,13 +131,13 @@
     // after one second from now.
     content::BrowserThread::PostDelayedTask(
         content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&TaskManagerIoThreadHelper::OnMultipleBytesReadIO,
+        base::Bind(&TaskManagerIoThreadHelper::OnMultipleBytesTransferredIO,
                    weak_factory_.GetWeakPtr()),
         base::TimeDelta::FromSeconds(1));
   }
 
-  bytes_read_buffer_.push_back(
-      BytesReadParam(origin_pid, child_id, route_id, bytes_read));
+  bytes_transferred_buffer_.push_back(BytesTransferredParam(
+      origin_pid, child_id, route_id, bytes_read, bytes_sent));
 }
 
 }  // namespace task_manager
diff --git a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h
index ff5315b..321025fa 100644
--- a/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h
+++ b/chrome/browser/task_manager/sampling/task_manager_io_thread_helper.h
@@ -19,13 +19,13 @@
 namespace task_manager {
 
 // Defines a wrapper of values that will be sent from IO to UI thread upon
-// reception of bytes read notifications.
-struct BytesReadParam {
+// reception and transmission of bytes notifications.
+struct BytesTransferredParam {
   // The PID of the originating process of the URLRequest, if the request is
   // sent on behalf of another process. Otherwise it's 0.
   int origin_pid;
 
-  // The unique ID of the host of the child process requestor.
+  // The unique ID of the host of the child process requester.
   int child_id;
 
   // The ID of the IPC route for the URLRequest (this identifies the
@@ -34,17 +34,21 @@
   int route_id;
 
   // The number of bytes read.
-  int64_t byte_count;
+  int64_t byte_read_count;
 
-  BytesReadParam(int origin_pid,
-                 int child_id,
-                 int route_id,
-                 int64_t byte_count)
+  // The number of bytes sent.
+  int64_t byte_sent_count;
+
+  BytesTransferredParam(int origin_pid,
+                        int child_id,
+                        int route_id,
+                        int64_t byte_read_count,
+                        int64_t byte_sent_count)
       : origin_pid(origin_pid),
         child_id(child_id),
         route_id(route_id),
-        byte_count(byte_count) {
-  }
+        byte_read_count(byte_read_count),
+        byte_sent_count(byte_sent_count) {}
 };
 
 // Defines a utility class used to schedule the creation and removal of the
@@ -59,7 +63,7 @@
 };
 
 // Defines a class used by the task manager to receive notifications of the
-// network bytes read by the various tasks.
+// network bytes transferred by the various tasks.
 // This object lives entirely only on the IO thread.
 class TaskManagerIoThreadHelper {
  public:
@@ -68,25 +72,33 @@
   static void CreateInstance();
   static void DeleteInstance();
 
-  // This is used to forward the call to update the network bytes from the
-  // TaskManagerInterface if the new task manager is enabled.
+  // This is used to forward the call to update the network bytes with read
+  // bytes from the TaskManagerInterface if the new task manager is enabled.
   static void OnRawBytesRead(const net::URLRequest& request,
                              int64_t bytes_read);
 
+  // This is used to forward the call to update the network bytes with sent
+  // bytes from the TaskManagerInterface if the new task manager is enabled.
+  static void OnRawBytesSent(const net::URLRequest& request,
+                             int64_t bytes_sent);
+
  private:
   TaskManagerIoThreadHelper();
   ~TaskManagerIoThreadHelper();
 
   // We gather multiple notifications on the IO thread in one second before a
-  // call is made to the following function to start the processing.
-  void OnMultipleBytesReadIO();
+  // call is made to the following function to start the processing for
+  // transferred bytes.
+  void OnMultipleBytesTransferredIO();
 
   // This will update the task manager with the network bytes read.
-  void OnNetworkBytesRead(const net::URLRequest& request, int64_t bytes_read);
+  void OnNetworkBytesTransferred(const net::URLRequest& request,
+                                 int64_t bytes_read,
+                                 int64_t bytes_sent);
 
   // This buffer will be filled on IO thread with information about the number
-  // of bytes read from URLRequests.
-  std::vector<BytesReadParam> bytes_read_buffer_;
+  // of bytes transferred from URLRequests.
+  std::vector<BytesTransferredParam> bytes_transferred_buffer_;
 
   base::WeakPtrFactory<TaskManagerIoThreadHelper> weak_factory_;
 
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index 51e133c..9641163 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -672,6 +672,80 @@
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html")));
 }
 
+IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, SentDataObserved) {
+  ShowTaskManager();
+  GURL test_gurl = embedded_test_server()->GetURL("/title1.html");
+
+  ui_test_utils::NavigateToURL(browser(), test_gurl);
+  std::string test_js = R"(
+      document.title = 'network use';
+      var mem = new Uint8Array(16 << 20);
+      for (var i = 0; i < mem.length; i += 16) {
+        mem[i] = i;
+      }
+      var formData = new FormData();
+      formData.append('StringKey1', new Blob([mem]));
+      var request =
+          new Request(location.href, {method: 'POST', body: formData});
+      fetch(request).then(response => response.text());
+      )";
+
+  browser()
+      ->tab_strip_model()
+      ->GetActiveWebContents()
+      ->GetMainFrame()
+      ->ExecuteJavaScriptForTests(base::UTF8ToUTF16(test_js));
+  // TODO(cburn): The assertion below currently assumes that the rate
+  // contribution of the entire 16MB upload arrives in a single refresh cycle.
+  // That's true now because it's only reported when the transaction completes,
+  // but if that changes in the future, this assertion may need to change.
+  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerStatToExceed(
+      MatchTab("network use"), ColumnSpecifier::NETWORK_USE, 16000000));
+}
+
+IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, TotalSentDataObserved) {
+  ShowTaskManager();
+  GURL test_gurl = embedded_test_server()->GetURL("/title1.html");
+
+  ui_test_utils::NavigateToURL(browser(), test_gurl);
+  std::string test_js = R"(
+      document.title = 'network use';
+      var mem = new Uint8Array(16 << 20);
+      for (var i = 0; i < mem.length; i += 16) {
+        mem[i] = i;
+      }
+      var formData = new FormData();
+      formData.append('StringKey1', new Blob([mem]));
+      var request =
+          new Request(location.href, {method: 'POST', body: formData});
+      fetch(request).then(response => response.text());
+      )";
+
+  browser()
+      ->tab_strip_model()
+      ->GetActiveWebContents()
+      ->GetMainFrame()
+      ->ExecuteJavaScriptForTests(base::UTF8ToUTF16(test_js));
+
+  // This test uses |setTimeout| to exceed the Nyquist ratio to ensure that at
+  // least 1 refresh has happened of no traffic.
+  test_js = R"(
+      var request =
+          new Request(location.href, {method: 'POST', body: formData});
+      setTimeout(
+          () => {fetch(request).then(response => response.text())}, 2000);
+      )";
+
+  browser()
+      ->tab_strip_model()
+      ->GetActiveWebContents()
+      ->GetMainFrame()
+      ->ExecuteJavaScriptForTests(base::UTF8ToUTF16(test_js));
+  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerStatToExceed(
+      MatchTab("network use"), ColumnSpecifier::TOTAL_NETWORK_USE,
+      16000000 * 2));
+}
+
 // Checks that task manager counts idle wakeups.
 // Flakily fails on Mac: http://crbug.com/639939
 #if defined(OS_MACOSX)
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.cc b/chrome/browser/task_manager/task_manager_browsertest_util.cc
index 5da52d1..fd5f2761 100644
--- a/chrome/browser/task_manager/task_manager_browsertest_util.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.cc
@@ -116,6 +116,10 @@
         return "Idle wake ups";
       case ColumnSpecifier::MEMORY_STATE:
         return "Memory State";
+      case ColumnSpecifier::NETWORK_USE:
+        return "Network";
+      case ColumnSpecifier::TOTAL_NETWORK_USE:
+        return "Total Network";
     }
     return "N/A";
   }
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.h b/chrome/browser/task_manager/task_manager_browsertest_util.h
index a22f739e..0802e6ef 100644
--- a/chrome/browser/task_manager/task_manager_browsertest_util.h
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.h
@@ -26,6 +26,8 @@
   SQLITE_MEMORY_USED,
   IDLE_WAKEUPS,
   MEMORY_STATE,
+  NETWORK_USE,
+  TOTAL_NETWORK_USE,
 
   COLUMN_NONE,  // Default value.
 };
diff --git a/chrome/browser/task_manager/task_manager_interface.cc b/chrome/browser/task_manager/task_manager_interface.cc
index c4a32857..2b833ec9 100644
--- a/chrome/browser/task_manager/task_manager_interface.cc
+++ b/chrome/browser/task_manager/task_manager_interface.cc
@@ -47,6 +47,13 @@
   TaskManagerIoThreadHelper::OnRawBytesRead(request, bytes_read);
 }
 
+// static
+void TaskManagerInterface::OnRawBytesSent(const net::URLRequest& request,
+                                          int64_t bytes_sent) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  TaskManagerIoThreadHelper::OnRawBytesSent(request, bytes_sent);
+}
+
 void TaskManagerInterface::AddObserver(TaskManagerObserver* observer) {
   observers_.AddObserver(observer);
   observer->observed_task_manager_ = this;
diff --git a/chrome/browser/task_manager/task_manager_interface.h b/chrome/browser/task_manager/task_manager_interface.h
index c4e31c24..fcd9c32a 100644
--- a/chrome/browser/task_manager/task_manager_interface.h
+++ b/chrome/browser/task_manager/task_manager_interface.h
@@ -51,10 +51,15 @@
   static TaskManagerInterface* GetTaskManager();
 
   // This notification will be received on the IO thread from
-  // ChromeNetworkDelegate to update the task manager with network usage.
+  // ChromeNetworkDelegate to update the task manager with read network usage.
   static void OnRawBytesRead(const net::URLRequest& request,
                              int64_t bytes_read);
 
+  // This notification will be received on the IO thread from
+  // ChromeNetworkDelegate to update the task manager with sent network usage.
+  static void OnRawBytesSent(const net::URLRequest& request,
+                             int64_t bytes_sent);
+
   void AddObserver(TaskManagerObserver* observer);
   void RemoveObserver(TaskManagerObserver* observer);
 
@@ -172,11 +177,13 @@
                                     int* out_error_code) const = 0;
 
   // Returns the network usage (in bytes per second) during the current refresh
-  // cycle for the task with |task_id|. A value of -1 means no valid value is
-  // currently available or that task has never been notified of any network
-  // usage.
+  // cycle for the task with |task_id|.
   virtual int64_t GetNetworkUsage(TaskId task_id) const = 0;
 
+  // Returns the network usage during the current lifetime of the task
+  // for the task with |task_id|.
+  virtual int64_t GetCumulativeNetworkUsage(TaskId task_id) const = 0;
+
   // Returns the total network usage (in bytes per second) during the current
   // refresh cycle for the process on which the task with |task_id| is running.
   // This is the sum of all the network usage of the individual tasks (that
@@ -184,6 +191,13 @@
   // usage calculation refresh is currently not available.
   virtual int64_t GetProcessTotalNetworkUsage(TaskId task_id) const = 0;
 
+  // Returns the total network usage during the lifetime of the process
+  // on which the task with |task_id| is running.
+  // This is the sum of all the network usage of the individual tasks (that
+  // can be gotten by the above GetTotalNetworkUsage()).
+  virtual int64_t GetCumulativeProcessTotalNetworkUsage(
+      TaskId task_id) const = 0;
+
   // Returns the Sqlite used memory (in bytes) for the task with |task_id|.
   // A value of -1 means no valid value is currently available.
   virtual int64_t GetSqliteMemoryUsed(TaskId task_id) const = 0;
diff --git a/chrome/browser/task_manager/task_manager_tester.cc b/chrome/browser/task_manager/task_manager_tester.cc
index f93a249..25d852a 100644
--- a/chrome/browser/task_manager/task_manager_tester.cc
+++ b/chrome/browser/task_manager/task_manager_tester.cc
@@ -112,6 +112,10 @@
     case ColumnSpecifier::MEMORY_STATE:
       column_id = IDS_TASK_MANAGER_MEMORY_STATE_COLUMN;
       break;
+    case ColumnSpecifier::TOTAL_NETWORK_USE:
+    case ColumnSpecifier::NETWORK_USE:
+      column_id = IDS_TASK_MANAGER_NET_COLUMN;
+      break;
   }
   model_->ToggleColumnVisibility(column_id);
 }
@@ -140,6 +144,13 @@
       value = task_manager()->GetIdleWakeupsPerSecond(task_id);
       success = true;
       break;
+    case ColumnSpecifier::NETWORK_USE:
+      value = task_manager()->GetNetworkUsage(task_id);
+      success = true;
+    case ColumnSpecifier::TOTAL_NETWORK_USE:
+      value = task_manager()->GetCumulativeNetworkUsage(task_id);
+      success = true;
+      break;
   }
   if (!success)
     return 0;
diff --git a/chrome/browser/task_manager/test_task_manager.cc b/chrome/browser/task_manager/test_task_manager.cc
index 5b90af6..23d93ee 100644
--- a/chrome/browser/task_manager/test_task_manager.cc
+++ b/chrome/browser/task_manager/test_task_manager.cc
@@ -135,13 +135,22 @@
 }
 
 int64_t TestTaskManager::GetNetworkUsage(TaskId task_id) const {
-  return -1;
+  return 0;
 }
 
 int64_t TestTaskManager::GetProcessTotalNetworkUsage(TaskId task_id) const {
   return -1;
 }
 
+int64_t TestTaskManager::GetCumulativeNetworkUsage(TaskId task_id) const {
+  return 0;
+}
+
+int64_t TestTaskManager::GetCumulativeProcessTotalNetworkUsage(
+    TaskId task_id) const {
+  return 0;
+}
+
 int64_t TestTaskManager::GetSqliteMemoryUsed(TaskId task_id) const {
   return -1;
 }
diff --git a/chrome/browser/task_manager/test_task_manager.h b/chrome/browser/task_manager/test_task_manager.h
index 4af6f95..bca4d0a6 100644
--- a/chrome/browser/task_manager/test_task_manager.h
+++ b/chrome/browser/task_manager/test_task_manager.h
@@ -60,6 +60,8 @@
                             int* out_error_code) const override;
   int64_t GetNetworkUsage(TaskId task_id) const override;
   int64_t GetProcessTotalNetworkUsage(TaskId task_id) const override;
+  int64_t GetCumulativeNetworkUsage(TaskId task_id) const override;
+  int64_t GetCumulativeProcessTotalNetworkUsage(TaskId task_id) const override;
   int64_t GetSqliteMemoryUsed(TaskId task_id) const override;
   bool GetV8Memory(TaskId task_id,
                    int64_t* allocated,
diff --git a/chrome/browser/tracing/background_tracing_field_trial.cc b/chrome/browser/tracing/background_tracing_field_trial.cc
index a6f80a5..2d39262 100644
--- a/chrome/browser/tracing/background_tracing_field_trial.cc
+++ b/chrome/browser/tracing/background_tracing_field_trial.cc
@@ -47,7 +47,7 @@
   if (GURL(upload_url).is_valid())
     uploader->SetUploadURL(upload_url);
 
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
   auto connection_type = net::NetworkChangeNotifier::GetConnectionType();
   if (connection_type != net::NetworkChangeNotifier::CONNECTION_WIFI &&
       connection_type != net::NetworkChangeNotifier::CONNECTION_ETHERNET &&
@@ -55,7 +55,7 @@
     // Allow only 100KiB for uploads over data.
     uploader->SetMaxUploadBytes(100 * 1024);
   }
-#endif  // defined(OS_ANDROID) || defined(OS_IOS)
+#endif
 
   uploader->DoUpload(
       file_contents->data(), content::TraceUploader::UNCOMPRESSED_UPLOAD,
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc
index ad257ad..0c978b9 100644
--- a/chrome/browser/translate/chrome_translate_client.cc
+++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -47,6 +47,7 @@
 #include "components/variations/service/variations_service.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
@@ -240,9 +241,13 @@
 
 // static
 void ChromeTranslateClient::BindContentTranslateDriver(
-    content::RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    translate::mojom::ContentTranslateDriverRequest request) {
+    translate::mojom::ContentTranslateDriverRequest request,
+    content::RenderFrameHost* render_frame_host) {
+  // Only valid for the main frame.
+  if (render_frame_host->GetParent())
+    return;
+
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   if (!web_contents)
diff --git a/chrome/browser/translate/chrome_translate_client.h b/chrome/browser/translate/chrome_translate_client.h
index 141350f..f79433a 100644
--- a/chrome/browser/translate/chrome_translate_client.h
+++ b/chrome/browser/translate/chrome_translate_client.h
@@ -72,9 +72,9 @@
                                     std::string* target);
 
   static void BindContentTranslateDriver(
-      content::RenderFrameHost* render_frame_host,
       const service_manager::BindSourceInfo& source_info,
-      translate::mojom::ContentTranslateDriverRequest request);
+      translate::mojom::ContentTranslateDriverRequest request,
+      content::RenderFrameHost* render_frame_host);
 
   // Gets the associated TranslateManager.
   translate::TranslateManager* GetTranslateManager();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 5a790b3..d1b18be 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -307,6 +307,8 @@
     "webui/chromeos/login/user_image_screen_handler.h",
     "webui/chromeos/login/voice_interaction_value_prop_screen_handler.cc",
     "webui/chromeos/login/voice_interaction_value_prop_screen_handler.h",
+    "webui/chromeos/login/wait_for_container_ready_screen_handler.cc",
+    "webui/chromeos/login/wait_for_container_ready_screen_handler.h",
     "webui/chromeos/login/wrong_hwid_screen_handler.cc",
     "webui/chromeos/login/wrong_hwid_screen_handler.h",
     "webui/chromeos/mobile_setup_dialog.cc",
diff --git a/chrome/browser/ui/app_list/test/fake_profile.cc b/chrome/browser/ui/app_list/test/fake_profile.cc
index 81b94ef..11edacb 100644
--- a/chrome/browser/ui/app_list/test/fake_profile.cc
+++ b/chrome/browser/ui/app_list/test/fake_profile.cc
@@ -210,3 +210,9 @@
 Profile::ExitType FakeProfile::GetLastSessionExitType() {
   return EXIT_NORMAL;
 }
+
+scoped_refptr<base::SequencedTaskRunner>
+FakeProfile::GetPrefServiceTaskRunner() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
diff --git a/chrome/browser/ui/app_list/test/fake_profile.h b/chrome/browser/ui/app_list/test/fake_profile.h
index 34a885a..ec3c26f 100644
--- a/chrome/browser/ui/app_list/test/fake_profile.h
+++ b/chrome/browser/ui/app_list/test/fake_profile.h
@@ -94,6 +94,7 @@
   bool WasCreatedByVersionOrLater(const std::string& version) override;
   void SetExitType(ExitType exit_type) override;
   ExitType GetLastSessionExitType() override;
+  scoped_refptr<base::SequencedTaskRunner> GetPrefServiceTaskRunner() override;
 
  private:
   std::string name_;
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index ddeed1a..93c22f4 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -206,10 +206,15 @@
     bool should_cvc_be_requested,
     const base::Closure& callback) {
 #if defined(OS_ANDROID)
-  InfoBarService::FromWebContents(web_contents())
-      ->AddInfoBar(CreateSaveCardInfoBarMobile(
+  std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile>
+      save_card_info_bar_delegate_mobile =
           base::MakeUnique<AutofillSaveCardInfoBarDelegateMobile>(
-              true, card, std::move(legal_message), callback, GetPrefs())));
+              true, card, std::move(legal_message), callback, GetPrefs());
+  if (save_card_info_bar_delegate_mobile->LegalMessagesParsedSuccessfully()) {
+    InfoBarService::FromWebContents(web_contents())
+        ->AddInfoBar(CreateSaveCardInfoBarMobile(
+            std::move(save_card_info_bar_delegate_mobile)));
+  }
 #else
   // Do lazy initialization of SaveCardBubbleControllerImpl.
   autofill::SaveCardBubbleControllerImpl::CreateForWebContents(web_contents());
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index 39ef2fe..978db35 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -23,7 +23,7 @@
 namespace {
 
 uint32_t GetHomeButtonAndHomePageIsNewTabPageFlags() {
-#if defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
   return PrefRegistry::NO_REGISTRATION_FLAGS;
 #else
   return user_prefs::PrefRegistrySyncable::SYNCABLE_PREF;
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
index d7c44a83..be6646d4 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -175,6 +175,10 @@
                                         defer:NO]);
     [popup_ setBackgroundColor:[NSColor clearColor]];
     [popup_ setOpaque:NO];
+    bool narrow_popup =
+        base::FeatureList::IsEnabled(omnibox::kUIExperimentNarrowDropdown);
+    if (narrow_popup)
+      [popup_ setHasShadow:YES];
 
     // Use a flipped view to pin the matrix top the top left. This is needed
     // for animated resize.
@@ -196,14 +200,16 @@
                                                   forDarkTheme:is_dark_theme]);
     [background_view_ addSubview:matrix_];
 
-    top_separator_view_.reset(
-        [[OmniboxPopupTopSeparatorView alloc] initWithFrame:NSZeroRect]);
-    [contentView addSubview:top_separator_view_];
+    if (!narrow_popup) {
+      top_separator_view_.reset(
+          [[OmniboxPopupTopSeparatorView alloc] initWithFrame:NSZeroRect]);
+      [contentView addSubview:top_separator_view_];
 
-    bottom_separator_view_.reset([[OmniboxPopupBottomSeparatorView alloc]
-        initWithFrame:NSZeroRect
-         forDarkTheme:is_dark_theme]);
-    [contentView addSubview:bottom_separator_view_];
+      bottom_separator_view_.reset([[OmniboxPopupBottomSeparatorView alloc]
+          initWithFrame:NSZeroRect
+           forDarkTheme:is_dark_theme]);
+      [contentView addSubview:bottom_separator_view_];
+    }
 
     // TODO(dtseng): Ignore until we provide NSAccessibility support.
     [popup_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole
diff --git a/chrome/browser/ui/page_info/page_info.cc b/chrome/browser/ui/page_info/page_info.cc
index 90204f51..4b93e3b 100644
--- a/chrome/browser/ui/page_info/page_info.cc
+++ b/chrome/browser/ui/page_info/page_info.cc
@@ -440,7 +440,7 @@
 
 void PageInfo::Init(const GURL& url,
                     const security_state::SecurityInfo& security_info) {
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
   // On desktop, internal URLs aren't handled by this class. Instead, a
   // custom and simpler bubble is shown.
   DCHECK(!url.SchemeIs(content::kChromeUIScheme) &&
@@ -449,9 +449,9 @@
          !url.SchemeIs(content_settings::kExtensionScheme));
 #endif
 
-  bool isChromeUINativeScheme = false;
+  bool is_chrome_ui_native_scheme = false;
 #if defined(OS_ANDROID)
-  isChromeUINativeScheme = url.SchemeIs(chrome::kChromeUINativeScheme);
+  is_chrome_ui_native_scheme = url.SchemeIs(chrome::kChromeUINativeScheme);
 #endif
 
   security_level_ = security_info.security_level;
@@ -469,7 +469,7 @@
     return;
   }
 
-  if (url.SchemeIs(content::kChromeUIScheme) || isChromeUINativeScheme) {
+  if (url.SchemeIs(content::kChromeUIScheme) || is_chrome_ui_native_scheme) {
     site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE;
     site_identity_details_ =
         l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE);
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index 1d45c189..685d8e55 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -703,7 +703,7 @@
 
 // On desktop, internal URLs aren't handled by PageInfo class. Instead, a
 // custom and simpler bubble is shown, so no need to test.
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
 TEST_F(PageInfoTest, InternalPage) {
   SetURL("chrome://bookmarks");
   SetDefaultUIExpectations(mock_ui());
diff --git a/chrome/browser/ui/views/desktop_capture/OWNERS b/chrome/browser/ui/views/desktop_capture/OWNERS
new file mode 100644
index 0000000..3d2adf2b
--- /dev/null
+++ b/chrome/browser/ui/views/desktop_capture/OWNERS
@@ -0,0 +1 @@
+qiangchen@chromium.org
\ No newline at end of file
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 b9871f61..fdb9fa0 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
@@ -34,7 +34,6 @@
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/content/payment_request_spec.h"
 #include "components/payments/content/payment_request_state.h"
-#include "components/payments/core/strings_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/insets.h"
@@ -209,8 +208,8 @@
   view->SetLayoutManager(layout);
 
   // "Cards accepted" label is "hint" grey.
-  view->AddChildView(CreateHintLabel(GetAcceptedCardTypesText(
-                                         spec()->supported_card_types_set()))
+  view->AddChildView(CreateHintLabel(l10n_util::GetStringUTF16(
+                                         IDS_PAYMENTS_ACCEPTED_CARDS_LABEL))
                          .release());
 
   // 8dp padding is required between icons.
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
index c1fed0e4..42ff50a 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -61,7 +61,7 @@
   row->SetLayoutManager(layout);
 
   views::ColumnSet* columns = layout->AddColumnSet(0);
-  // The first column has resize_percent = 1 so that it stretches all the way
+  // The first column has resize_percent = 1 so that it streches all the way
   // across the row up to the amount label. This way the first label elides as
   // required.
   columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 1,
@@ -83,10 +83,6 @@
     currency_text = CreateHintLabel(currency);
     amount_text = base::MakeUnique<views::Label>(amount);
   }
-  // Strings from the website may not match the locale of the device, so align
-  // them according to the language of the text. This will result, for example,
-  // in "he" labels being right-aligned in a browser that's using "en" locale.
-  label_text->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
   amount_text->set_id(static_cast<int>(amount_label_id));
   amount_text->SetMultiLine(true);
   amount_text->SetAllowCharacterBreak(true);
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 5766ef2..8ed67f7 100644
--- a/chrome/browser/ui/views/payments/payment_method_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_method_view_controller.cc
@@ -22,14 +22,12 @@
 #include "components/payments/content/payment_request_state.h"
 #include "components/payments/core/autofill_payment_instrument.h"
 #include "components/payments/core/payment_instrument.h"
-#include "components/payments/core/strings_util.h"
 #include "components/strings/grit/components_strings.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/views/border.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/layout/box_layout.h"
@@ -41,8 +39,8 @@
 
 namespace {
 
-constexpr int kFirstTagValue =
-    static_cast<int>(PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX);
+constexpr int kFirstTagValue = static_cast<int>(
+    payments::PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX);
 
 enum class PaymentMethodViewControllerTags : int {
   // The tag for the button that triggers the "add card" flow. Starts at
@@ -52,7 +50,7 @@
   MAX_TAG,
 };
 
-class PaymentMethodListItem : public PaymentRequestItemList::Item {
+class PaymentMethodListItem : public payments::PaymentRequestItemList::Item {
  public:
   // Does not take ownership of |instrument|, which should not be null and
   // should outlive this object. |list| is the PaymentRequestItemList object
@@ -63,11 +61,11 @@
                         PaymentRequestItemList* list,
                         PaymentRequestDialogView* dialog,
                         bool selected)
-      : PaymentRequestItemList::Item(spec,
-                                     state,
-                                     list,
-                                     selected,
-                                     /*show_edit_button=*/true),
+      : payments::PaymentRequestItemList::Item(spec,
+                                               state,
+                                               list,
+                                               selected,
+                                               /*show_edit_button=*/true),
         instrument_(instrument),
         dialog_(dialog) {}
   ~PaymentMethodListItem() override {}
@@ -92,7 +90,7 @@
     NOTREACHED();
   }
 
-  // PaymentRequestItemList::Item:
+  // payments::PaymentRequestItemList::Item:
   std::unique_ptr<views::View> CreateExtraView() override {
     std::unique_ptr<views::ImageView> card_icon_view = CreateInstrumentIconView(
         instrument_->icon_resource_id(), instrument_->GetLabel());
@@ -103,12 +101,14 @@
   std::unique_ptr<views::View> CreateContentView(
       base::string16* accessible_content) override {
     DCHECK(accessible_content);
-    auto card_info_container = base::MakeUnique<views::View>();
+    std::unique_ptr<views::View> card_info_container =
+        base::MakeUnique<views::View>();
     card_info_container->set_can_process_events_within_subtree(false);
 
-    auto box_layout = base::MakeUnique<views::BoxLayout>(
-        views::BoxLayout::kVertical,
-        gfx::Insets(kPaymentRequestRowVerticalInsets, 0));
+    std::unique_ptr<views::BoxLayout> box_layout =
+        base::MakeUnique<views::BoxLayout>(
+            views::BoxLayout::kVertical,
+            gfx::Insets(kPaymentRequestRowVerticalInsets, 0));
     box_layout->set_cross_axis_alignment(
         views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
     card_info_container->SetLayoutManager(box_layout.release());
@@ -122,8 +122,9 @@
     base::string16 missing_info;
     if (!instrument_->IsCompleteForPayment()) {
       missing_info = instrument_->GetMissingInfoLabel();
-      auto missing_info_label = base::MakeUnique<views::Label>(
-          missing_info, CONTEXT_DEPRECATED_SMALL);
+      std::unique_ptr<views::Label> missing_info_label =
+          base::MakeUnique<views::Label>(missing_info,
+                                         CONTEXT_DEPRECATED_SMALL);
       missing_info_label->SetEnabledColor(
           missing_info_label->GetNativeTheme()->GetSystemColor(
               ui::NativeTheme::kColorId_LinkEnabled));
@@ -165,16 +166,6 @@
   DISALLOW_COPY_AND_ASSIGN(PaymentMethodListItem);
 };
 
-std::unique_ptr<views::View> CreateHeaderView(const base::string16& text) {
-  auto label = base::MakeUnique<views::Label>(text);
-  label->SetMultiLine(true);
-  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  label->SetBorder(views::CreateEmptyBorder(
-      kPaymentRequestRowVerticalInsets, kPaymentRequestRowHorizontalInsets, 0,
-      kPaymentRequestRowHorizontalInsets));
-  return label;
-}
-
 }  // namespace
 
 PaymentMethodViewController::PaymentMethodViewController(
@@ -184,10 +175,12 @@
     : PaymentRequestSheetController(spec, state, dialog) {
   const std::vector<std::unique_ptr<PaymentInstrument>>& available_instruments =
       state->available_instruments();
-  for (const auto& instrument : available_instruments) {
-    auto item = base::MakeUnique<PaymentMethodListItem>(
-        instrument.get(), spec, state, &payment_method_list_, dialog,
-        instrument.get() == state->selected_instrument());
+  for (const std::unique_ptr<PaymentInstrument>& instrument :
+       available_instruments) {
+    std::unique_ptr<PaymentMethodListItem> item =
+        base::MakeUnique<PaymentMethodListItem>(
+            instrument.get(), spec, state, &payment_method_list_, dialog,
+            instrument.get() == state->selected_instrument());
     payment_method_list_.AddItem(std::move(item));
   }
 }
@@ -200,17 +193,7 @@
 }
 
 void PaymentMethodViewController::FillContentView(views::View* content_view) {
-  auto layout = base::MakeUnique<views::BoxLayout>(views::BoxLayout::kVertical);
-  layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
-  layout->set_cross_axis_alignment(
-      views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
-  content_view->SetLayoutManager(layout.release());
-
-  base::string16 sub_header =
-      GetCardTypesAreAcceptedText(spec()->supported_card_types_set());
-  if (!sub_header.empty())
-    content_view->AddChildView(CreateHeaderView(sub_header).release());
-
+  content_view->SetLayoutManager(new views::FillLayout);
   std::unique_ptr<views::View> list_view =
       payment_method_list_.CreateListView();
   list_view->set_id(
@@ -220,7 +203,7 @@
 
 std::unique_ptr<views::View>
 PaymentMethodViewController::CreateExtraFooterView() {
-  auto extra_view = base::MakeUnique<views::View>();
+  std::unique_ptr<views::View> extra_view = base::MakeUnique<views::View>();
 
   extra_view->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(),
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
index 98dfb427..4dc2c35 100644
--- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
+++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
@@ -28,7 +28,7 @@
 namespace autofill {
 class AutofillProfile;
 class CreditCard;
-}  // namespace autofill
+}
 
 namespace content {
 class WebContents;
diff --git a/chrome/browser/ui/views/payments/payment_request_debit_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_debit_browsertest.cc
deleted file mode 100644
index eca18710..0000000
--- a/chrome/browser/ui/views/payments/payment_request_debit_browsertest.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h"
-#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
-#include "components/autofill/core/browser/autofill_test_utils.h"
-#include "components/autofill/core/browser/credit_card.h"
-#include "content/public/test/browser_test_utils.h"
-
-namespace payments {
-
-constexpr auto CREDIT = ::autofill::CreditCard::CardType::CARD_TYPE_CREDIT;
-constexpr auto DEBIT = ::autofill::CreditCard::CardType::CARD_TYPE_DEBIT;
-constexpr auto PREPAID = ::autofill::CreditCard::CardType::CARD_TYPE_PREPAID;
-constexpr auto UNKNOWN = ::autofill::CreditCard::CardType::CARD_TYPE_UNKNOWN;
-
-// Tests for a merchant that requests a debit card.
-class PaymentRequestDebitTest : public PaymentRequestBrowserTestBase {
- protected:
-  PaymentRequestDebitTest()
-      : PaymentRequestBrowserTestBase("/payment_request_debit_test.html") {}
-
-  const std::string& GetOrCreateBillingAddressId() {
-    if (billing_address_id_.empty()) {
-      autofill::AutofillProfile billing_address =
-          autofill::test::GetFullProfile();
-      billing_address_id_ = billing_address.guid();
-      AddAutofillProfile(billing_address);
-    }
-    return billing_address_id_;
-  }
-
-  void AddServerCardWithType(autofill::CreditCard::CardType card_type) {
-    autofill::CreditCard card = autofill::test::GetMaskedServerCard();
-    card.set_card_type(card_type);
-    card.set_billing_address_id(GetOrCreateBillingAddressId());
-    AddCreditCard(card);
-  }
-
-  void CallCanMakePayment() {
-    ResetEventObserver(DialogEvent::CAN_MAKE_PAYMENT_CALLED);
-    ASSERT_TRUE(
-        content::ExecuteScript(GetActiveWebContents(), "canMakePayment();"));
-    WaitForObservedEvent();
-  }
-
- private:
-  std::string billing_address_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(PaymentRequestDebitTest);
-};
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest, CanMakePaymentWithDebitCard) {
-  AddServerCardWithType(DEBIT);
-  CallCanMakePayment();
-  ExpectBodyContains({"true"});
-}
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest,
-                       CanMakePaymentWithUnknownCardType) {
-  AddServerCardWithType(UNKNOWN);
-  CallCanMakePayment();
-  ExpectBodyContains({"true"});
-}
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest,
-                       CannotMakePaymentWithCreditAndPrepaidCard) {
-  AddServerCardWithType(CREDIT);
-  AddServerCardWithType(PREPAID);
-  CallCanMakePayment();
-  ExpectBodyContains({"false"});
-}
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest, DebitCardIsPreselected) {
-  AddServerCardWithType(DEBIT);
-  CallCanMakePayment();
-  InvokePaymentRequestUI();
-  EXPECT_TRUE(IsPayButtonEnabled());
-  ClickOnCancel();
-}
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest,
-                       UnknownCardTypeIsNotPreselected) {
-  AddServerCardWithType(UNKNOWN);
-  InvokePaymentRequestUI();
-  EXPECT_FALSE(IsPayButtonEnabled());
-  ClickOnCancel();
-}
-
-IN_PROC_BROWSER_TEST_F(PaymentRequestDebitTest, PayWithLocalCard) {
-  // All local cards have "unknown" card type by design.
-  autofill::CreditCard card = autofill::test::GetCreditCard();
-  card.set_billing_address_id(GetOrCreateBillingAddressId());
-  AddCreditCard(card);
-  InvokePaymentRequestUI();
-
-  // The local card of "unknown" type is not pre-selected.
-  EXPECT_FALSE(IsPayButtonEnabled());
-
-  // Select the local card and click the "Pay" button.
-  OpenPaymentMethodScreen();
-  ResetEventObserver(DialogEvent::BACK_NAVIGATION);
-  ClickOnChildInListViewAndWait(/*child_index=*/0, /*num_children=*/1,
-                                DialogViewID::PAYMENT_METHOD_SHEET_LIST_VIEW);
-  EXPECT_TRUE(IsPayButtonEnabled());
-
-  // Type in the CVC number and verify that it's sent to the page.
-  ResetEventObserver(DialogEvent::DIALOG_CLOSED);
-  PayWithCreditCardAndWait(base::ASCIIToUTF16("012"));
-  ExpectBodyContains({"\"cardSecurityCode\": \"012\""});
-}
-
-}  // namespace payments
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h b/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h
index da64362..a76b928b 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h
@@ -51,7 +51,7 @@
   // The following are Label objects.
   SHIPPING_OPTION_DESCRIPTION,
   SHIPPING_OPTION_AMOUNT,
-  SHIPPING_ADDRESS_SECTION_HEADER_LABEL,
+  SHIPPING_ADDRESS_OPTION_ERROR,
 
   // Used in profile labels to annotate each line of the grouping.
   PROFILE_LABEL_LINE_1,
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 dc8e501..2bfa4797 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -375,11 +375,7 @@
     std::unique_ptr<views::Label> shipping_label =
         emphasize_label ? CreateMediumLabel(text)
                         : base::MakeUnique<views::Label>(text);
-    // Strings from the website may not match the locale of the device, so align
-    // them according to the language of the text. This will result, for
-    // example, in "he" labels being right-aligned in a browser that's using
-    // "en" locale.
-    shipping_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
+    shipping_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     shipping_label->set_id(
         static_cast<int>(DialogViewID::SHIPPING_OPTION_DESCRIPTION));
     container->AddChildView(shipping_label.release());
diff --git a/chrome/browser/ui/views/payments/profile_list_view_controller.cc b/chrome/browser/ui/views/payments/profile_list_view_controller.cc
index a0ae9f3..9be4e98 100644
--- a/chrome/browser/ui/views/payments/profile_list_view_controller.cc
+++ b/chrome/browser/ui/views/payments/profile_list_view_controller.cc
@@ -31,8 +31,8 @@
 
 namespace {
 
-constexpr int kFirstTagValue =
-    static_cast<int>(PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX);
+constexpr int kFirstTagValue = static_cast<int>(
+    payments::PaymentRequestCommonTags::PAYMENT_REQUEST_COMMON_TAG_MAX);
 
 enum class PaymentMethodViewControllerTags : int {
   // The tag for the button that triggers the "add address" flow. Starts at
@@ -56,17 +56,17 @@
               ProfileListViewController* controller,
               PaymentRequestDialogView* dialog,
               bool selected)
-      : PaymentRequestItemList::Item(spec,
-                                     state,
-                                     parent_list,
-                                     selected,
-                                     /*show_edit_button=*/true),
+      : payments::PaymentRequestItemList::Item(spec,
+                                               state,
+                                               parent_list,
+                                               selected,
+                                               /*show_edit_button=*/true),
         controller_(controller),
         profile_(profile) {}
   ~ProfileItem() override {}
 
  private:
-  // PaymentRequestItemList::Item:
+  // payments::PaymentRequestItemList::Item:
   std::unique_ptr<views::View> CreateContentView(
       base::string16* accessible_content) override {
     DCHECK(profile_);
@@ -165,54 +165,39 @@
     return DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW;
   }
 
-  // Creates a warning message when address is not valid or an informational
-  // message when the user has not selected their shipping address yet. The
-  // warning icon is displayed only for warning messages.
-  // ---------------------------------------------
-  // | Warning icon | Warning message            |
-  // ---------------------------------------------
   std::unique_ptr<views::View> CreateHeaderView() override {
-    if (!spec()->details().shipping_options.empty())
+    if (spec()->selected_shipping_option_error().empty())
       return nullptr;
 
-    auto header_view = base::MakeUnique<views::View>();
-    // 8 pixels between the warning icon view (if present) and the text.
+    std::unique_ptr<views::View> header_view = base::MakeUnique<views::View>();
+    // 8 pixels between the warning icon view and the text.
     constexpr int kRowHorizontalSpacing = 8;
-    auto layout = base::MakeUnique<views::BoxLayout>(
+    views::BoxLayout* layout = new views::BoxLayout(
         views::BoxLayout::kHorizontal,
-        gfx::Insets(0, kPaymentRequestRowHorizontalInsets),
+        gfx::Insets(0, payments::kPaymentRequestRowHorizontalInsets),
         kRowHorizontalSpacing);
     layout->set_main_axis_alignment(
         views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
     layout->set_cross_axis_alignment(
         views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
-    header_view->SetLayoutManager(layout.release());
+    header_view->SetLayoutManager(layout);
 
-    auto label = base::MakeUnique<views::Label>(
-        spec()->selected_shipping_option_error().empty()
-            ? GetShippingAddressSelectorInfoMessage(spec()->shipping_type())
-            : spec()->selected_shipping_option_error());
-    // If the warning message comes from the websites, then align label
-    // according to the language of the website's text.
-    label->SetHorizontalAlignment(
-        spec()->selected_shipping_option_error().empty() ? gfx::ALIGN_LEFT
-                                                         : gfx::ALIGN_TO_HEAD);
+    std::unique_ptr<views::ImageView> warning_icon =
+        base::MakeUnique<views::ImageView>();
+    warning_icon->set_can_process_events_within_subtree(false);
+    warning_icon->SetImage(gfx::CreateVectorIcon(
+        ui::kWarningIcon, 16,
+        warning_icon->GetNativeTheme()->GetSystemColor(
+            ui::NativeTheme::kColorId_AlertSeverityHigh)));
+    header_view->AddChildView(warning_icon.release());
+
+    std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>(
+        spec()->selected_shipping_option_error());
     label->set_id(
-        static_cast<int>(DialogViewID::SHIPPING_ADDRESS_SECTION_HEADER_LABEL));
+        static_cast<int>(DialogViewID::SHIPPING_ADDRESS_OPTION_ERROR));
+    label->SetEnabledColor(label->GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_AlertSeverityHigh));
     label->SetMultiLine(true);
-
-    if (!spec()->selected_shipping_option_error().empty()) {
-      auto warning_icon = base::MakeUnique<views::ImageView>();
-      warning_icon->set_can_process_events_within_subtree(false);
-      warning_icon->SetImage(gfx::CreateVectorIcon(
-          ui::kWarningIcon, 16,
-          warning_icon->GetNativeTheme()->GetSystemColor(
-              ui::NativeTheme::kColorId_AlertSeverityHigh)));
-      header_view->AddChildView(warning_icon.release());
-      label->SetEnabledColor(label->GetNativeTheme()->GetSystemColor(
-          ui::NativeTheme::kColorId_AlertSeverityHigh));
-    }
-
     header_view->AddChildView(label.release());
     return header_view;
   }
@@ -384,11 +369,11 @@
 }
 
 void ProfileListViewController::FillContentView(views::View* content_view) {
-  auto layout = base::MakeUnique<views::BoxLayout>(views::BoxLayout::kVertical);
+  views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical);
   layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
   layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
-  content_view->SetLayoutManager(layout.release());
+  content_view->SetLayoutManager(layout);
   std::unique_ptr<views::View> header_view = CreateHeaderView();
   if (header_view)
     content_view->AddChildView(header_view.release());
@@ -399,7 +384,7 @@
 
 std::unique_ptr<views::View>
 ProfileListViewController::CreateExtraFooterView() {
-  auto extra_view = base::MakeUnique<views::View>();
+  std::unique_ptr<views::View> extra_view = base::MakeUnique<views::View>();
 
   extra_view->SetLayoutManager(
       new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(),
diff --git a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
index 83ca2241..28b9b73 100644
--- a/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
+++ b/chrome/browser/ui/views/payments/shipping_option_view_controller_browsertest.cc
@@ -51,9 +51,10 @@
 
   // Go to the shipping address screen and select the first address (MI state).
   OpenShippingAddressSectionScreen();
-  EXPECT_EQ(base::ASCIIToUTF16(
-                "To see shipping methods and requirements, select an address"),
-            GetLabelText(DialogViewID::SHIPPING_ADDRESS_SECTION_HEADER_LABEL));
+  // There is no error at the top of this screen, because no address has been
+  // selected yet.
+  EXPECT_EQ(nullptr, dialog_view()->GetViewByID(static_cast<int>(
+                         DialogViewID::SHIPPING_ADDRESS_OPTION_ERROR)));
 
   ResetEventObserverForSequence(std::list<DialogEvent>{
       DialogEvent::SPEC_DONE_UPDATING, DialogEvent::BACK_NAVIGATION});
@@ -98,7 +99,7 @@
 
   // The address selector has this error.
   EXPECT_EQ(base::ASCIIToUTF16("We do not ship to this address"),
-            GetLabelText(DialogViewID::SHIPPING_ADDRESS_SECTION_HEADER_LABEL));
+            GetLabelText(DialogViewID::SHIPPING_ADDRESS_OPTION_ERROR));
 
   // There is no a longer shipping option section, because no shipping options
   // are available for Canada.
@@ -107,6 +108,7 @@
   EXPECT_EQ(nullptr,
             dialog_view()->GetViewByID(static_cast<int>(
                 DialogViewID::PAYMENT_SHEET_SHIPPING_OPTION_SECTION_BUTTON)));
+
 }
 
 }  // namespace payments
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index f9043f0..7233468 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -60,6 +60,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/voice_interaction_value_prop_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
@@ -337,6 +338,8 @@
 
   AddScreenHandler(base::MakeUnique<VoiceInteractionValuePropScreenHandler>());
 
+  AddScreenHandler(base::MakeUnique<WaitForContainerReadyScreenHandler>());
+
   // Initialize KioskAppMenuHandler. Note that it is NOT a screen handler.
   auto kiosk_app_menu_handler =
       base::MakeUnique<KioskAppMenuHandler>(network_state_informer_);
@@ -463,6 +466,10 @@
   return GetView<VoiceInteractionValuePropScreenHandler>();
 }
 
+WaitForContainerReadyScreenView* OobeUI::GetWaitForContainerReadyScreenView() {
+  return GetView<WaitForContainerReadyScreenHandler>();
+}
+
 UserImageView* OobeUI::GetUserImageView() {
   return GetView<UserImageScreenHandler>();
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 288fefe4..5259255 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -32,7 +32,6 @@
 class AppLaunchSplashScreenView;
 class ArcKioskSplashScreenView;
 class ArcTermsOfServiceScreenView;
-class VoiceInteractionValuePropScreenView;
 class AutoEnrollmentCheckScreenView;
 class BaseScreenHandler;
 class ControllerPairingScreenView;
@@ -63,6 +62,8 @@
 class UserBoardView;
 class UserImageView;
 class UpdateView;
+class VoiceInteractionValuePropScreenView;
+class WaitForContainerReadyScreenView;
 class WrongHWIDScreenView;
 
 // A custom WebUI that defines datasource for out-of-box-experience (OOBE) UI:
@@ -119,6 +120,7 @@
   DeviceDisabledScreenView* GetDeviceDisabledScreenView();
   EncryptionMigrationScreenView* GetEncryptionMigrationScreenView();
   VoiceInteractionValuePropScreenView* GetVoiceInteractionValuePropScreenView();
+  WaitForContainerReadyScreenView* GetWaitForContainerReadyScreenView();
   GaiaView* GetGaiaScreenView();
   UserBoardView* GetUserBoardView();
 
diff --git a/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc
new file mode 100644
index 0000000..ddaf995
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.cc
@@ -0,0 +1,115 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/arc/arc_session_manager.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+#include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/login/localized_values_builder.h"
+
+namespace {
+
+constexpr char kJsScreenPath[] = "login.WaitForContainerReadyScreen";
+constexpr base::TimeDelta kWaitingTimeout = base::TimeDelta::FromMinutes(1);
+
+}  // namespace
+
+namespace chromeos {
+
+WaitForContainerReadyScreenHandler::WaitForContainerReadyScreenHandler()
+    : BaseScreenHandler(kScreenId), weak_ptr_factory_(this) {
+  set_call_js_prefix(kJsScreenPath);
+  arc::ArcSessionManager::Get()->AddObserver(this);
+  is_container_ready_ = arc::ArcSessionManager::Get()->IsSessionRunning();
+}
+
+WaitForContainerReadyScreenHandler::~WaitForContainerReadyScreenHandler() {
+  if (screen_) {
+    screen_->OnViewDestroyed(this);
+  }
+  timer_.Stop();
+  if (arc::ArcSessionManager::Get())
+    arc::ArcSessionManager::Get()->RemoveObserver(this);
+}
+
+void WaitForContainerReadyScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {
+  builder->Add("waitForContainerReadyTitle",
+               IDS_WAIT_FOR_CONTAINER_READY_TITLE);
+  builder->Add("waitForContainerReadyIntroMessage",
+               IDS_WAIT_FOR_CONTAINER_READY_INTRO_MESSAGE);
+}
+
+void WaitForContainerReadyScreenHandler::Bind(
+    WaitForContainerReadyScreen* screen) {
+  BaseScreenHandler::SetBaseScreen(screen);
+  screen_ = screen;
+  if (page_is_ready())
+    Initialize();
+}
+
+void WaitForContainerReadyScreenHandler::Unbind() {
+  screen_ = nullptr;
+  BaseScreenHandler::SetBaseScreen(nullptr);
+  timer_.Stop();
+}
+
+void WaitForContainerReadyScreenHandler::Show() {
+  if (!page_is_ready() || !screen_) {
+    show_on_init_ = true;
+    return;
+  }
+
+  if (is_container_ready_) {
+    NotifyContainerReady();
+    return;
+  }
+
+  timer_.Start(
+      FROM_HERE, kWaitingTimeout,
+      base::Bind(&WaitForContainerReadyScreenHandler::OnMaxContainerWaitTimeout,
+                 weak_ptr_factory_.GetWeakPtr()));
+
+  ShowScreen(kScreenId);
+}
+
+void WaitForContainerReadyScreenHandler::Hide() {}
+
+void WaitForContainerReadyScreenHandler::OnArcInitialStart() {
+  is_container_ready_ = true;
+  if (!screen_)
+    return;
+
+  // TODO(updowndota): Remove the temporary delay after the potential racing
+  // issue is eliminated.
+  timer_.Stop();
+  timer_.Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(5),
+      base::Bind(&WaitForContainerReadyScreenHandler::NotifyContainerReady,
+                 weak_ptr_factory_.GetWeakPtr()));
+}
+
+void WaitForContainerReadyScreenHandler::Initialize() {
+  if (!screen_ || !show_on_init_)
+    return;
+
+  Show();
+  show_on_init_ = false;
+}
+
+void WaitForContainerReadyScreenHandler::OnMaxContainerWaitTimeout() {
+  // TODO(updowndota): Add histogram to Voice Interaction OptIn flow.
+  if (screen_)
+    screen_->OnContainerReady();
+}
+
+void WaitForContainerReadyScreenHandler::NotifyContainerReady() {
+  if (screen_)
+    screen_->OnContainerReady();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.h
new file mode 100644
index 0000000..0af862c
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/wait_for_container_ready_screen_handler.h
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WAIT_FOR_CONTAINER_READY_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WAIT_FOR_CONTAINER_READY_SCREEN_HANDLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/arc/arc_session_manager.h"
+#include "chrome/browser/chromeos/login/screens/wait_for_container_ready_screen_view.h"
+#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
+
+namespace chromeos {
+
+class WaitForContainerReadyScreenHandler
+    : public BaseScreenHandler,
+      public WaitForContainerReadyScreenView,
+      public arc::ArcSessionManager::Observer {
+ public:
+  WaitForContainerReadyScreenHandler();
+  ~WaitForContainerReadyScreenHandler() override;
+
+  // BaseScreenHandler:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+
+  // WaitForContainerReadyScreenView:
+  void Bind(WaitForContainerReadyScreen* screen) override;
+  void Unbind() override;
+  void Show() override;
+  void Hide() override;
+
+  // arc::ArcSessionManager::Observer overrides.
+  void OnArcInitialStart() override;
+
+ private:
+  // BaseScreenHandler:
+  void Initialize() override;
+
+  // Called to notify the screen that the container is ready.
+  void NotifyContainerReady();
+
+  // Called when the max wait timeout is reached.
+  void OnMaxContainerWaitTimeout();
+
+  WaitForContainerReadyScreen* screen_ = nullptr;
+
+  // Whether the screen should be shown right after initialization.
+  bool show_on_init_ = false;
+
+  // Whether container is ready.
+  bool is_container_ready_ = false;
+
+  // Timer used to exit the page when timeout reaches.
+  base::OneShotTimer timer_;
+
+  base::WeakPtrFactory<WaitForContainerReadyScreenHandler> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaitForContainerReadyScreenHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WAIT_FOR_CONTAINER_READY_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index 03ba8fae..c37e0a9 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -68,7 +68,7 @@
 
 void GetUiDevToolsTargets(base::ListValue& targets) {
   for (const auto& client_pair :
-       ui::devtools::UiDevToolsServer::GetClientNamesAndUrls()) {
+       ui_devtools::UiDevToolsServer::GetClientNamesAndUrls()) {
     auto target_data = base::MakeUnique<base::DictionaryValue>();
     target_data->SetString(kNameField, client_pair.first);
     target_data->SetString(kUrlField, client_pair.second);
diff --git a/chrome/browser/ui/webui/net_export_ui.cc b/chrome/browser/ui/webui/net_export_ui.cc
index 84922b4..3f5b6f89 100644
--- a/chrome/browser/ui/webui/net_export_ui.cc
+++ b/chrome/browser/ui/webui/net_export_ui.cc
@@ -328,7 +328,7 @@
 
 // static
 bool NetExportMessageHandler::UsingMobileUI() {
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
   return true;
 #else
   return false;
diff --git a/chrome/browser/web_applications/web_app_unittest.cc b/chrome/browser/web_applications/web_app_unittest.cc
index 7043861..fb5a1cb 100644
--- a/chrome/browser/web_applications/web_app_unittest.cc
+++ b/chrome/browser/web_applications/web_app_unittest.cc
@@ -46,8 +46,9 @@
 
   content::RenderFrameHostTester::For(main_rfh())
       ->InitializeRenderFrameIfNeeded();
-  RenderViewHostTester::TestOnMessageReceived(
-      rvh(), ChromeViewHostMsg_DidGetWebApplicationInfo(0, web_app_info));
+  content::RenderFrameHostTester::TestOnMessageReceived(
+      rvh()->GetMainFrame(),
+      ChromeFrameHostMsg_DidGetWebApplicationInfo(0, web_app_info));
   std::unique_ptr<web_app::ShortcutInfo> info =
       web_app::GetShortcutInfoForTab(web_contents());
 
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index d07f061..838017d 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -203,7 +203,7 @@
 #endif
 };
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 // Enables media content bitstream remoting, an optimization that can activate
 // during Cast Tab Mirroring.
 const base::Feature kMediaRemoting{"MediaRemoting",
@@ -214,7 +214,7 @@
 // resources.
 const base::Feature kMediaRouterUIRouteController{
     "MediaRouterUIRouteController", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif  // !defined(OS_ANDROID)
 
 // Enables or disables modal permission prompts.
 const base::Feature kModalPermissionPrompts{"ModalPermissionPrompts",
@@ -243,7 +243,7 @@
 const base::Feature kOfflinePageDownloadSuggestionsFeature{
     "NTPOfflinePageDownloadSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 // Enables or disabled the OneGoogleBar on the local NTP.
 const base::Feature kOneGoogleBarOnLocalNtp{"OneGoogleBarOnLocalNtp",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 1ba9a8b..9d19efaa 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -109,10 +109,10 @@
 
 extern const base::Feature kMaterialDesignIncognitoNTP;
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 extern const base::Feature kMediaRemoting;
 extern const base::Feature kMediaRouterUIRouteController;
-#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif
 
 extern const base::Feature kModalPermissionPrompts;
 
@@ -126,7 +126,7 @@
 
 extern const base::Feature kOfflinePageDownloadSuggestionsFeature;
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 extern const base::Feature kOneGoogleBarOnLocalNtp;
 #endif
 
diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm
index d0bbbf7..cca3bbb 100644
--- a/chrome/common/chrome_paths_mac.mm
+++ b/chrome/common/chrome_paths_mac.mm
@@ -20,7 +20,6 @@
 
 namespace {
 
-#if !defined(OS_IOS)
 const base::FilePath* g_override_versioned_directory = NULL;
 
 // Return a retained (NOT autoreleased) NSBundle* as the internal
@@ -47,19 +46,14 @@
 
   return [[NSBundle bundleWithPath:outer_app_dir_ns] retain];
 }
-#endif  // !defined(OS_IOS)
 
 char* ProductDirNameForBundle(NSBundle* chrome_bundle) {
   const char* product_dir_name = NULL;
-#if !defined(OS_IOS)
   base::mac::ScopedNSAutoreleasePool pool;
 
   NSString* product_dir_name_ns =
       [chrome_bundle objectForInfoDictionaryKey:@"CrProductDirName"];
   product_dir_name = [product_dir_name_ns fileSystemRepresentation];
-#else
-  DCHECK(!chrome_bundle);
-#endif
 
   if (!product_dir_name) {
 #if defined(GOOGLE_CHROME_BUILD)
@@ -82,9 +76,6 @@
 // official canary channel, the Info.plist will have CrProductDirName set
 // to "Google/Chrome Canary".
 std::string ProductDirName() {
-#if defined(OS_IOS)
-  static const char* product_dir_name = ProductDirNameForBundle(nil);
-#else
   // Use OuterAppBundle() to get the main app's bundle. This key needs to live
   // in the main app's bundle because it will be set differently on the canary
   // channel, and the autoupdate system dictates that there can be no
@@ -96,7 +87,6 @@
   // browser .app's Info.plist for the CrProductDirName key.
   static const char* product_dir_name =
       ProductDirNameForBundle(chrome::OuterAppBundle());
-#endif
   return std::string(product_dir_name);
 }
 
@@ -161,8 +151,6 @@
   return base::mac::GetUserDirectory(NSMoviesDirectory, result);
 }
 
-#if !defined(OS_IOS)
-
 base::FilePath GetVersionedDirectory() {
   if (g_override_versioned_directory)
     return *g_override_versioned_directory;
@@ -234,8 +222,6 @@
   return GetDefaultUserDataDirectoryForProduct(product_dir_name.get(), result);
 }
 
-#endif  // !defined(OS_IOS)
-
 bool ProcessNeedsProfileDir(const std::string& process_type) {
   // For now we have no reason to forbid this on other MacOS as we don't
   // have the roaming profile troubles there.
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json b/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json
index 2865edd..6a59859 100644
--- a/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json
+++ b/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json
@@ -1,8 +1,9 @@
 {
+  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjd3VZe2un2t/ju5HGcZrbD862LLhtukwtXeySPzbQaq9zEyFzr+pVd1EeAW7ZPUA86K9/mpWiDycoSMMj9hpm+QQqBnQDrPPtBJfogkFvWsgDQaw6SXZmErTlzz1wukn/0YLQrPLJ7JPj3zGzWcoVj9AhOjQeDpq2E9P3lz85mHwG0RrxgpknP1wGNNkXl/y4WDaWHZyoX1zgcn2r3bzTdb77RWiA9pduXSn6d14GA9B9CdQA4bTDmc9HY1WaVGK0oDX2A2eJEllHqdeBJmpqPqds4cIhm0Gq6lKvxB61I2UZlbCaSIMfTTxBnt+r7NPgpxHBKJIF1xOCpuGtWuc0wIDAQAB",
   "name": "Desktop Capture Example",
   "description": "Show desktop media picker UI",
   "version": "1",
-  "manifest_version": 2,
+  "manifest_version": 3,
   "icons": {
     "16": "icon.png",
     "128": "icon.png"
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index deff17e..ee36981 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1012,7 +1012,7 @@
 // permitted.
 const char kAllowDeletingBrowserHistory[] = "history.deleting_enabled";
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 // Whether the "Click here to clear your browsing data" tooltip promo has been
 // shown on the Material Design History page.
 const char kMdHistoryMenuPromoShown[] = "history.menu_promo_shown";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index adfd9ff..985b3aa 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -336,7 +336,7 @@
 extern const char kSpeechRecognitionFilterProfanities[];
 extern const char kSavingBrowserHistoryDisabled[];
 extern const char kAllowDeletingBrowserHistory[];
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
 extern const char kMdHistoryMenuPromoShown[];
 #endif
 extern const char kForceGoogleSafeSearch[];
diff --git a/chrome/common/profiling/BUILD.gn b/chrome/common/profiling/BUILD.gn
index ff59ef5..16464eea 100644
--- a/chrome/common/profiling/BUILD.gn
+++ b/chrome/common/profiling/BUILD.gn
@@ -7,6 +7,10 @@
 if (enable_oop_heap_profiling) {
   static_library("profiling") {
     sources = [
+      "memlog_allocator_shim.cc",
+      "memlog_allocator_shim.h",
+      "memlog_sender.cc",
+      "memlog_sender.h",
       "memlog_sender_pipe.h",
       "memlog_sender_pipe_win.cc",
       "memlog_sender_pipe_win.h",
diff --git a/chrome/common/profiling/memlog_allocator_shim.cc b/chrome/common/profiling/memlog_allocator_shim.cc
new file mode 100644
index 0000000..9ff84cf
--- /dev/null
+++ b/chrome/common/profiling/memlog_allocator_shim.cc
@@ -0,0 +1,236 @@
+// 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/common/profiling/memlog_allocator_shim.h"
+
+#include "base/allocator/allocator_shim.h"
+#include "base/debug/debugging_flags.h"
+#include "base/debug/stack_trace.h"
+#include "base/synchronization/lock.h"
+#include "base/trace_event/heap_profiler_allocation_register.h"
+#include "chrome/common/profiling/memlog_stream.h"
+
+namespace profiling {
+
+namespace {
+
+using base::allocator::AllocatorDispatch;
+
+MemlogSenderPipe* g_sender_pipe = nullptr;
+
+// This maximum number of stack entries to log. Long-term we will likely want
+// to raise this to avoid truncation. This matches the current value in the
+// in-process heap profiler (heap_profiler_allocation_context.h) so the two
+// systems performance and memory overhead can be compared consistently.
+const int kMaxStackEntries = 48;
+
+// Matches the native buffer size on the pipe.
+const int kSendBufferSize = 65536;
+
+// Prime since this is used like a hash table. Numbers of this magnitude seemed
+// to provide sufficient parallelism to avoid lock overhead in ad-hoc testing.
+const int kNumSendBuffers = 17;
+
+class SendBuffer {
+ public:
+  SendBuffer() : buffer_(new char[kSendBufferSize]) {}
+  ~SendBuffer() { delete[] buffer_; }
+
+  void Send(const void* data, size_t sz) {
+    base::AutoLock lock(lock_);
+
+    if (used_ + sz > kSendBufferSize)
+      SendCurrentBuffer();
+
+    memcpy(&buffer_[used_], data, sz);
+    used_ += sz;
+  }
+
+ private:
+  void SendCurrentBuffer() {
+    g_sender_pipe->Send(buffer_, used_);
+    used_ = 0;
+  }
+
+  base::Lock lock_;
+
+  char* buffer_;
+  size_t used_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(SendBuffer);
+};
+
+SendBuffer* g_send_buffers = nullptr;
+
+// "address" is the address in question, which is used to select which send
+// buffer to use.
+void DoSend(const void* address, const void* data, size_t size) {
+  base::trace_event::AllocationRegister::AddressHasher hasher;
+  int bin_to_use = hasher(address) % kNumSendBuffers;
+  g_send_buffers[bin_to_use].Send(data, size);
+}
+
+void* HookAlloc(const AllocatorDispatch* self, size_t size, void* context) {
+  const AllocatorDispatch* const next = self->next;
+  void* ptr = next->alloc_function(next, size, context);
+  AllocatorShimLogAlloc(ptr, size);
+  return ptr;
+}
+
+void* HookZeroInitAlloc(const AllocatorDispatch* self,
+                        size_t n,
+                        size_t size,
+                        void* context) {
+  const AllocatorDispatch* const next = self->next;
+  void* ptr = next->alloc_zero_initialized_function(next, n, size, context);
+  AllocatorShimLogAlloc(ptr, n * size);
+  return ptr;
+}
+
+void* HookAllocAligned(const AllocatorDispatch* self,
+                       size_t alignment,
+                       size_t size,
+                       void* context) {
+  const AllocatorDispatch* const next = self->next;
+  void* ptr = next->alloc_aligned_function(next, alignment, size, context);
+  AllocatorShimLogAlloc(ptr, size);
+  return ptr;
+}
+
+void* HookRealloc(const AllocatorDispatch* self,
+                  void* address,
+                  size_t size,
+                  void* context) {
+  const AllocatorDispatch* const next = self->next;
+  void* ptr = next->realloc_function(next, address, size, context);
+  AllocatorShimLogFree(address);
+  if (size > 0)  // realloc(size == 0) means free()
+    AllocatorShimLogAlloc(ptr, size);
+  return ptr;
+}
+
+void HookFree(const AllocatorDispatch* self, void* address, void* context) {
+  AllocatorShimLogFree(address);
+  const AllocatorDispatch* const next = self->next;
+  next->free_function(next, address, context);
+}
+
+size_t HookGetSizeEstimate(const AllocatorDispatch* self,
+                           void* address,
+                           void* context) {
+  const AllocatorDispatch* const next = self->next;
+  return next->get_size_estimate_function(next, address, context);
+}
+
+unsigned HookBatchMalloc(const AllocatorDispatch* self,
+                         size_t size,
+                         void** results,
+                         unsigned num_requested,
+                         void* context) {
+  const AllocatorDispatch* const next = self->next;
+  unsigned count =
+      next->batch_malloc_function(next, size, results, num_requested, context);
+  for (unsigned i = 0; i < count; ++i)
+    AllocatorShimLogAlloc(results[i], size);
+  return count;
+}
+
+void HookBatchFree(const AllocatorDispatch* self,
+                   void** to_be_freed,
+                   unsigned num_to_be_freed,
+                   void* context) {
+  const AllocatorDispatch* const next = self->next;
+  for (unsigned i = 0; i < num_to_be_freed; ++i)
+    AllocatorShimLogFree(to_be_freed[i]);
+  next->batch_free_function(next, to_be_freed, num_to_be_freed, context);
+}
+
+void HookFreeDefiniteSize(const AllocatorDispatch* self,
+                          void* ptr,
+                          size_t size,
+                          void* context) {
+  AllocatorShimLogFree(ptr);
+  const AllocatorDispatch* const next = self->next;
+  next->free_definite_size_function(next, ptr, size, context);
+}
+
+AllocatorDispatch g_memlog_hooks = {
+    &HookAlloc,             // alloc_function
+    &HookZeroInitAlloc,     // alloc_zero_initialized_function
+    &HookAllocAligned,      // alloc_aligned_function
+    &HookRealloc,           // realloc_function
+    &HookFree,              // free_function
+    &HookGetSizeEstimate,   // get_size_estimate_function
+    &HookBatchMalloc,       // batch_malloc_function
+    &HookBatchFree,         // batch_free_function
+    &HookFreeDefiniteSize,  // free_definite_size_function
+    nullptr,                // next
+};
+
+}  // namespace
+
+void InitAllocatorShim(MemlogSenderPipe* sender_pipe) {
+  g_send_buffers = new SendBuffer[kNumSendBuffers];
+
+  g_sender_pipe = sender_pipe;
+#ifdef NDEBUG
+  base::allocator::InsertAllocatorDispatch(&g_memlog_hooks);
+#endif
+}
+
+void AllocatorShimLogAlloc(void* address, size_t sz) {
+  if (!g_send_buffers)
+    return;
+  if (address) {
+    constexpr size_t max_message_size =
+        sizeof(AllocPacket) + kMaxStackEntries * sizeof(uint64_t);
+    char message[max_message_size];
+    // TODO(ajwong) check that this is technically valid.
+    AllocPacket* alloc_packet = reinterpret_cast<AllocPacket*>(message);
+
+    uint64_t* stack =
+        reinterpret_cast<uint64_t*>(&message[sizeof(AllocPacket)]);
+
+#if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
+    const void* frames[kMaxStackEntries];
+    size_t frame_count = base::debug::TraceStackFramePointers(
+        frames, kMaxStackEntries,
+        1);  // exclude this function from the trace.
+#else   // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
+    // Fall-back to capturing the stack with base::debug::StackTrace,
+    // which is likely slower, but more reliable.
+    base::debug::StackTrace stack_trace(kMaxStackEntries);
+    size_t frame_count = 0u;
+    const void* const* frames = stack_trace.Addresses(&frame_count);
+#endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
+
+    // If there are too many frames, keep the ones furthest from main().
+    for (size_t i = 0; i < frame_count; i++)
+      stack[i] = (uint64_t)frames[i];
+
+    alloc_packet->op = kAllocPacketType;
+    alloc_packet->time = 0;  // TODO(brettw) add timestamp.
+    alloc_packet->address = (uint64_t)address;
+    alloc_packet->size = sz;
+    alloc_packet->stack_len = static_cast<uint32_t>(frame_count);
+
+    DoSend(address, message,
+           sizeof(AllocPacket) + alloc_packet->stack_len * sizeof(uint64_t));
+  }
+}
+
+void AllocatorShimLogFree(void* address) {
+  if (!g_send_buffers)
+    return;
+  if (address) {
+    FreePacket free_packet;
+    free_packet.op = kFreePacketType;
+    free_packet.time = 0;  // TODO(brettw) add timestamp.
+    free_packet.address = (uint64_t)address;
+
+    DoSend(address, &free_packet, sizeof(FreePacket));
+  }
+}
+
+}  // namespace profiling
diff --git a/chrome/common/profiling/memlog_allocator_shim.h b/chrome/common/profiling/memlog_allocator_shim.h
new file mode 100644
index 0000000..17da0e6
--- /dev/null
+++ b/chrome/common/profiling/memlog_allocator_shim.h
@@ -0,0 +1,25 @@
+// 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_COMMON_PROFILING_MEMLOG_ALLOCATOR_SHIM_H_
+#define CHROME_COMMON_PROFILING_MEMLOG_ALLOCATOR_SHIM_H_
+
+#include "chrome/common/profiling/memlog_sender_pipe.h"
+
+// This is a temporary allocator shim for testing out-of-process heap
+// profiling.
+//
+// TODO(brettw) replace this with the base allocator shim, plus a way to get
+// the events at the Chrome layer.
+
+namespace profiling {
+
+void InitAllocatorShim(MemlogSenderPipe* sender_pipe);
+
+void AllocatorShimLogAlloc(void* address, size_t sz);
+void AllocatorShimLogFree(void* address);
+
+}  // namespace profiling
+
+#endif  // CHROME_COMMON_PROFILING_MEMLOG_ALLOCATOR_SHIM_H_
diff --git a/chrome/common/profiling/memlog_sender.cc b/chrome/common/profiling/memlog_sender.cc
new file mode 100644
index 0000000..4b3160b
--- /dev/null
+++ b/chrome/common/profiling/memlog_sender.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/profiling/memlog_sender.h"
+
+#include "base/command_line.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/profiling/memlog_allocator_shim.h"
+#include "chrome/common/profiling/memlog_sender_pipe.h"
+#include "chrome/common/profiling/memlog_stream.h"
+
+namespace profiling {
+
+void InitMemlogSenderIfNecessary(const base::CommandLine& cmdline) {
+  base::CommandLine::StringType pipe_id =
+      cmdline.GetSwitchValueNative(switches::kMemlogPipe);
+  if (pipe_id.empty())
+    return;  // No pipe, don't run.
+
+  static MemlogSenderPipe pipe(pipe_id);
+  pipe.Connect();
+
+  StreamHeader header;
+  header.signature = kStreamSignature;
+
+  pipe.Send(&header, sizeof(StreamHeader));
+
+  InitAllocatorShim(&pipe);
+}
+
+}  // namespace profiling
diff --git a/chrome/common/profiling/memlog_sender.h b/chrome/common/profiling/memlog_sender.h
new file mode 100644
index 0000000..cda630f
--- /dev/null
+++ b/chrome/common/profiling/memlog_sender.h
@@ -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.
+
+#ifndef CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_
+#define CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_
+
+namespace base {
+
+class CommandLine;
+
+}  // namespace base
+
+namespace profiling {
+
+void InitMemlogSenderIfNecessary(const base::CommandLine& cmdline);
+
+}  // namespace profiling
+
+#endif  // CHROME_COMMON_PROFILING_MEMLOG_SENDER_H_
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 12d7c45..625a4b3 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -146,9 +146,9 @@
 IPC_MESSAGE_ROUTED1(ChromeViewMsg_SetWindowFeatures,
                     blink::mojom::WindowFeatures /* window_features */)
 
-// Requests application info for the page. The renderer responds back with
-// ChromeViewHostMsg_DidGetWebApplicationInfo.
-IPC_MESSAGE_ROUTED0(ChromeViewMsg_GetWebApplicationInfo)
+// Requests application info for the frame. The renderer responds back with
+// ChromeFrameHostMsg_DidGetWebApplicationInfo.
+IPC_MESSAGE_ROUTED0(ChromeFrameMsg_GetWebApplicationInfo)
 
 // chrome.principals messages ------------------------------------------------
 
@@ -327,7 +327,7 @@
 // a secure page by a security policy.  The page may appear incomplete.
 IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_DidBlockDisplayingInsecureContent)
 
-IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_DidGetWebApplicationInfo,
+IPC_MESSAGE_ROUTED1(ChromeFrameHostMsg_DidGetWebApplicationInfo,
                     WebApplicationInfo)
 
 // Tells the renderer a list of URLs which should be bounced back to the browser
diff --git a/chrome/gpu/gpu_arc_video_decode_accelerator.h b/chrome/gpu/gpu_arc_video_decode_accelerator.h
index ddac163b..2b44d7e 100644
--- a/chrome/gpu/gpu_arc_video_decode_accelerator.h
+++ b/chrome/gpu/gpu_arc_video_decode_accelerator.h
@@ -10,6 +10,7 @@
 
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/gpu/arc_video_decode_accelerator.h"
 #include "components/arc/common/video_decode_accelerator.mojom.h"
 #include "components/arc/video_accelerator/video_accelerator.h"
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn
new file mode 100644
index 0000000..f3ef26bc
--- /dev/null
+++ b/chrome/installer/zucchini/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/process_version_rc_template.gni")
+import("//testing/test.gni")
+
+executable("zucchini") {
+  sources = [
+    "zucchini_main.cc",
+  ]
+
+  deps = []
+
+  if (is_win) {
+    deps += [ ":zucchini_exe_version" ]
+  }
+}
+
+if (is_win) {
+  process_version_rc_template("zucchini_exe_version") {
+    template_file = "zucchini_exe_version.rc.version"
+    output = "$target_gen_dir/zucchini_exe_version.rc"
+  }
+}
+
+test("zucchini_unittests") {
+  sources = []
+
+  deps = [
+    "//base/test:run_all_unittests",
+  ]
+}
diff --git a/chrome/installer/zucchini/OWNERS b/chrome/installer/zucchini/OWNERS
new file mode 100644
index 0000000..8a3e7793
--- /dev/null
+++ b/chrome/installer/zucchini/OWNERS
@@ -0,0 +1,5 @@
+huangs@chromium.org
+etiennep@chromium.org
+wfh@chromium.org
+
+# COMPONENT: Internals>Installer>Diff
diff --git a/chrome/installer/zucchini/zucchini_exe_version.rc.version b/chrome/installer/zucchini/zucchini_exe_version.rc.version
new file mode 100644
index 0000000..9d46a4b
--- /dev/null
+++ b/chrome/installer/zucchini/zucchini_exe_version.rc.version
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <verrsrc.h>
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@
+ PRODUCTVERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName", "@COMPANY_FULLNAME@"
+            VALUE "FileDescription", "Zucchini"
+            VALUE "FileVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
+            VALUE "InternalName", "zucchini"
+            VALUE "LegalCopyright", "@COPYRIGHT@"
+            VALUE "ProductName", "Zucchini"
+            VALUE "ProductVersion", "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
+            VALUE "CompanyShortName", "@COMPANY_SHORTNAME@"
+            VALUE "ProductShortName", "Zucchini"
+            VALUE "LastChange", "@LASTCHANGE@"
+            VALUE "Official Build", "@OFFICIAL_BUILD@"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/chrome/installer/zucchini/zucchini_main.cc b/chrome/installer/zucchini/zucchini_main.cc
new file mode 100644
index 0000000..3663e67
--- /dev/null
+++ b/chrome/installer/zucchini/zucchini_main.cc
@@ -0,0 +1,7 @@
+// 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.
+
+int main(int argc, const char* argv[]) {
+  return 0;
+}
diff --git a/chrome/profiling/profiling_main.cc b/chrome/profiling/profiling_main.cc
index ccc022b..c9c46679 100644
--- a/chrome/profiling/profiling_main.cc
+++ b/chrome/profiling/profiling_main.cc
@@ -97,6 +97,8 @@
   base::Process process = base::Process::Current();
   std::string pipe_id = base::IntToString(static_cast<int>(process.Pid()));
 
+  globals->GetMemlogConnectionManager()->StartConnections(pipe_id);
+
   if (!LaunchBrowser(cmdline, pipe_id))
     return 1;
 
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index 08ca11e..7b13a72 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
@@ -24,6 +25,7 @@
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h"
+#include "chrome/renderer/web_apps.h"
 #include "components/translate/content/renderer/translate_helper.h"
 #include "content/public/common/associated_interface_provider.h"
 #include "content/public/renderer/render_frame.h"
@@ -149,6 +151,8 @@
     return false;
 
   IPC_BEGIN_MESSAGE_MAP(ChromeRenderFrameObserver, message)
+    IPC_MESSAGE_HANDLER(ChromeFrameMsg_GetWebApplicationInfo,
+                        OnGetWebApplicationInfo)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetClientSidePhishingDetection,
                         OnSetClientSidePhishingDetection)
 #if BUILDFLAG(ENABLE_PRINTING)
@@ -231,6 +235,47 @@
 #endif
 }
 
+void ChromeRenderFrameObserver::OnGetWebApplicationInfo() {
+  WebLocalFrame* frame = render_frame()->GetWebFrame();
+
+  WebApplicationInfo web_app_info;
+  web_apps::ParseWebAppFromWebDocument(frame, &web_app_info);
+
+  // The warning below is specific to mobile but it doesn't hurt to show it even
+  // if the Chromium build is running on a desktop. It will get more exposition.
+  if (web_app_info.mobile_capable == WebApplicationInfo::MOBILE_CAPABLE_APPLE) {
+    blink::WebConsoleMessage message(
+        blink::WebConsoleMessage::kLevelWarning,
+        "<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"> is "
+        "deprecated. Please include <meta name=\"mobile-web-app-capable\" "
+        "content=\"yes\"> - "
+        "http://developers.google.com/chrome/mobile/docs/installtohomescreen");
+    frame->AddMessageToConsole(message);
+  }
+
+  // Prune out any data URLs in the set of icons.  The browser process expects
+  // any icon with a data URL to have originated from a favicon.  We don't want
+  // to decode arbitrary data URLs in the browser process.  See
+  // http://b/issue?id=1162972
+  for (std::vector<WebApplicationInfo::IconInfo>::iterator it =
+           web_app_info.icons.begin();
+       it != web_app_info.icons.end();) {
+    if (it->url.SchemeIs(url::kDataScheme))
+      it = web_app_info.icons.erase(it);
+    else
+      ++it;
+  }
+
+  // Truncate the strings we send to the browser process.
+  web_app_info.title =
+      web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength);
+  web_app_info.description =
+      web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength);
+
+  Send(new ChromeFrameHostMsg_DidGetWebApplicationInfo(routing_id(),
+                                                       web_app_info));
+}
+
 void ChromeRenderFrameObserver::OnSetClientSidePhishingDetection(
     bool enable_phishing_detection) {
 #if defined(SAFE_BROWSING_CSD)
diff --git a/chrome/renderer/chrome_render_frame_observer.h b/chrome/renderer/chrome_render_frame_observer.h
index 7437034..24da7f6 100644
--- a/chrome/renderer/chrome_render_frame_observer.h
+++ b/chrome/renderer/chrome_render_frame_observer.h
@@ -66,6 +66,7 @@
       chrome::mojom::ThumbnailCapturerRequest request);
 
   // IPC handlers
+  void OnGetWebApplicationInfo();
   void OnSetIsPrerendering(prerender::PrerenderMode mode);
   void OnRequestThumbnailForContextNode(
       int thumbnail_min_area_pixels,
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index dd9335a..5445f7fb 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -16,12 +16,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
-#include "chrome/common/chrome_constants.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
-#include "chrome/renderer/web_apps.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -61,8 +59,6 @@
     IPC_MESSAGE_HANDLER(ChromeViewMsg_UpdateBrowserControlsState,
                         OnUpdateBrowserControlsState)
 #endif
-    IPC_MESSAGE_HANDLER(ChromeViewMsg_GetWebApplicationInfo,
-                        OnGetWebApplicationInfo)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetWindowFeatures, OnSetWindowFeatures)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -86,50 +82,6 @@
 }
 #endif
 
-void ChromeRenderViewObserver::OnGetWebApplicationInfo() {
-  WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
-  DCHECK(main_frame);
-
-  WebApplicationInfo web_app_info;
-  web_apps::ParseWebAppFromWebDocument(main_frame, &web_app_info);
-
-  // The warning below is specific to mobile but it doesn't hurt to show it even
-  // if the Chromium build is running on a desktop. It will get more exposition.
-  // TODO(mlamouri): Associate this message with an actual frame, to avoid the
-  // need to check whether or not the main frame is local.
-  if (web_app_info.mobile_capable == WebApplicationInfo::MOBILE_CAPABLE_APPLE &&
-      main_frame->IsWebLocalFrame()) {
-    blink::WebConsoleMessage message(
-        blink::WebConsoleMessage::kLevelWarning,
-        "<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"> is "
-        "deprecated. Please include <meta name=\"mobile-web-app-capable\" "
-        "content=\"yes\"> - "
-        "http://developers.google.com/chrome/mobile/docs/installtohomescreen");
-    main_frame->ToWebLocalFrame()->AddMessageToConsole(message);
-  }
-
-  // Prune out any data URLs in the set of icons.  The browser process expects
-  // any icon with a data URL to have originated from a favicon.  We don't want
-  // to decode arbitrary data URLs in the browser process.  See
-  // http://b/issue?id=1162972
-  for (std::vector<WebApplicationInfo::IconInfo>::iterator it =
-          web_app_info.icons.begin(); it != web_app_info.icons.end();) {
-    if (it->url.SchemeIs(url::kDataScheme))
-      it = web_app_info.icons.erase(it);
-    else
-      ++it;
-  }
-
-  // Truncate the strings we send to the browser process.
-  web_app_info.title =
-      web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength);
-  web_app_info.description =
-      web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength);
-
-  Send(new ChromeViewHostMsg_DidGetWebApplicationInfo(
-      routing_id(), web_app_info));
-}
-
 void ChromeRenderViewObserver::OnSetWindowFeatures(
     const blink::mojom::WindowFeatures& window_features) {
   render_view()->GetWebView()->SetWindowFeatures(
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index ea76e9d..5609f10 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -48,7 +48,6 @@
                                     content::BrowserControlsState current,
                                     bool animate);
 #endif
-  void OnGetWebApplicationInfo();
   void OnSetWindowFeatures(const blink::mojom::WindowFeatures& window_features);
 
   // Determines if a host is in the strict security host set.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 216f665..0979d615 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2061,7 +2061,6 @@
         "../browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc",
         "../browser/ui/views/payments/payment_request_completion_status_metrics_browsertest.cc",
         "../browser/ui/views/payments/payment_request_data_url_browsertest.cc",
-        "../browser/ui/views/payments/payment_request_debit_browsertest.cc",
         "../browser/ui/views/payments/payment_request_journey_logger_browsertest.cc",
         "../browser/ui/views/payments/payment_request_payment_app_browsertest.cc",
         "../browser/ui/views/payments/payment_request_payment_response_browsertest.cc",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 1faa6b0e..884a457 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -1050,6 +1050,12 @@
   return last_session_exited_cleanly_ ? EXIT_NORMAL : EXIT_CRASHED;
 }
 
+scoped_refptr<base::SequencedTaskRunner>
+TestingProfile::GetPrefServiceTaskRunner() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 TestingProfile::Builder::Builder()
     : build_called_(false),
       delegate_(NULL),
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 2384f0c..9aefe2d 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -327,6 +327,7 @@
   bool IsGuestSession() const override;
   void SetExitType(ExitType exit_type) override {}
   ExitType GetLastSessionExitType() override;
+  scoped_refptr<base::SequencedTaskRunner> GetPrefServiceTaskRunner() override;
 #if defined(OS_CHROMEOS)
   void ChangeAppLocale(const std::string&, AppLocaleChangedVia) override {}
   void OnLogin() override {}
diff --git a/chrome/test/data/payments/debit.js b/chrome/test/data/payments/debit.js
deleted file mode 100644
index f8f293c2c..0000000
--- a/chrome/test/data/payments/debit.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * Builds a payment request for a debit card.
- * @return {!PaymentRequest} A payment request for a debit card.
- * @private
- */
-function buildPaymentRequest() {
-  return new PaymentRequest([{
-    supportedMethods: ['basic-card'],
-    data: {
-      supportedTypes: ['debit'],
-    },
-  }], {
-    total: {
-      label: 'Total',
-      amount: {
-        currency: 'USD',
-        value: '1.00',
-      },
-    },
-  });
-}
-
-/** Requests payment via a debit card. */
-function buy() { // eslint-disable-line no-unused-vars
-  try {
-    buildPaymentRequest()
-      .show()
-      .then(function(response) {
-        response.complete()
-          .then(function() {
-            print(JSON.stringify(response, undefined, 2));
-          })
-          .catch(function(error) {
-            print(error);
-          });
-      })
-      .catch(function(error) {
-        print(error);
-      });
-  } catch (error) {
-    print(error);
-  }
-}
-
-/** Checks whether payment via a debit card is possible. */
-function canMakePayment() { // eslint-disable-line no-unused-vars
-  try {
-    buildPaymentRequest()
-      .canMakePayment()
-      .then(function(result) {
-        print(result);
-      })
-      .catch(function(error) {
-        print(error);
-      });
-  } catch (error) {
-    print(error);
-  }
-}
diff --git a/chrome/test/data/payments/payment_request_debit_test.html b/chrome/test/data/payments/payment_request_debit_test.html
deleted file mode 100644
index 33c8ae5c..0000000
--- a/chrome/test/data/payments/payment_request_debit_test.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<!--
-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.
--->
-<html>
-
-<head>
-  <title>Debit Test</title>
-  <meta charset="utf-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <link rel="stylesheet" type="text/css" href="style.css">
-</head>
-
-<body>
-  <div><button onclick="buy()" id="buy">Debit Buy Test</button></div>
-  <div><button onclick="canMakePayment()" id="canMakePayment">Debit
-      CanMakePayment Test</button></div>
-  <pre id="result"></pre>
-  <script src="util.js"></script>
-  <script src="debit.js"></script>
-</body>
-
-</html>
diff --git a/chrome/utility/media_router/dial_device_description_parser_impl.h b/chrome/utility/media_router/dial_device_description_parser_impl.h
index 9f3eb3ae..ee6e741 100644
--- a/chrome/utility/media_router/dial_device_description_parser_impl.h
+++ b/chrome/utility/media_router/dial_device_description_parser_impl.h
@@ -6,6 +6,7 @@
 #define CHROME_UTILITY_MEDIA_ROUTER_DIAL_DEVICE_DESCRIPTION_PARSER_IMPL_H_
 
 #include "base/macros.h"
+#include "base/threading/thread_checker.h"
 #include "chrome/common/media_router/mojo/dial_device_description_parser.mojom.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 
diff --git a/components/BUILD.gn b/components/BUILD.gn
index a6e920843..6189588 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -157,6 +157,10 @@
     "//components/webdata/common:unit_tests",
   ]
 
+  if (toolkit_views && use_aura) {
+    deps += [ "//components/ui_devtools/views:unit_tests" ]
+  }
+
   if (enable_nacl) {
     deps += [ "//components/nacl/browser:unit_tests" ]
   }
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc
index e49ffd8e..cda89cd 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -78,9 +78,9 @@
 
 // static
 void ContentAutofillDriverFactory::BindAutofillDriver(
-    content::RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    mojom::AutofillDriverRequest request) {
+    mojom::AutofillDriverRequest request,
+    content::RenderFrameHost* render_frame_host) {
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   // We try to bind to the driver of this render frame host,
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h
index e7f0b97..6c9efea3 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -47,9 +47,9 @@
   static ContentAutofillDriverFactory* FromWebContents(
       content::WebContents* contents);
   static void BindAutofillDriver(
-      content::RenderFrameHost* render_frame_host,
       const service_manager::BindSourceInfo& source_info,
-      mojom::AutofillDriverRequest request);
+      mojom::AutofillDriverRequest request,
+      content::RenderFrameHost* render_frame_host);
 
   // Gets the |ContentAutofillDriver| associated with |render_frame_host|.
   // |render_frame_host| must be owned by |web_contents()|.
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index d849ce1..d96e9046 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -283,6 +283,9 @@
     INFOBAR_DENIED,     // The user explicitly denied the infobar.
     INFOBAR_IGNORED,    // The user completely ignored the infobar (logged on
                         // tab close).
+    INFOBAR_NOT_SHOWN_INVALID_LEGAL_MESSAGE,  // We didn't show the infobar
+                                              // because the provided legal
+                                              // message was invalid.
     NUM_INFO_BAR_METRICS,
   };
 
diff --git a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
index 62674317..d28102a 100644
--- a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
+++ b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -43,8 +43,15 @@
 #endif
       card_label_(base::string16(kMidlineEllipsis) + card.LastFourDigits()),
       card_sub_label_(card.AbbreviatedExpirationDateForDisplay()) {
-  if (legal_message)
-    LegalMessageLine::Parse(*legal_message, &legal_messages_);
+  if (legal_message) {
+    if (!LegalMessageLine::Parse(*legal_message, &legal_messages_)) {
+      AutofillMetrics::LogCreditCardInfoBarMetric(
+          AutofillMetrics::INFOBAR_NOT_SHOWN_INVALID_LEGAL_MESSAGE, upload_,
+          pref_service_->GetInteger(
+              prefs::kAutofillAcceptSaveCreditCardPromptState));
+      return;
+    }
+  }
 
   AutofillMetrics::LogCreditCardInfoBarMetric(
       AutofillMetrics::INFOBAR_SHOWN, upload_,
@@ -63,6 +70,12 @@
   infobar()->owner()->OpenURL(url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
 }
 
+bool AutofillSaveCardInfoBarDelegateMobile::LegalMessagesParsedSuccessfully() {
+  // If we are uploading to the server, verify that legal lines have been parsed
+  // into |legal_messages_|.
+  return !upload_ || !legal_messages_.empty();
+}
+
 int AutofillSaveCardInfoBarDelegateMobile::GetIconId() const {
   return IDR_INFOBAR_AUTOFILL_CC;
 }
diff --git a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
index d1a0d229..8b933018 100644
--- a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
+++ b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
@@ -45,6 +45,10 @@
   // Called when a link in the legal message text was clicked.
   void OnLegalMessageLinkClicked(GURL url);
 
+  // Ensures the InfoBar is not shown if legal messages failed to parse.
+  // Legal messages are only specified for the upload case, not for local save.
+  bool LegalMessagesParsedSuccessfully();
+
   // ConfirmInfoBarDelegate:
   int GetIconId() const override;
   base::string16 GetMessageText() const override;
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc
index 0e343a8..33dc123 100644
--- a/components/autofill/core/browser/credit_card.cc
+++ b/components/autofill/core/browser/credit_card.cc
@@ -103,7 +103,6 @@
 CreditCard::CreditCard(const std::string& guid, const std::string& origin)
     : AutofillDataModel(guid, origin),
       record_type_(LOCAL_CARD),
-      card_type_(CARD_TYPE_UNKNOWN),
       network_(kGenericCard),
       expiration_month_(0),
       expiration_year_(0),
@@ -491,7 +490,6 @@
     return;
 
   record_type_ = credit_card.record_type_;
-  card_type_ = credit_card.card_type_;
   number_ = credit_card.number_;
   name_on_card_ = credit_card.name_on_card_;
   network_ = credit_card.network_;
diff --git a/components/autofill/core/browser/credit_card.h b/components/autofill/core/browser/credit_card.h
index d5cd807c..4dc8bb9 100644
--- a/components/autofill/core/browser/credit_card.h
+++ b/components/autofill/core/browser/credit_card.h
@@ -46,17 +46,6 @@
     OK,
   };
 
-  // The type of the card. Local cards are all CARD_TYPE_UNKNOWN. Server cards
-  // may have a more specific type.
-  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.autofill
-  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: CardType
-  enum CardType : int {
-    CARD_TYPE_UNKNOWN,
-    CARD_TYPE_CREDIT,
-    CARD_TYPE_DEBIT,
-    CARD_TYPE_PREPAID,
-  };
-
   CreditCard(const std::string& guid, const std::string& origin);
 
   // Creates a server card.  The type must be MASKED_SERVER_CARD or
@@ -158,11 +147,6 @@
   RecordType record_type() const { return record_type_; }
   void set_record_type(RecordType rt) { record_type_ = rt; }
 
-  // Whether this is a credit, debit, or prepaid card. Known only for server
-  // cards. All local cards are CARD_TYPE_UNKNOWN.
-  CardType card_type() const { return card_type_; }
-  void set_card_type(CardType card_type) { card_type_ = card_type; }
-
   // Returns true if there are no values (field types) set.
   bool IsEmpty(const std::string& app_locale) const;
 
@@ -253,7 +237,6 @@
 
   // See enum definition above.
   RecordType record_type_;
-  CardType card_type_;
 
   // The card number. For MASKED_SERVER_CARDs, this number will just contain the
   // last four digits of the card number.
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 4225073d..2a1b23d 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -835,27 +835,6 @@
     EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
 }
 
-TEST_F(PersonalDataManagerTest, SavesServerCardType) {
-  EnableWalletCardImport();
-  std::vector<CreditCard> server_cards;
-  server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
-  test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
-                          "9012" /* Visa */, "01", "2999", "1");
-  server_cards.back().SetNetworkForMaskedCard(kVisaCard);
-
-  server_cards.back().set_card_type(CreditCard::CARD_TYPE_DEBIT);
-
-  test::SetServerCreditCards(autofill_table_, server_cards);
-  personal_data_->Refresh();
-  EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
-      .WillOnce(QuitMainMessageLoop());
-  base::RunLoop().Run();
-  auto cards = personal_data_->GetCreditCards();
-  ASSERT_EQ(1U, cards.size());
-
-  EXPECT_EQ(CreditCard::CARD_TYPE_DEBIT, cards.front()->card_type());
-}
-
 TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
   AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
   test::SetProfileInfo(&profile0,
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index f32cee2..d98db89 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -472,9 +472,6 @@
     case 72:
       *update_compatible_version = true;
       return MigrateToVersion72RenameCardTypeToIssuerNetwork();
-    case 73:
-      *update_compatible_version = false;
-      return MigrateToVersion73AddServerCardTypeColumn();
   }
   return true;
 }
@@ -1218,12 +1215,11 @@
       "metadata.use_count,"           // 3
       "metadata.use_date,"            // 4
       "network,"                      // 5
-      "type,"                         // 6
-      "status,"                       // 7
-      "name_on_card,"                 // 8
-      "exp_month,"                    // 9
-      "exp_year,"                     // 10
-      "metadata.billing_address_id "  // 11
+      "status,"                       // 6
+      "name_on_card,"                 // 7
+      "exp_month,"                    // 8
+      "exp_year,"                     // 9
+      "metadata.billing_address_id "  // 10
       "FROM masked_credit_cards masked "
       "LEFT OUTER JOIN unmasked_credit_cards USING (id) "
       "LEFT OUTER JOIN server_card_metadata metadata USING (id)"));
@@ -1260,12 +1256,6 @@
       DCHECK_EQ(CreditCard::GetCardNetwork(full_card_number), card_network);
     }
 
-    int card_type = s.ColumnInt(index++);
-    if (card_type >= CreditCard::CARD_TYPE_UNKNOWN &&
-        card_type <= CreditCard::CARD_TYPE_PREPAID) {
-      card->set_card_type(static_cast<CreditCard::CardType>(card_type));
-    }
-
     card->SetServerStatus(ServerStatusStringToEnum(s.ColumnString(index++)));
     card->SetRawInfo(CREDIT_CARD_NAME_FULL, s.ColumnString16(index++));
     card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++));
@@ -1283,24 +1273,22 @@
       db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
                               "id,"            // 0
                               "network,"       // 1
-                              "type,"          // 2
-                              "status,"        // 3
-                              "name_on_card,"  // 4
-                              "last_four,"     // 5
-                              "exp_month,"     // 6
-                              "exp_year)"      // 7
-                              "VALUES (?,?,?,?,?,?,?,?)"));
+                              "status,"        // 2
+                              "name_on_card,"  // 3
+                              "last_four,"     // 4
+                              "exp_month,"     // 5
+                              "exp_year)"      // 6
+                              "VALUES (?,?,?,?,?,?,?)"));
   for (const CreditCard& card : credit_cards) {
     DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
     masked_insert.BindString(0, card.server_id());
     masked_insert.BindString(1, card.network());
-    masked_insert.BindInt(2, card.card_type());
-    masked_insert.BindString(3,
+    masked_insert.BindString(2,
                              ServerStatusEnumToString(card.GetServerStatus()));
-    masked_insert.BindString16(4, card.GetRawInfo(CREDIT_CARD_NAME_FULL));
-    masked_insert.BindString16(5, card.LastFourDigits());
-    masked_insert.BindString16(6, card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
-    masked_insert.BindString16(7,
+    masked_insert.BindString16(3, card.GetRawInfo(CREDIT_CARD_NAME_FULL));
+    masked_insert.BindString16(4, card.LastFourDigits());
+    masked_insert.BindString16(5, card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
+    masked_insert.BindString16(6,
                                card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
 
     masked_insert.Run();
@@ -1367,12 +1355,12 @@
 
 void AutofillTable::AddUnmaskedCreditCard(const std::string& id,
                                           const base::string16& full_number) {
-  sql::Statement s(
-      db_->GetUniqueStatement("INSERT INTO unmasked_credit_cards("
-                              "id,"
-                              "card_number_encrypted,"
-                              "unmask_date)"
-                              "VALUES (?,?,?)"));
+  sql::Statement s(db_->GetUniqueStatement(
+      "INSERT INTO unmasked_credit_cards("
+          "id,"
+          "card_number_encrypted,"
+          "unmask_date)"
+      "VALUES (?,?,?)"));
   s.BindString(0, id);
 
   std::string encrypted_data;
@@ -1968,8 +1956,7 @@
                       "network VARCHAR,"
                       "last_four VARCHAR,"
                       "exp_month INTEGER DEFAULT 0,"
-                      "exp_year INTEGER DEFAULT 0, "
-                      "type INTEGER DEFAULT 0)")) {
+                      "exp_year INTEGER DEFAULT 0)")) {
       NOTREACHED();
       return false;
     }
@@ -2612,9 +2599,4 @@
          transaction.Commit();
 }
 
-bool AutofillTable::MigrateToVersion73AddServerCardTypeColumn() {
-  return db_->Execute(
-      "ALTER TABLE masked_credit_cards ADD COLUMN type INTEGER DEFAULT 0");
-}
-
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index 4949791..161b033f 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -162,8 +162,6 @@
 //   name_on_card
 //   network            Issuer network of the card. For example, "VISA". Renamed
 //                      from "type" in version 72.
-//   type               Card type. One of CreditCard::CardType enum values.
-//                      Added in version 73.
 //   last_four          Last four digits of the card number. For de-duping
 //                      with locally stored cards and generating descriptions.
 //   exp_month          Expiration month: 1-12
@@ -466,7 +464,6 @@
   bool MigrateToVersion70AddSyncMetadata();
   bool MigrateToVersion71AddHasConvertedAndBillingAddressIdMetadata();
   bool MigrateToVersion72RenameCardTypeToIssuerNetwork();
-  bool MigrateToVersion73AddServerCardTypeColumn();
 
   // Max data length saved in the table, AKA the maximum length allowed for
   // form data.
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index 5f332262..54e8be78 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -35,7 +35,7 @@
   return reinterpret_cast<void*>(&user_data_key);
 }
 
-const char* CardNetworkFromWalletCardType(
+const char* CardTypeFromWalletCardType(
     sync_pb::WalletMaskedCreditCard::WalletCardType type) {
   switch (type) {
     case sync_pb::WalletMaskedCreditCard::AMEX:
@@ -60,20 +60,6 @@
   }
 }
 
-CreditCard::CardType CardTypeFromWalletCardClass(
-    sync_pb::WalletMaskedCreditCard::WalletCardClass card_class) {
-  switch (card_class) {
-    case sync_pb::WalletMaskedCreditCard::CREDIT:
-      return CreditCard::CARD_TYPE_CREDIT;
-    case sync_pb::WalletMaskedCreditCard::DEBIT:
-      return CreditCard::CARD_TYPE_DEBIT;
-    case sync_pb::WalletMaskedCreditCard::PREPAID:
-      return CreditCard::CARD_TYPE_PREPAID;
-    default:
-      return CreditCard::CARD_TYPE_UNKNOWN;
-  }
-}
-
 CreditCard::ServerStatus ServerToLocalStatus(
     sync_pb::WalletMaskedCreditCard::WalletCardStatus status) {
   switch (status) {
@@ -90,8 +76,7 @@
   CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id());
   result.SetNumber(base::UTF8ToUTF16(card.last_four()));
   result.SetServerStatus(ServerToLocalStatus(card.status()));
-  result.SetNetworkForMaskedCard(CardNetworkFromWalletCardType(card.type()));
-  result.set_card_type(CardTypeFromWalletCardClass(card.card_class()));
+  result.SetNetworkForMaskedCard(CardTypeFromWalletCardType(card.type()));
   result.SetRawInfo(CREDIT_CARD_NAME_FULL,
                     base::UTF8ToUTF16(card.name_on_card()));
   result.SetExpirationMonth(card.exp_month());
@@ -113,7 +98,8 @@
   profile.SetRawInfo(COMPANY_NAME, base::UTF8ToUTF16(address.company_name()));
   profile.SetRawInfo(ADDRESS_HOME_STATE,
                      base::UTF8ToUTF16(address.address_1()));
-  profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(address.address_2()));
+  profile.SetRawInfo(ADDRESS_HOME_CITY,
+                     base::UTF8ToUTF16(address.address_2()));
   profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
                      base::UTF8ToUTF16(address.address_3()));
   // AutofillProfile doesn't support address_4 ("sub dependent locality").
@@ -206,9 +192,11 @@
 AutofillWalletSyncableService::AutofillWalletSyncableService(
     AutofillWebDataBackend* webdata_backend,
     const std::string& app_locale)
-    : webdata_backend_(webdata_backend) {}
+    : webdata_backend_(webdata_backend) {
+}
 
-AutofillWalletSyncableService::~AutofillWalletSyncableService() {}
+AutofillWalletSyncableService::~AutofillWalletSyncableService() {
+}
 
 syncer::SyncMergeResult AutofillWalletSyncableService::MergeDataAndStartSyncing(
     syncer::ModelType type,
@@ -354,8 +342,10 @@
   size_t prev_card_count = 0;
   size_t prev_address_count = 0;
   bool changed_cards = SetDataIfChanged(
-      table, wallet_cards, &AutofillTable::GetServerCreditCards,
-      &AutofillTable::SetServerCreditCards, &prev_card_count);
+      table, wallet_cards,
+      &AutofillTable::GetServerCreditCards,
+      &AutofillTable::SetServerCreditCards,
+      &prev_card_count);
   bool changed_addresses = SetDataIfChanged(
       table, wallet_addresses, &AutofillTable::GetServerProfiles,
       &AutofillTable::SetServerProfiles, &prev_address_count);
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 6ccc3a2..44c5cdd9 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -1300,6 +1300,8 @@
     return;
   }
 
+  RecordMemoryUsageHistograms();
+
   StartSyncingWithServer();
 }
 
@@ -2392,6 +2394,16 @@
   sync_prefs_.SetCleanShutdown(false);
 }
 
+void ProfileSyncService::RecordMemoryUsageHistograms() {
+  ModelTypeSet active_types = GetActiveDataTypes();
+  for (ModelTypeSet::Iterator type_it = active_types.First(); type_it.Good();
+       type_it.Inc()) {
+    auto dtc_it = data_type_controllers_.find(type_it.Get());
+    if (dtc_it != data_type_controllers_.end())
+      dtc_it->second->RecordMemoryUsageHistogram();
+  }
+}
+
 const GURL& ProfileSyncService::sync_service_url() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   return sync_service_url_;
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index a47fe59..ed8908c 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -725,6 +725,9 @@
   // Check if previous shutdown is shutdown cleanly.
   void ReportPreviousSessionMemoryWarningCount();
 
+  // Estimates and records memory usage histograms per type.
+  void RecordMemoryUsageHistograms();
+
   // After user switches to custom passphrase encryption a set of steps needs to
   // be performed:
   //
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index e8e65b4..a3ba71d 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -27,7 +27,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/statistics_recorder.h"
@@ -726,39 +725,38 @@
   }
 
   if (config->enable_quic) {
-    for (auto hint = config->quic_hints.begin();
-         hint != config->quic_hints.end(); ++hint) {
-      const URLRequestContextConfig::QuicHint& quic_hint = **hint;
-      if (quic_hint.host.empty()) {
-        LOG(ERROR) << "Empty QUIC hint host: " << quic_hint.host;
+    for (const auto& quic_hint : config->quic_hints) {
+      if (quic_hint->host.empty()) {
+        LOG(ERROR) << "Empty QUIC hint host: " << quic_hint->host;
         continue;
       }
 
       url::CanonHostInfo host_info;
-      std::string canon_host(net::CanonicalizeHost(quic_hint.host, &host_info));
+      std::string canon_host(
+          net::CanonicalizeHost(quic_hint->host, &host_info));
       if (!host_info.IsIPAddress() &&
           !net::IsCanonicalizedHostCompliant(canon_host)) {
-        LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint.host;
+        LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint->host;
         continue;
       }
 
-      if (quic_hint.port <= std::numeric_limits<uint16_t>::min() ||
-          quic_hint.port > std::numeric_limits<uint16_t>::max()) {
-        LOG(ERROR) << "Invalid QUIC hint port: "
-                   << quic_hint.port;
+      if (quic_hint->port <= std::numeric_limits<uint16_t>::min() ||
+          quic_hint->port > std::numeric_limits<uint16_t>::max()) {
+        LOG(ERROR) << "Invalid QUIC hint port: " << quic_hint->port;
         continue;
       }
 
-      if (quic_hint.alternate_port <= std::numeric_limits<uint16_t>::min() ||
-          quic_hint.alternate_port > std::numeric_limits<uint16_t>::max()) {
+      if (quic_hint->alternate_port <= std::numeric_limits<uint16_t>::min() ||
+          quic_hint->alternate_port > std::numeric_limits<uint16_t>::max()) {
         LOG(ERROR) << "Invalid QUIC hint alternate port: "
-                   << quic_hint.alternate_port;
+                   << quic_hint->alternate_port;
         continue;
       }
 
-      url::SchemeHostPort quic_server("https", canon_host, quic_hint.port);
+      url::SchemeHostPort quic_server("https", canon_host, quic_hint->port);
       net::AlternativeService alternative_service(
-          net::kProtoQUIC, "", static_cast<uint16_t>(quic_hint.alternate_port));
+          net::kProtoQUIC, "",
+          static_cast<uint16_t>(quic_hint->alternate_port));
       context_->http_server_properties()->SetAlternativeService(
           quic_server, alternative_service, base::Time::Max());
     }
@@ -779,7 +777,7 @@
   }
 
   // Iterate through PKP configuration for every host.
-  for (auto* const pkp : config->pkp_list) {
+  for (const auto& pkp : config->pkp_list) {
     // Add the host pinning.
     context_->transport_security_state()->AddHPKP(
         pkp->host, pkp->expiration_date, pkp->include_subdomains,
diff --git a/components/cronet/ios/Cronet.mm b/components/cronet/ios/Cronet.mm
index 2b40989..489b70c3 100644
--- a/components/cronet/ios/Cronet.mm
+++ b/components/cronet/ios/Cronet.mm
@@ -5,13 +5,13 @@
 #import "components/cronet/ios/Cronet.h"
 
 #include <memory>
+#include <vector>
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/mac/bundle_locations.h"
 #include "base/mac/scoped_block.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/synchronization/lock.h"
 #include "components/cronet/ios/accept_languages_table.h"
@@ -26,6 +26,8 @@
 
 class CronetHttpProtocolHandlerDelegate;
 
+using QuicHintVector =
+    std::vector<std::unique_ptr<cronet::URLRequestContextConfig::QuicHint>>;
 // Currently there is one and only one instance of CronetEnvironment,
 // which is leaked at the shutdown. We should consider allowing multiple
 // instances if that makes sense in the future.
@@ -36,12 +38,12 @@
 BOOL gQuicEnabled = NO;
 cronet::URLRequestContextConfig::HttpCacheType gHttpCache =
     cronet::URLRequestContextConfig::HttpCacheType::DISK;
-ScopedVector<cronet::URLRequestContextConfig::QuicHint> gQuicHints;
+QuicHintVector gQuicHints;
 NSString* gExperimentalOptions = @"{}";
 NSString* gUserAgent = nil;
 BOOL gUserAgentPartial = NO;
 NSString* gSslKeyLogFileName = nil;
-ScopedVector<cronet::URLRequestContextConfig::Pkp> gPkpList = {};
+std::vector<std::unique_ptr<cronet::URLRequestContextConfig::Pkp>> gPkpList;
 RequestFilterBlock gRequestFilterBlock = nil;
 base::LazyInstance<std::unique_ptr<CronetHttpProtocolHandlerDelegate>>::Leaky
     gHttpProtocolHandlerDelegate = LAZY_INSTANCE_INITIALIZER;
@@ -171,8 +173,9 @@
 
 + (void)addQuicHint:(NSString*)host port:(int)port altPort:(int)altPort {
   [self checkNotStarted];
-  gQuicHints.push_back(new cronet::URLRequestContextConfig::QuicHint(
-      base::SysNSStringToUTF8(host), port, altPort));
+  gQuicHints.push_back(
+      base::MakeUnique<cronet::URLRequestContextConfig::QuicHint>(
+          base::SysNSStringToUTF8(host), port, altPort));
 }
 
 + (void)setExperimentalOptions:(NSString*)experimentalOptions {
@@ -264,7 +267,7 @@
   gChromeNet.Get()->set_ssl_key_log_file_name(
       base::SysNSStringToUTF8(gSslKeyLogFileName));
   gChromeNet.Get()->set_pkp_list(std::move(gPkpList));
-  for (const auto* quicHint : gQuicHints) {
+  for (const auto& quicHint : gQuicHints) {
     gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port,
                                   quicHint->alternate_port);
   }
diff --git a/components/cronet/ios/cronet_environment.h b/components/cronet/ios/cronet_environment.h
index 99eb667a..8363025 100644
--- a/components/cronet/ios/cronet_environment.h
+++ b/components/cronet/ios/cronet_environment.h
@@ -37,6 +37,8 @@
 // and initialization.
 class CronetEnvironment {
  public:
+  using PkpVector = std::vector<std::unique_ptr<URLRequestContextConfig::Pkp>>;
+
   // Initialize Cronet environment globals. Must be called only once on the
   // main thread.
   static void Initialize();
@@ -101,9 +103,7 @@
     ssl_key_log_file_name_ = ssl_key_log_file_name;
   }
 
-  void set_pkp_list(ScopedVector<URLRequestContextConfig::Pkp> pkp_list) {
-    pkp_list_ = std::move(pkp_list);
-  }
+  void set_pkp_list(PkpVector pkp_list) { pkp_list_ = std::move(pkp_list); }
 
   // Returns the URLRequestContext associated with this object.
   net::URLRequestContext* GetURLRequestContext() const;
@@ -145,7 +145,7 @@
   std::string experimental_options_;
   std::string ssl_key_log_file_name_;
   URLRequestContextConfig::HttpCacheType http_cache_;
-  ScopedVector<URLRequestContextConfig::Pkp> pkp_list_;
+  PkpVector pkp_list_;
 
   std::list<net::HostPortPair> quic_hints_;
 
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index 326bb88..0154346 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -347,7 +347,7 @@
   main_context_ = context_builder.Build();
 
   // Iterate through PKP configuration for every host.
-  for (auto* const pkp : config->pkp_list) {
+  for (const auto& pkp : config->pkp_list) {
     // Add the host pinning.
     main_context_->transport_security_state()->AddHPKP(
         pkp->host, pkp->expiration_date, pkp->include_subdomains,
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index 16bd87f..e4b4a773 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -86,14 +86,65 @@
 
 const char kSSLKeyLogFile[] = "ssl_key_log_file";
 
-// Returns the effective experimental options.
-std::unique_ptr<base::DictionaryValue> ParseAndSetExperimentalOptions(
+}  // namespace
+
+URLRequestContextConfig::QuicHint::QuicHint(const std::string& host,
+                                            int port,
+                                            int alternate_port)
+    : host(host), port(port), alternate_port(alternate_port) {}
+
+URLRequestContextConfig::QuicHint::~QuicHint() {}
+
+URLRequestContextConfig::Pkp::Pkp(const std::string& host,
+                                  bool include_subdomains,
+                                  const base::Time& expiration_date)
+    : host(host),
+      include_subdomains(include_subdomains),
+      expiration_date(expiration_date) {}
+
+URLRequestContextConfig::Pkp::~Pkp() {}
+
+URLRequestContextConfig::URLRequestContextConfig(
+    bool enable_quic,
+    const std::string& quic_user_agent_id,
+    bool enable_spdy,
+    bool enable_sdch,
+    bool enable_brotli,
+    HttpCacheType http_cache,
+    int http_cache_max_size,
+    bool load_disable_cache,
+    const std::string& storage_path,
+    const std::string& user_agent,
     const std::string& experimental_options,
+    std::unique_ptr<net::CertVerifier> mock_cert_verifier,
+    bool enable_network_quality_estimator,
+    bool bypass_public_key_pinning_for_local_trust_anchors,
+    const std::string& cert_verifier_data)
+    : enable_quic(enable_quic),
+      quic_user_agent_id(quic_user_agent_id),
+      enable_spdy(enable_spdy),
+      enable_sdch(enable_sdch),
+      enable_brotli(enable_brotli),
+      http_cache(http_cache),
+      http_cache_max_size(http_cache_max_size),
+      load_disable_cache(load_disable_cache),
+      storage_path(storage_path),
+      user_agent(user_agent),
+      experimental_options(experimental_options),
+      mock_cert_verifier(std::move(mock_cert_verifier)),
+      enable_network_quality_estimator(enable_network_quality_estimator),
+      bypass_public_key_pinning_for_local_trust_anchors(
+          bypass_public_key_pinning_for_local_trust_anchors),
+      cert_verifier_data(cert_verifier_data) {}
+
+URLRequestContextConfig::~URLRequestContextConfig() {}
+
+void URLRequestContextConfig::ParseAndSetExperimentalOptions(
     net::URLRequestContextBuilder* context_builder,
     net::NetLog* net_log,
     const scoped_refptr<base::SequencedTaskRunner>& file_task_runner) {
   if (experimental_options.empty())
-    return nullptr;
+    return;
 
   DCHECK(net_log);
 
@@ -104,7 +155,7 @@
   if (!options) {
     DCHECK(false) << "Parsing experimental options failed: "
                   << experimental_options;
-    return nullptr;
+    return;
   }
 
   std::unique_ptr<base::DictionaryValue> dict =
@@ -113,7 +164,7 @@
   if (!dict) {
     DCHECK(false) << "Experimental options string is not a dictionary: "
                   << experimental_options;
-    return nullptr;
+    return;
   }
 
   bool async_dns_enable = false;
@@ -121,8 +172,7 @@
   bool host_resolver_rules_enable = false;
   bool disable_ipv6_on_wifi = false;
 
-  std::unique_ptr<base::DictionaryValue> effective_experimental_options =
-      dict->CreateDeepCopy();
+  effective_experimental_options = dict->CreateDeepCopy();
   StaleHostResolver::StaleOptions stale_dns_options;
   std::string host_resolver_rules_string;
   for (base::DictionaryValue::Iterator it(*dict.get()); !it.IsAtEnd();
@@ -306,62 +356,8 @@
     }
     context_builder->set_host_resolver(std::move(host_resolver));
   }
-  return effective_experimental_options;
 }
 
-}  // namespace
-
-URLRequestContextConfig::QuicHint::QuicHint(const std::string& host,
-                                            int port,
-                                            int alternate_port)
-    : host(host), port(port), alternate_port(alternate_port) {}
-
-URLRequestContextConfig::QuicHint::~QuicHint() {}
-
-URLRequestContextConfig::Pkp::Pkp(const std::string& host,
-                                  bool include_subdomains,
-                                  const base::Time& expiration_date)
-    : host(host),
-      include_subdomains(include_subdomains),
-      expiration_date(expiration_date) {}
-
-URLRequestContextConfig::Pkp::~Pkp() {}
-
-URLRequestContextConfig::URLRequestContextConfig(
-    bool enable_quic,
-    const std::string& quic_user_agent_id,
-    bool enable_spdy,
-    bool enable_sdch,
-    bool enable_brotli,
-    HttpCacheType http_cache,
-    int http_cache_max_size,
-    bool load_disable_cache,
-    const std::string& storage_path,
-    const std::string& user_agent,
-    const std::string& experimental_options,
-    std::unique_ptr<net::CertVerifier> mock_cert_verifier,
-    bool enable_network_quality_estimator,
-    bool bypass_public_key_pinning_for_local_trust_anchors,
-    const std::string& cert_verifier_data)
-    : enable_quic(enable_quic),
-      quic_user_agent_id(quic_user_agent_id),
-      enable_spdy(enable_spdy),
-      enable_sdch(enable_sdch),
-      enable_brotli(enable_brotli),
-      http_cache(http_cache),
-      http_cache_max_size(http_cache_max_size),
-      load_disable_cache(load_disable_cache),
-      storage_path(storage_path),
-      user_agent(user_agent),
-      experimental_options(experimental_options),
-      mock_cert_verifier(std::move(mock_cert_verifier)),
-      enable_network_quality_estimator(enable_network_quality_estimator),
-      bypass_public_key_pinning_for_local_trust_anchors(
-          bypass_public_key_pinning_for_local_trust_anchors),
-      cert_verifier_data(cert_verifier_data) {}
-
-URLRequestContextConfig::~URLRequestContextConfig() {}
-
 void URLRequestContextConfig::ConfigureURLRequestContextBuilder(
     net::URLRequestContextBuilder* context_builder,
     net::NetLog* net_log,
@@ -391,8 +387,7 @@
   if (enable_quic)
     context_builder->set_quic_user_agent_id(quic_user_agent_id);
 
-  effective_experimental_options = ParseAndSetExperimentalOptions(
-      experimental_options, context_builder, net_log, file_task_runner);
+  ParseAndSetExperimentalOptions(context_builder, net_log, file_task_runner);
 
   std::unique_ptr<net::CertVerifier> cert_verifier;
   if (mock_cert_verifier) {
diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h
index 6e55a92a..7b13833 100644
--- a/components/cronet/url_request_context_config.h
+++ b/components/cronet/url_request_context_config.h
@@ -7,16 +7,16 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "net/base/hash_value.h"
 #include "net/cert/cert_verifier.h"
 
 namespace base {
-class DictionaryValue;
 class SequencedTaskRunner;
 }  // namespace base
 
@@ -30,6 +30,8 @@
 
 // Common configuration parameters used by Cronet to configure
 // URLRequestContext.
+// TODO(mgersh): This shouldn't be a struct, and experimental option parsing
+// should be kept more separate from applying the configuration.
 struct URLRequestContextConfig {
   // Type of HTTP cache.
   // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net.impl
@@ -160,15 +162,23 @@
   const std::string cert_verifier_data;
 
   // App-provided list of servers that support QUIC.
-  ScopedVector<QuicHint> quic_hints;
+  std::vector<std::unique_ptr<QuicHint>> quic_hints;
 
   // The list of public key pins.
-  ScopedVector<Pkp> pkp_list;
+  std::vector<std::unique_ptr<Pkp>> pkp_list;
 
   // Experimental options that are recognized by the config parser.
-  std::unique_ptr<base::DictionaryValue> effective_experimental_options;
+  std::unique_ptr<base::DictionaryValue> effective_experimental_options =
+      nullptr;
 
  private:
+  // Parses experimental options and makes appropriate changes to settings in
+  // the URLRequestContextConfig and URLRequestContextBuilder.
+  void ParseAndSetExperimentalOptions(
+      net::URLRequestContextBuilder* context_builder,
+      net::NetLog* net_log,
+      const scoped_refptr<base::SequencedTaskRunner>& file_task_runner);
+
   DISALLOW_COPY_AND_ASSIGN(URLRequestContextConfig);
 };
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index 3e1b471..e43687a 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc
index 46ac490..69bffa7b 100644
--- a/components/download/internal/controller_impl.cc
+++ b/components/download/internal/controller_impl.cc
@@ -634,6 +634,8 @@
     model_->Remove(guid);
   }
 
+  if (callback.is_null())
+    return;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::Bind(callback, guid, result));
 }
diff --git a/components/download/internal/download_service_impl.cc b/components/download/internal/download_service_impl.cc
index f030b569..5a05885 100644
--- a/components/download/internal/download_service_impl.cc
+++ b/components/download/internal/download_service_impl.cc
@@ -4,6 +4,7 @@
 
 #include "components/download/internal/download_service_impl.h"
 
+#include "base/strings/string_util.h"
 #include "components/download/internal/controller.h"
 #include "components/download/internal/startup_status.h"
 #include "components/download/internal/stats.h"
@@ -47,24 +48,28 @@
 void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
   stats::LogServiceApiAction(download_params.client,
                              stats::ServiceApiAction::START_DOWNLOAD);
+  DCHECK_EQ(download_params.guid, base::ToUpperASCII(download_params.guid));
   controller_->StartDownload(download_params);
 }
 
 void DownloadServiceImpl::PauseDownload(const std::string& guid) {
   stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
                              stats::ServiceApiAction::PAUSE_DOWNLOAD);
+  DCHECK_EQ(guid, base::ToUpperASCII(guid));
   controller_->PauseDownload(guid);
 }
 
 void DownloadServiceImpl::ResumeDownload(const std::string& guid) {
   stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
                              stats::ServiceApiAction::RESUME_DOWNLOAD);
+  DCHECK_EQ(guid, base::ToUpperASCII(guid));
   controller_->ResumeDownload(guid);
 }
 
 void DownloadServiceImpl::CancelDownload(const std::string& guid) {
   stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
                              stats::ServiceApiAction::CANCEL_DOWNLOAD);
+  DCHECK_EQ(guid, base::ToUpperASCII(guid));
   controller_->CancelDownload(guid);
 }
 
@@ -73,6 +78,7 @@
     const SchedulingParams& params) {
   stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
                              stats::ServiceApiAction::CHANGE_CRITERIA);
+  DCHECK_EQ(guid, base::ToUpperASCII(guid));
   controller_->ChangeDownloadCriteria(guid, params);
 }
 
diff --git a/components/download/internal/download_service_impl_unittest.cc b/components/download/internal/download_service_impl_unittest.cc
index 579361b0..11c14b3 100644
--- a/components/download/internal/download_service_impl_unittest.cc
+++ b/components/download/internal/download_service_impl_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
 #include "components/download/internal/startup_status.h"
 #include "components/download/internal/test/download_params_utils.h"
 #include "components/download/internal/test/mock_controller.h"
@@ -63,6 +64,9 @@
 
 TEST_F(DownloadServiceImplTest, TestApiPassThrough) {
   DownloadParams params = test::BuildBasicDownloadParams();
+  // TODO(xingliu): Remove the limitation of upper case guid in
+  // |download_params|, see http://crbug.com/734818.
+  params.guid = base::ToUpperASCII(params.guid);
   SchedulingParams scheduling_params;
   scheduling_params.priority = SchedulingParams::Priority::UI;
 
diff --git a/components/download/internal/scheduler/scheduler_impl.cc b/components/download/internal/scheduler/scheduler_impl.cc
index ec9110e..9b5b34c 100644
--- a/components/download/internal/scheduler/scheduler_impl.cc
+++ b/components/download/internal/scheduler/scheduler_impl.cc
@@ -41,7 +41,6 @@
       config_(config),
       download_clients_(clients),
       current_client_index_(0) {
-  DCHECK(!download_clients_.empty());
   DCHECK(task_scheduler_);
 }
 
diff --git a/components/download/public/download_params.h b/components/download/public/download_params.h
index abd18771..7f54fca 100644
--- a/components/download/public/download_params.h
+++ b/components/download/public/download_params.h
@@ -131,6 +131,8 @@
   DownloadClient client;
 
   // A unique GUID that represents this download.  See |base::GenerateGUID()|.
+  // TODO(xingliu): guid in content download must be upper case, see
+  // http://crbug.com/734818.
   std::string guid;
 
   // A callback that will be notified if this download has been accepted and
diff --git a/components/download/public/download_service.h b/components/download/public/download_service.h
index e8d410b..fdf8ac5 100644
--- a/components/download/public/download_service.h
+++ b/components/download/public/download_service.h
@@ -75,7 +75,9 @@
 
   // Sends the download to the service.  A callback to
   // |DownloadParams::callback| will be triggered once the download has been
-  // persisted and saved in the service
+  // persisted and saved in the service.
+  // TODO(xingliu): Remove the limitation of upper case guid in
+  // |download_params|, see http://crbug.com/734818.
   virtual void StartDownload(const DownloadParams& download_params) = 0;
 
   // Allows any feature to pause or resume downloads at will.  Paused downloads
diff --git a/components/exo/notification_surface.cc b/components/exo/notification_surface.cc
index 91c13bc..f863e7a5 100644
--- a/components/exo/notification_surface.cc
+++ b/components/exo/notification_surface.cc
@@ -101,7 +101,6 @@
 }
 
 void NotificationSurface::OnSurfaceCommit() {
-  surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
   surface_->CommitSurfaceHierarchy();
 
   gfx::Rect bounds = window_->bounds();
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 2271212..ec34b5a4 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -276,7 +276,6 @@
 // SurfaceDelegate overrides:
 
 void Pointer::OnSurfaceCommit() {
-  surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
   surface_->CommitSurfaceHierarchy();
 
   // Capture new cursor to reflect result of commit.
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index d8cb82b1..54dc844 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -704,7 +704,6 @@
 // SurfaceDelegate overrides:
 
 void ShellSurface::OnSurfaceCommit() {
-  surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
   surface_->CommitSurfaceHierarchy();
 
   if (enabled() && !widget_) {
diff --git a/components/exo/sub_surface.cc b/components/exo/sub_surface.cc
index 76e7978e..1f8e2f30 100644
--- a/components/exo/sub_surface.cc
+++ b/components/exo/sub_surface.cc
@@ -96,7 +96,6 @@
   if (IsSurfaceSynchronized())
     return;
 
-  surface_->CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
   surface_->CommitSurfaceHierarchy();
 }
 
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 2a9bfb59..c83338c 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -441,7 +441,6 @@
   if (delegate_) {
     delegate_->OnSurfaceCommit();
   } else {
-    CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
     CommitSurfaceHierarchy();
   }
 
@@ -484,14 +483,10 @@
 
   UpdateSurface(false);
 
-  if (needs_commit_to_new_surface_) {
-    needs_commit_to_new_surface_ = false;
-    window_->layer()->SetFillsBoundsOpaquely(
-        !current_resource_has_alpha_ ||
-        state_.blend_mode == SkBlendMode::kSrc ||
-        state_.opaque_region.contains(
-            gfx::RectToSkIRect(gfx::Rect(content_size_))));
-  }
+  window_->layer()->SetFillsBoundsOpaquely(
+      !current_resource_has_alpha_ || state_.blend_mode == SkBlendMode::kSrc ||
+      state_.opaque_region.contains(
+          gfx::RectToSkIRect(gfx::Rect(content_size_))));
 
   // Reset damage.
   pending_damage_.setEmpty();
@@ -647,11 +642,6 @@
   return true;
 }
 
-void Surface::CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces() {
-  if (HasLayerHierarchyChanged())
-    SetSurfaceHierarchyNeedsCommitToNewSurfaces();
-}
-
 bool Surface::IsStylusOnly() {
   return window_->GetProperty(kStylusOnlyKey);
 }
@@ -751,24 +741,6 @@
   buffer_ = buffer;
 }
 
-bool Surface::HasLayerHierarchyChanged() const {
-  if (needs_commit_surface_hierarchy_ && has_pending_layer_changes_)
-    return true;
-
-  for (const auto& sub_surface_entry : pending_sub_surfaces_) {
-    if (sub_surface_entry.first->HasLayerHierarchyChanged())
-      return true;
-  }
-  return false;
-}
-
-void Surface::SetSurfaceHierarchyNeedsCommitToNewSurfaces() {
-  needs_commit_to_new_surface_ = true;
-  for (auto& sub_surface_entry : pending_sub_surfaces_) {
-    sub_surface_entry.first->SetSurfaceHierarchyNeedsCommitToNewSurfaces();
-  }
-}
-
 void Surface::UpdateResource(bool client_usage) {
   if (current_buffer_.buffer() &&
       current_buffer_.buffer()->ProduceTransferableResource(
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 0abd511..d0d5974 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -193,10 +193,6 @@
   // Called when the begin frame source has changed.
   void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
 
-  // Check whether this Surface and its children need to create new cc::Surface
-  // IDs for their contents next time they get new buffer contents.
-  void CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
-
   // Returns the active contents size.
   gfx::Size content_size() const { return content_size_; }
 
@@ -266,13 +262,6 @@
     return needs_commit_surface_hierarchy_;
   }
 
-  // Returns true if this surface or any child surface needs a commit and has
-  // has_pending_layer_changes_ true.
-  bool HasLayerHierarchyChanged() const;
-
-  // Sets that all children must create new cc::SurfaceIds for their contents.
-  void SetSurfaceHierarchyNeedsCommitToNewSurfaces();
-
   // Set SurfaceLayer contents to the current buffer.
   void SetSurfaceLayerContents(ui::Layer* layer);
 
@@ -300,11 +289,6 @@
   // buffer with the same size as the old shouldn't set this to true.
   bool has_pending_layer_changes_ = true;
 
-  // This is true if the next commit to this surface should put its contents
-  // into a new cc::SurfaceId. This allows for synchronization between Surface
-  // and layer changes.
-  bool needs_commit_to_new_surface_ = true;
-
   // This is the size of the last committed contents.
   gfx::Size content_size_;
 
diff --git a/components/offline_pages/core/archive_manager.cc b/components/offline_pages/core/archive_manager.cc
index cd817767..400a059 100644
--- a/components/offline_pages/core/archive_manager.cc
+++ b/components/offline_pages/core/archive_manager.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/offline_pages/core/archive_manager.h"
+
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/files/file_enumerator.h"
@@ -9,10 +11,10 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/offline_pages/core/archive_manager.h"
 
 namespace offline_pages {
 
@@ -22,7 +24,16 @@
     base::Callback<void(const ArchiveManager::StorageStats& storage_stats)>;
 
 void EnsureArchivesDirCreatedImpl(const base::FilePath& archives_dir) {
-  CHECK(base::CreateDirectory(archives_dir));
+  base::File::Error error = base::File::FILE_OK;
+  if (!base::DirectoryExists(archives_dir)) {
+    if (!base::CreateDirectoryAndGetError(archives_dir, &error)) {
+      LOG(ERROR) << "Failed to create offline pages archive directory: "
+                 << base::File::ErrorToString(error);
+    }
+    UMA_HISTOGRAM_ENUMERATION(
+        "OfflinePages.ArchiveManager.ArchiveDirsCreationResult", -error,
+        -base::File::FILE_ERROR_MAX);
+  }
 }
 
 void ExistsArchiveImpl(const base::FilePath& file_path,
diff --git a/components/offline_pages/core/archive_manager_unittest.cc b/components/offline_pages/core/archive_manager_unittest.cc
index 57f868a8..10ffeb6 100644
--- a/components/offline_pages/core/archive_manager_unittest.cc
+++ b/components/offline_pages/core/archive_manager_unittest.cc
@@ -10,9 +10,11 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/test/histogram_tester.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -53,6 +55,7 @@
   ArchiveManager::StorageStats last_storage_sizes() const {
     return last_storage_sizes_;
   }
+  base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
 
  private:
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
@@ -63,6 +66,7 @@
   CallbackStatus callback_status_;
   std::set<base::FilePath> last_archvie_paths_;
   ArchiveManager::StorageStats last_storage_sizes_;
+  std::unique_ptr<base::HistogramTester> histogram_tester_;
 };
 
 ArchiveManagerTest::ArchiveManagerTest()
@@ -74,6 +78,7 @@
 void ArchiveManagerTest::SetUp() {
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   ResetManager(temp_dir_.GetPath());
+  histogram_tester_.reset(new base::HistogramTester());
 }
 
 void ArchiveManagerTest::PumpLoop() {
@@ -117,6 +122,11 @@
   PumpLoop();
   EXPECT_EQ(CallbackStatus::CALLED_TRUE, callback_status());
   EXPECT_TRUE(base::PathExists(archive_dir));
+  histogram_tester()->ExpectUniqueSample(
+      "OfflinePages.ArchiveManager.ArchiveDirsCreationResult",
+      -base::File::Error::FILE_OK, 1);
+  histogram_tester()->ExpectTotalCount(
+      "OfflinePages.ArchiveManager.ArchiveDirsCreationResult", 1);
 
   // Try again when the file already exists.
   ResetResults();
@@ -125,6 +135,11 @@
   PumpLoop();
   EXPECT_EQ(CallbackStatus::CALLED_TRUE, callback_status());
   EXPECT_TRUE(base::PathExists(archive_dir));
+  histogram_tester()->ExpectUniqueSample(
+      "OfflinePages.ArchiveManager.ArchiveDirsCreationResult",
+      -base::File::Error::FILE_OK, 1);
+  histogram_tester()->ExpectTotalCount(
+      "OfflinePages.ArchiveManager.ArchiveDirsCreationResult", 1);
 }
 
 TEST_F(ArchiveManagerTest, ExistsArchive) {
diff --git a/components/offline_pages/core/offline_page_model_impl.cc b/components/offline_pages/core/offline_page_model_impl.cc
index 4c3bbdc..fc9ebe4 100644
--- a/components/offline_pages/core/offline_page_model_impl.cc
+++ b/components/offline_pages/core/offline_page_model_impl.cc
@@ -883,6 +883,11 @@
   ReportSavePageResultHistogramAfterSave(client_id, result);
   archive_manager_->GetStorageStats(
       base::Bind(&ReportStorageHistogramsAfterSave));
+  // No need to pass in a callback, since if the archive manager fails every
+  // time when creating an archive directory, there's nothing else to do other
+  // than fail every attempt to save a page.
+  if (result == SavePageResult::ARCHIVE_CREATION_FAILED)
+    archive_manager_->EnsureArchivesDirCreated(base::Bind([]() {}));
   callback.Run(result, offline_id);
 }
 
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.cc b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
index c1dddc0..f043c48a 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_factory.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver_factory.cc
@@ -75,9 +75,9 @@
 
 // static
 void ContentPasswordManagerDriverFactory::BindPasswordManagerDriver(
-    content::RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    autofill::mojom::PasswordManagerDriverRequest request) {
+    autofill::mojom::PasswordManagerDriverRequest request,
+    content::RenderFrameHost* render_frame_host) {
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   if (!web_contents)
@@ -100,9 +100,9 @@
 
 // static
 void ContentPasswordManagerDriverFactory::BindSensitiveInputVisibilityService(
-    content::RenderFrameHost* render_frame_host,
     const service_manager::BindSourceInfo& source_info,
-    blink::mojom::SensitiveInputVisibilityServiceRequest request) {
+    blink::mojom::SensitiveInputVisibilityServiceRequest request,
+    content::RenderFrameHost* render_frame_host) {
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
   if (!web_contents)
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.h b/components/password_manager/content/browser/content_password_manager_driver_factory.h
index 12c3aef..85fab1a 100644
--- a/components/password_manager/content/browser/content_password_manager_driver_factory.h
+++ b/components/password_manager/content/browser/content_password_manager_driver_factory.h
@@ -43,14 +43,14 @@
       content::WebContents* web_contents);
 
   static void BindPasswordManagerDriver(
-      content::RenderFrameHost* render_frame_host,
       const service_manager::BindSourceInfo& source_info,
-      autofill::mojom::PasswordManagerDriverRequest request);
+      autofill::mojom::PasswordManagerDriverRequest request,
+      content::RenderFrameHost* render_frame_host);
 
   static void BindSensitiveInputVisibilityService(
-      content::RenderFrameHost* render_frame_host,
       const service_manager::BindSourceInfo& source_info,
-      blink::mojom::SensitiveInputVisibilityServiceRequest request);
+      blink::mojom::SensitiveInputVisibilityServiceRequest request,
+      content::RenderFrameHost* render_frame_host);
 
   ContentPasswordManagerDriver* GetDriverForFrame(
       content::RenderFrameHost* render_frame_host);
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc
index fc3f5ca5..252fe150 100644
--- a/components/payments/content/payment_request_spec.cc
+++ b/components/payments/content/payment_request_spec.cc
@@ -42,21 +42,6 @@
   return std::string();
 }
 
-// Returns the card type associated with the given BasicCardType.
-autofill::CreditCard::CardType GetBasicCardType(
-    const mojom::BasicCardType& type) {
-  switch (type) {
-    case mojom::BasicCardType::CREDIT:
-      return autofill::CreditCard::CARD_TYPE_CREDIT;
-    case mojom::BasicCardType::DEBIT:
-      return autofill::CreditCard::CARD_TYPE_DEBIT;
-    case mojom::BasicCardType::PREPAID:
-      return autofill::CreditCard::CARD_TYPE_PREPAID;
-  }
-  NOTREACHED();
-  return autofill::CreditCard::CARD_TYPE_UNKNOWN;
-}
-
 }  // namespace
 
 const char kBasicCardMethodName[] = "basic-card";
@@ -174,41 +159,24 @@
 
     PaymentMethodData method_data;
     method_data.supported_methods = method_data_entry->supported_methods;
-
-    // Transfer the supported basic card networks (visa, amex) and types
-    // (credit, debit).
+    // Transfer the supported basic card networks.
+    std::vector<std::string> supported_networks;
     for (const mojom::BasicCardNetwork& network :
          method_data_entry->supported_networks) {
-      method_data.supported_networks.push_back(
-          GetBasicCardNetworkName(network));
+      supported_networks.push_back(GetBasicCardNetworkName(network));
     }
-    for (const mojom::BasicCardType& type :
-         method_data_entry->supported_types) {
-      autofill::CreditCard::CardType card_type = GetBasicCardType(type);
-      method_data.supported_types.insert(card_type);
-      supported_card_types_set_.insert(card_type);
-    }
+    method_data.supported_networks = std::move(supported_networks);
 
+    // TODO(crbug.com/708603): Add browser-side support for
+    // |method_data.supported_types|.
     method_data_vector.push_back(std::move(method_data));
   }
 
-  // TODO(rouslan): Parse card types (credit, debit, prepaid) in data_util, so
-  // iOS can use it as well. http://crbug.com/602665
   data_util::ParseBasicCardSupportedNetworks(method_data_vector,
                                              &supported_card_networks_,
                                              &basic_card_specified_networks_);
   supported_card_networks_set_.insert(supported_card_networks_.begin(),
                                       supported_card_networks_.end());
-
-  // Omitting the card types means all 3 card types are supported.
-  if (supported_card_types_set_.empty()) {
-    supported_card_types_set_.insert(autofill::CreditCard::CARD_TYPE_CREDIT);
-    supported_card_types_set_.insert(autofill::CreditCard::CARD_TYPE_DEBIT);
-    supported_card_types_set_.insert(autofill::CreditCard::CARD_TYPE_PREPAID);
-  }
-
-  // Let the user decide whether an unknown card type should be used.
-  supported_card_types_set_.insert(autofill::CreditCard::CARD_TYPE_UNKNOWN);
 }
 
 void PaymentRequestSpec::UpdateSelectedShippingOption(bool after_update) {
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h
index 9170efaf..c8fd2a6 100644
--- a/components/payments/content/payment_request_spec.h
+++ b/components/payments/content/payment_request_spec.h
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/strings/string16.h"
-#include "components/autofill/core/browser/credit_card.h"
 #include "components/payments/core/currency_formatter.h"
 #include "components/payments/core/payment_options_provider.h"
 #include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
@@ -83,10 +82,6 @@
       const {
     return stringified_method_data_;
   }
-  const std::set<autofill::CreditCard::CardType>& supported_card_types_set()
-      const {
-    return supported_card_types_set_;
-  }
   // Returns whether the |method_name| was specified as supported through the
   // "basic-card" payment method. If false, it means either the |method_name| is
   // not supported at all, or specified directly in supportedMethods.
@@ -162,8 +157,6 @@
   std::vector<std::string> supported_card_networks_;
   std::set<std::string> supported_card_networks_set_;
 
-  std::set<autofill::CreditCard::CardType> supported_card_types_set_;
-
   // Only the set of basic-card specified networks. NOTE: callers should use
   // |supported_card_networks_set_| to check merchant support.
   std::set<std::string> basic_card_specified_networks_;
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 740a4d6..47a068ec 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -77,10 +77,11 @@
 }
 
 bool PaymentRequestState::CanMakePayment() const {
-  for (const auto& instrument : available_instruments_) {
+  for (const std::unique_ptr<PaymentInstrument>& instrument :
+       available_instruments_) {
     if (instrument->IsValidForCanMakePayment()) {
       // AddAutofillPaymentInstrument() filters out available instruments based
-      // on supported card networks (visa, amex) and types (credit, debit).
+      // on supported card networks.
       DCHECK(spec_->supported_card_networks_set().find(
                  instrument->method_name()) !=
              spec_->supported_card_networks_set().end());
@@ -143,26 +144,15 @@
   std::string basic_card_network =
       autofill::data_util::GetPaymentRequestData(card.network())
           .basic_card_issuer_network;
-  if (!spec_->supported_card_networks_set().count(basic_card_network) ||
-      !spec_->supported_card_types_set().count(card.card_type())) {
+  if (!spec_->supported_card_networks_set().count(basic_card_network))
     return;
-  }
-
-  // The total number of card types: credit, debit, prepaid, unknown.
-  constexpr size_t kTotalNumberOfCardTypes = 4U;
-
-  // Whether the card type (credit, debit, prepaid) matches thetype that the
-  // merchant has requested exactly. This should be false for unknown card
-  // types, if the merchant cannot accept some card types.
-  bool matches_merchant_card_type_exactly =
-      card.card_type() != autofill::CreditCard::CARD_TYPE_UNKNOWN ||
-      spec_->supported_card_types_set().size() == kTotalNumberOfCardTypes;
 
   // AutofillPaymentInstrument makes a copy of |card| so it is effectively
   // owned by this object.
-  auto instrument = base::MakeUnique<AutofillPaymentInstrument>(
-      basic_card_network, card, matches_merchant_card_type_exactly,
-      shipping_profiles_, app_locale_, payment_request_delegate_);
+  std::unique_ptr<PaymentInstrument> instrument =
+      base::MakeUnique<AutofillPaymentInstrument>(
+          basic_card_network, card, shipping_profiles_, app_locale_,
+          payment_request_delegate_);
   available_instruments_.push_back(std::move(instrument));
 
   if (selected)
@@ -303,8 +293,7 @@
   auto first_complete_instrument =
       std::find_if(instruments.begin(), instruments.end(),
                    [](const std::unique_ptr<PaymentInstrument>& instrument) {
-                     return instrument->IsCompleteForPayment() &&
-                            instrument->IsExactlyMatchingMerchantRequest();
+                     return instrument->IsCompleteForPayment();
                    });
   selected_instrument_ = first_complete_instrument == instruments.end()
                              ? nullptr
diff --git a/components/payments/content/payment_response_helper_unittest.cc b/components/payments/content/payment_response_helper_unittest.cc
index 4d5d122..d21dac6 100644
--- a/components/payments/content/payment_response_helper_unittest.cc
+++ b/components/payments/content/payment_response_helper_unittest.cc
@@ -37,8 +37,8 @@
     visa_card.set_billing_address_id(address_.guid());
     visa_card.set_use_count(5u);
     autofill_instrument_ = base::MakeUnique<AutofillPaymentInstrument>(
-        "visa", visa_card, /*matches_merchant_card_type_exactly=*/true,
-        billing_addresses_, "en-US", &test_payment_request_delegate_);
+        "visa", visa_card, billing_addresses_, "en-US",
+        &test_payment_request_delegate_);
   }
   ~PaymentResponseHelperTest() override {}
 
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index 5ceb667..eaa3d41 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -86,7 +86,6 @@
     "payment_method_data_unittest.cc",
     "payment_request_data_util_unittest.cc",
     "payments_profile_comparator_unittest.cc",
-    "strings_util_unittest.cc",
     "subkey_requester_unittest.cc",
   ]
 
diff --git a/components/payments/core/autofill_payment_instrument.cc b/components/payments/core/autofill_payment_instrument.cc
index 2d935ea..82ff24d 100644
--- a/components/payments/core/autofill_payment_instrument.cc
+++ b/components/payments/core/autofill_payment_instrument.cc
@@ -25,7 +25,6 @@
 AutofillPaymentInstrument::AutofillPaymentInstrument(
     const std::string& method_name,
     const autofill::CreditCard& card,
-    bool matches_merchant_card_type_exactly,
     const std::vector<autofill::AutofillProfile*>& billing_profiles,
     const std::string& app_locale,
     PaymentRequestDelegate* payment_request_delegate)
@@ -35,7 +34,6 @@
               .icon_resource_id,
           PaymentInstrument::Type::AUTOFILL),
       credit_card_(card),
-      matches_merchant_card_type_exactly_(matches_merchant_card_type_exactly),
       billing_profiles_(billing_profiles),
       app_locale_(app_locale),
       delegate_(nullptr),
@@ -87,10 +85,6 @@
          autofill::CREDIT_CARD_EXPIRED;
 }
 
-bool AutofillPaymentInstrument::IsExactlyMatchingMerchantRequest() {
-  return matches_merchant_card_type_exactly_;
-}
-
 base::string16 AutofillPaymentInstrument::GetMissingInfoLabel() {
   return autofill::GetCompletionMessageForCard(
       autofill::GetCompletionStatusForCard(credit_card_, app_locale_,
diff --git a/components/payments/core/autofill_payment_instrument.h b/components/payments/core/autofill_payment_instrument.h
index fc4243e..6df075f 100644
--- a/components/payments/core/autofill_payment_instrument.h
+++ b/components/payments/core/autofill_payment_instrument.h
@@ -33,7 +33,6 @@
   AutofillPaymentInstrument(
       const std::string& method_name,
       const autofill::CreditCard& card,
-      bool matches_merchant_card_type_exactly,
       const std::vector<autofill::AutofillProfile*>& billing_profiles,
       const std::string& app_locale,
       PaymentRequestDelegate* payment_request_delegate);
@@ -42,7 +41,6 @@
   // PaymentInstrument:
   void InvokePaymentApp(PaymentInstrument::Delegate* delegate) override;
   bool IsCompleteForPayment() override;
-  bool IsExactlyMatchingMerchantRequest() override;
   base::string16 GetMissingInfoLabel() override;
   bool IsValidForCanMakePayment() override;
   void RecordUse() override;
@@ -67,13 +65,6 @@
 
   // A copy of the card is owned by this object.
   autofill::CreditCard credit_card_;
-
-  // Whether the card type (credit, debit, prepaid) matches the merchant's
-  // requested card type exactly. If the merchant accepts all card types, then
-  // this variable is always "true". If the merchant accepts only a subset of
-  // the card types, then this variable is "false" for unknown card types.
-  const bool matches_merchant_card_type_exactly_;
-
   // Not owned by this object, should outlive this.
   const std::vector<autofill::AutofillProfile*>& billing_profiles_;
 
diff --git a/components/payments/core/autofill_payment_instrument_unittest.cc b/components/payments/core/autofill_payment_instrument_unittest.cc
index 117d587..7f84726 100644
--- a/components/payments/core/autofill_payment_instrument_unittest.cc
+++ b/components/payments/core/autofill_payment_instrument_unittest.cc
@@ -164,10 +164,8 @@
 
 // A valid local credit card is a valid instrument for payment.
 TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment) {
-  AutofillPaymentInstrument instrument(
-      "visa", local_credit_card(),
-      /*matches_merchant_card_type_exactly=*/true, billing_profiles(), "en-US",
-      nullptr);
+  AutofillPaymentInstrument instrument("visa", local_credit_card(),
+                                       billing_profiles(), "en-US", nullptr);
   EXPECT_TRUE(instrument.IsCompleteForPayment());
   EXPECT_TRUE(instrument.GetMissingInfoLabel().empty());
 }
@@ -176,9 +174,8 @@
 TEST_F(AutofillPaymentInstrumentTest, IsCompleteForPayment_Expired) {
   autofill::CreditCard& card = local_credit_card();
   card.SetExpirationYear(2016);  // Expired.
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_TRUE(instrument.IsCompleteForPayment());
   EXPECT_EQ(base::string16(), instrument.GetMissingInfoLabel());
 }
@@ -189,9 +186,8 @@
   card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
                base::ASCIIToUTF16(""), "en-US");
   base::string16 missing_info;
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsCompleteForPayment());
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_NAME_ON_CARD_REQUIRED),
             instrument.GetMissingInfoLabel());
@@ -202,9 +198,8 @@
   autofill::CreditCard& card = local_credit_card();
   card.SetNumber(base::ASCIIToUTF16(""));
   base::string16 missing_info;
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsCompleteForPayment());
   EXPECT_EQ(l10n_util::GetStringUTF16(
                 IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
@@ -217,9 +212,8 @@
   autofill::CreditCard& card = local_credit_card();
   card.set_billing_address_id("");
   base::string16 missing_info;
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsCompleteForPayment());
   EXPECT_EQ(
       l10n_util::GetStringUTF16(IDS_PAYMENTS_CARD_BILLING_ADDRESS_REQUIRED),
@@ -233,9 +227,8 @@
   autofill::CreditCard& card = local_credit_card();
   card.set_billing_address_id("InvalidBillingAddressId");
   base::string16 missing_info;
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsCompleteForPayment());
   EXPECT_EQ(
       l10n_util::GetStringUTF16(IDS_PAYMENTS_CARD_BILLING_ADDRESS_REQUIRED),
@@ -250,9 +243,8 @@
   card.SetNumber(base::ASCIIToUTF16(""));
   card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
                base::ASCIIToUTF16(""), "en-US");
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsCompleteForPayment());
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAYMENTS_MORE_INFORMATION_REQUIRED),
             instrument.GetMissingInfoLabel());
@@ -263,9 +255,8 @@
   autofill::CreditCard card = autofill::test::GetMaskedServerCard();
   ASSERT_GT(billing_profiles().size(), 0UL);
   card.set_billing_address_id(billing_profiles()[0]->guid());
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_TRUE(instrument.IsCompleteForPayment());
   EXPECT_TRUE(instrument.GetMissingInfoLabel().empty());
 }
@@ -276,9 +267,8 @@
   ASSERT_GT(billing_profiles().size(), 0UL);
   card.set_billing_address_id(billing_profiles()[0]->guid());
   card.SetExpirationYear(2016);  // Expired.
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_TRUE(instrument.IsCompleteForPayment());
   EXPECT_EQ(base::string16(), instrument.GetMissingInfoLabel());
 }
@@ -287,9 +277,8 @@
 TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_Minimal) {
   autofill::CreditCard& card = local_credit_card();
   card.SetExpirationYear(2016);  // Expired.
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_TRUE(instrument.IsValidForCanMakePayment());
 }
 
@@ -297,9 +286,8 @@
 TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_MaskedCard) {
   autofill::CreditCard card = autofill::test::GetMaskedServerCard();
   card.SetExpirationYear(2016);  // Expired.
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_TRUE(instrument.IsValidForCanMakePayment());
 }
 
@@ -308,9 +296,8 @@
   autofill::CreditCard& card = local_credit_card();
   card.SetInfo(autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
                base::ASCIIToUTF16(""), "en-US");
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsValidForCanMakePayment());
 }
 
@@ -318,9 +305,8 @@
 TEST_F(AutofillPaymentInstrumentTest, IsValidForCanMakePayment_NoNumber) {
   autofill::CreditCard& card = local_credit_card();
   card.SetNumber(base::ASCIIToUTF16(""));
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", nullptr);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", nullptr);
   EXPECT_FALSE(instrument.IsValidForCanMakePayment());
 }
 
@@ -334,9 +320,8 @@
 
   autofill::CreditCard& card = local_credit_card();
   card.SetNumber(base::ASCIIToUTF16(""));
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", &delegate);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", &delegate);
 
   FakePaymentInstrumentDelegate instrument_delegate;
 
@@ -363,9 +348,8 @@
 
   autofill::CreditCard& card = local_credit_card();
   card.SetNumber(base::ASCIIToUTF16(""));
-  AutofillPaymentInstrument instrument(
-      "visa", card, /*matches_merchant_card_type_exactly=*/true,
-      billing_profiles(), "en-US", &delegate);
+  AutofillPaymentInstrument instrument("visa", card, billing_profiles(),
+                                       "en-US", &delegate);
 
   FakePaymentInstrumentDelegate instrument_delegate;
 
diff --git a/components/payments/core/payment_instrument.h b/components/payments/core/payment_instrument.h
index f189c02..6da0769 100644
--- a/components/payments/core/payment_instrument.h
+++ b/components/payments/core/payment_instrument.h
@@ -39,10 +39,6 @@
   // Returns whether the instrument is complete to be used as a payment method
   // without further editing.
   virtual bool IsCompleteForPayment() = 0;
-  // Returns whether the instrument is exactly matching all filters provided by
-  // the merchant. For example, this can return "false" for unknown card types,
-  // if the merchant requested only debit cards.
-  virtual bool IsExactlyMatchingMerchantRequest() = 0;
   // Returns a message to indicate to the user what's missing for the instrument
   // to be complete for payment.
   virtual base::string16 GetMissingInfoLabel() = 0;
diff --git a/components/payments/core/payment_method_data.cc b/components/payments/core/payment_method_data.cc
index b0bb839..2ea818e 100644
--- a/components/payments/core/payment_method_data.cc
+++ b/components/payments/core/payment_method_data.cc
@@ -20,27 +20,6 @@
 static const char kSupportedNetworks[] = "supportedNetworks";
 static const char kSupportedTypes[] = "supportedTypes";
 
-// Converts |supported_type| to |card_type| and returns true on success.
-bool ConvertCardTypeStringToEnum(const std::string& supported_type,
-                                 autofill::CreditCard::CardType* card_type) {
-  if (supported_type == "credit") {
-    *card_type = autofill::CreditCard::CARD_TYPE_CREDIT;
-    return true;
-  }
-
-  if (supported_type == "debit") {
-    *card_type = autofill::CreditCard::CARD_TYPE_DEBIT;
-    return true;
-  }
-
-  if (supported_type == "prepaid") {
-    *card_type = autofill::CreditCard::CARD_TYPE_PREPAID;
-    return true;
-  }
-
-  return false;
-}
-
 }  // namespace
 
 PaymentMethodData::PaymentMethodData() {}
@@ -105,10 +84,7 @@
             !base::IsStringASCII(supported_type)) {
           return false;
         }
-        autofill::CreditCard::CardType card_type =
-            autofill::CreditCard::CARD_TYPE_UNKNOWN;
-        if (ConvertCardTypeStringToEnum(supported_type, &card_type))
-          this->supported_types.insert(card_type);
+        this->supported_types.push_back(supported_type);
       }
     }
   }
diff --git a/components/payments/core/payment_method_data.h b/components/payments/core/payment_method_data.h
index f0ce9237..5bc7241 100644
--- a/components/payments/core/payment_method_data.h
+++ b/components/payments/core/payment_method_data.h
@@ -6,12 +6,9 @@
 #define COMPONENTS_PAYMENTS_CORE_PAYMENT_METHOD_DATA_H_
 
 #include <memory>
-#include <set>
 #include <string>
 #include <vector>
 
-#include "components/autofill/core/browser/credit_card.h"
-
 namespace base {
 class DictionaryValue;
 }
@@ -44,7 +41,7 @@
   // When the methods include "basic-card", a list of networks and types that
   // are supported.
   std::vector<std::string> supported_networks;
-  std::set<autofill::CreditCard::CardType> supported_types;
+  std::vector<std::string> supported_types;
 };
 
 }  // namespace payments
diff --git a/components/payments/core/payment_method_data_unittest.cc b/components/payments/core/payment_method_data_unittest.cc
index b44a231..a20e283 100644
--- a/components/payments/core/payment_method_data_unittest.cc
+++ b/components/payments/core/payment_method_data_unittest.cc
@@ -12,14 +12,20 @@
 // Tests the success case when populating a PaymentMethodData from a dictionary.
 TEST(PaymentMethodData, FromDictionaryValueSuccess) {
   PaymentMethodData expected;
-  expected.supported_methods.push_back("visa");
-  expected.supported_methods.push_back("basic-card");
+  std::vector<std::string> supported_methods;
+  supported_methods.push_back("visa");
+  supported_methods.push_back("basic-card");
+  expected.supported_methods = supported_methods;
   expected.data =
       "{\"supportedNetworks\":[\"mastercard\"],"
       "\"supportedTypes\":[\"debit\",\"credit\"]}";
-  expected.supported_networks.push_back("mastercard");
-  expected.supported_types.insert(autofill::CreditCard::CARD_TYPE_DEBIT);
-  expected.supported_types.insert(autofill::CreditCard::CARD_TYPE_CREDIT);
+  std::vector<std::string> supported_networks;
+  supported_networks.push_back("mastercard");
+  expected.supported_networks = supported_networks;
+  std::vector<std::string> supported_types;
+  supported_types.push_back("debit");
+  supported_types.push_back("credit");
+  expected.supported_types = supported_types;
 
   base::DictionaryValue method_data_dict;
   std::unique_ptr<base::ListValue> supported_methods_list(new base::ListValue);
@@ -91,11 +97,13 @@
   method_data2.supported_networks = supported_networks1;
   EXPECT_EQ(method_data1, method_data2);
 
-  method_data1.supported_types = {autofill::CreditCard::CARD_TYPE_UNKNOWN};
+  std::vector<std::string> supported_types1{"credit"};
+  method_data1.supported_types = supported_types1;
   EXPECT_NE(method_data1, method_data2);
-  method_data2.supported_types = {autofill::CreditCard::CARD_TYPE_DEBIT};
+  std::vector<std::string> supported_types2{"debit"};
+  method_data2.supported_types = supported_types2;
   EXPECT_NE(method_data1, method_data2);
-  method_data2.supported_types = method_data1.supported_types;
+  method_data2.supported_types = supported_types1;
   EXPECT_EQ(method_data1, method_data2);
 }
 
diff --git a/components/payments/core/strings_util.cc b/components/payments/core/strings_util.cc
index bc5fad06..165d2b22 100644
--- a/components/payments/core/strings_util.cc
+++ b/components/payments/core/strings_util.cc
@@ -13,27 +13,6 @@
 #include "ui/base/l10n/l10n_util.h"
 
 namespace payments {
-namespace {
-
-constexpr size_t kNone = 0;
-constexpr size_t kCredit = 1;
-constexpr size_t kDebit = 2;
-constexpr size_t kPrepaid = 4;
-
-size_t getCardTypeBitmask(
-    const std::set<autofill::CreditCard::CardType>& types) {
-  return (types.find(autofill::CreditCard::CARD_TYPE_CREDIT) != types.end()
-              ? kCredit
-              : kNone) |
-         (types.find(autofill::CreditCard::CARD_TYPE_DEBIT) != types.end()
-              ? kDebit
-              : kNone) |
-         (types.find(autofill::CreditCard::CARD_TYPE_PREPAID) != types.end()
-              ? kPrepaid
-              : kNone);
-}
-
-}  // namespace
 
 base::string16 GetShippingAddressLabelFormAutofillProfile(
     const autofill::AutofillProfile& profile,
@@ -120,47 +99,4 @@
   }
 }
 
-base::string16 GetAcceptedCardTypesText(
-    const std::set<autofill::CreditCard::CardType>& types) {
-  int string_ids[8];
-
-  string_ids[kNone] = IDS_PAYMENTS_ACCEPTED_CARDS_LABEL;
-  string_ids[kCredit | kDebit | kPrepaid] = IDS_PAYMENTS_ACCEPTED_CARDS_LABEL;
-
-  string_ids[kCredit] = IDS_PAYMENTS_ACCEPTED_CREDIT_CARDS_LABEL;
-  string_ids[kDebit] = IDS_PAYMENTS_ACCEPTED_DEBIT_CARDS_LABEL;
-  string_ids[kPrepaid] = IDS_PAYMENTS_ACCEPTED_PREPAID_CARDS_LABEL;
-
-  string_ids[kCredit | kDebit] = IDS_PAYMENTS_ACCEPTED_CREDIT_DEBIT_CARDS_LABEL;
-  string_ids[kCredit | kPrepaid] =
-      IDS_PAYMENTS_ACCEPTED_CREDIT_PREPAID_CARDS_LABEL;
-  string_ids[kDebit | kPrepaid] =
-      IDS_PAYMENTS_ACCEPTED_DEBIT_PREPAID_CARDS_LABEL;
-
-  return l10n_util::GetStringUTF16(string_ids[getCardTypeBitmask(types)]);
-}
-
-base::string16 GetCardTypesAreAcceptedText(
-    const std::set<autofill::CreditCard::CardType>& types) {
-  int string_ids[8];
-
-  string_ids[kNone] = 0;
-  string_ids[kCredit | kDebit | kPrepaid] = 0;
-
-  string_ids[kCredit] = IDS_PAYMENTS_CREDIT_CARDS_ARE_ACCEPTED_LABEL;
-  string_ids[kDebit] = IDS_PAYMENTS_DEBIT_CARDS_ARE_ACCEPTED_LABEL;
-  string_ids[kPrepaid] = IDS_PAYMENTS_PREPAID_CARDS_ARE_ACCEPTED_LABEL;
-
-  string_ids[kCredit | kDebit] =
-      IDS_PAYMENTS_CREDIT_DEBIT_CARDS_ARE_ACCEPTED_LABEL;
-  string_ids[kCredit | kPrepaid] =
-      IDS_PAYMENTS_CREDIT_PREPAID_CARDS_ARE_ACCEPTED_LABEL;
-  string_ids[kDebit | kPrepaid] =
-      IDS_PAYMENTS_DEBIT_PREPAID_CARDS_ARE_ACCEPTED_LABEL;
-
-  int string_id = string_ids[getCardTypeBitmask(types)];
-  return string_id == 0 ? base::string16()
-                        : l10n_util::GetStringUTF16(string_id);
-}
-
 }  // namespace payments
diff --git a/components/payments/core/strings_util.h b/components/payments/core/strings_util.h
index db084f40..c693d29 100644
--- a/components/payments/core/strings_util.h
+++ b/components/payments/core/strings_util.h
@@ -5,11 +5,9 @@
 #ifndef COMPONENTS_PAYMENTS_CORE_STRINGS_UTIL_H_
 #define COMPONENTS_PAYMENTS_CORE_STRINGS_UTIL_H_
 
-#include <set>
 #include <string>
 
 #include "base/strings/string16.h"
-#include "components/autofill/core/browser/credit_card.h"
 #include "components/payments/core/payment_options_provider.h"
 
 namespace autofill {
@@ -43,19 +41,6 @@
 base::string16 GetShippingOptionSectionString(
     PaymentShippingType shipping_type);
 
-// Returns the label "Accepted cards" that is customized based on the
-// accepted card |types|. For example, "Accepted debit cards". If |types| is
-// empty or contains all possible values, then returns the generic "Accepted
-// cards" string.
-base::string16 GetAcceptedCardTypesText(
-    const std::set<autofill::CreditCard::CardType>& types);
-
-// Returns the label "Cards are accepted" that is customized based on the
-// accepted card |types|. For example, "Debit cards are accepted". If |types| is
-// empty or contains all possible values, then returns an empty string.
-base::string16 GetCardTypesAreAcceptedText(
-    const std::set<autofill::CreditCard::CardType>& types);
-
 }  // namespace payments
 
 #endif  // COMPONENTS_PAYMENTS_CORE_STRINGS_UTIL_H_
diff --git a/components/payments/core/strings_util_unittest.cc b/components/payments/core/strings_util_unittest.cc
deleted file mode 100644
index 7aebf44..0000000
--- a/components/payments/core/strings_util_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/payments/core/strings_util.h"
-
-#include <string>
-#include <vector>
-
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace payments {
-namespace {
-
-using CardType = ::autofill::CreditCard::CardType;
-
-constexpr CardType CREDIT = ::autofill::CreditCard::CARD_TYPE_CREDIT;
-constexpr CardType DEBIT = ::autofill::CreditCard::CARD_TYPE_DEBIT;
-constexpr CardType PREPAID = ::autofill::CreditCard::CARD_TYPE_PREPAID;
-constexpr CardType UNKNOWN = ::autofill::CreditCard::CARD_TYPE_UNKNOWN;
-
-}  // namespace
-
-TEST(StringsUtilTest, GetAcceptedCardTypesText) {
-  static const struct {
-    std::vector<CardType> card_types;
-    const char* const expected_text;
-  } kTestCases[] = {
-      {std::vector<CardType>(), "Accepted cards"},
-      {{UNKNOWN}, "Accepted cards"},
-      {{CREDIT}, "Accepted credit cards"},
-      {{DEBIT}, "Accepted debit cards"},
-      {{PREPAID}, "Accepted prepaid cards"},
-      {{CREDIT, DEBIT}, "Accepted credit and debit cards"},
-      {{CREDIT, PREPAID}, "Accepted credit and prepaid cards"},
-      {{DEBIT, PREPAID}, "Accepted debit and prepaid cards"},
-      {{CREDIT, DEBIT, PREPAID}, "Accepted cards"},
-  };
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
-    EXPECT_EQ(
-        base::UTF8ToUTF16(kTestCases[i].expected_text),
-        GetAcceptedCardTypesText(std::set<CardType>(
-            kTestCases[i].card_types.begin(), kTestCases[i].card_types.end())));
-  }
-}
-
-TEST(StringsUtilTest, GetCardTypesAreAcceptedText) {
-  static const struct {
-    std::vector<CardType> card_types;
-    const char* const expected_text;
-  } kTestCases[] = {
-      {std::vector<CardType>(), ""},
-      {{UNKNOWN}, ""},
-      {{CREDIT}, "Credit cards are accepted."},
-      {{DEBIT}, "Debit cards are accepted."},
-      {{PREPAID}, "Prepaid cards are accepted."},
-      {{CREDIT, DEBIT}, "Credit and debit cards are accepted."},
-      {{CREDIT, PREPAID}, "Credit and prepaid cards are accepted."},
-      {{DEBIT, PREPAID}, "Debit and prepaid cards are accepted."},
-      {{CREDIT, DEBIT, PREPAID}, ""},
-  };
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
-    EXPECT_EQ(
-        base::UTF8ToUTF16(kTestCases[i].expected_text),
-        GetCardTypesAreAcceptedText(std::set<CardType>(
-            kTestCases[i].card_types.begin(), kTestCases[i].card_types.end())));
-  }
-}
-
-}  // namespace payments
diff --git a/components/payments_strings.grdp b/components/payments_strings.grdp
index 6a796b6..40cf5f4a 100644
--- a/components/payments_strings.grdp
+++ b/components/payments_strings.grdp
@@ -16,45 +16,9 @@
   <message name="IDS_PAYMENTS_SAVE_CARD_TO_DEVICE_CHECKBOX" desc="The label for the checkbox that enables the user to save a credit card to their device, for example, on their phone." formatter_data="android_java">
     Save this card to this device
   </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_CARDS_LABEL" desc="The title for the section that displays the card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
+  <message name="IDS_PAYMENTS_ACCEPTED_CARDS_LABEL" desc="The title for the section that displays the credit card types that the merchant accepts. Below the title, we show a row of icons indicating the accepted cards (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
     Accepted cards
   </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_CREDIT_CARDS_LABEL" desc="The title for the section that displays the credit card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted credit card networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted credit cards
-  </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_DEBIT_CARDS_LABEL" desc="The title for the section that displays the debit card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted debit card networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted debit cards
-  </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_PREPAID_CARDS_LABEL" desc="The title for the section that displays the prepaid card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted prepaid card networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted prepaid cards
-  </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_CREDIT_DEBIT_CARDS_LABEL" desc="The title for the section that displays the credit and debit card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted credit and debit cards
-  </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_CREDIT_PREPAID_CARDS_LABEL" desc="The title for the section that displays the credit and prepaid card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted credit and prepaid cards
-  </message>
-  <message name="IDS_PAYMENTS_ACCEPTED_DEBIT_PREPAID_CARDS_LABEL" desc="The title for the section that displays the debit and prepaid card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted networks (Visa icon, Mastercard icon, etc.)." formatter_data="android_java">
-    Accepted debit and prepaid cards
-  </message>
-  <message name="IDS_PAYMENTS_CREDIT_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's credit cards that the merchant accepts." formatter_data="android_java">
-    Credit cards are accepted.
-  </message>
-  <message name="IDS_PAYMENTS_DEBIT_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's debit cards that the merchant accepts." formatter_data="android_java">
-    Debit cards are accepted.
-  </message>
-  <message name="IDS_PAYMENTS_PREPAID_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's prepaid cards that the merchant accepts." formatter_data="android_java">
-    Prepaid cards are accepted.
-  </message>
-  <message name="IDS_PAYMENTS_CREDIT_DEBIT_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's credit and debit cards that the merchant accepts." formatter_data="android_java">
-    Credit and debit cards are accepted.
-  </message>
-  <message name="IDS_PAYMENTS_CREDIT_PREPAID_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's credit and prepaid cards that the merchant accepts." formatter_data="android_java">
-    Credit and prepaid cards are accepted.
-  </message>
-  <message name="IDS_PAYMENTS_DEBIT_PREPAID_CARDS_ARE_ACCEPTED_LABEL" desc="A message for the section that displays user's debit and prepaid cards that the merchant accepts." formatter_data="android_java">
-    Debit and prepaid cards are accepted.
-  </message>
   <message name="IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL" desc="The title for the section that lets the user select the method of payment." formatter_data="android_java">
     Payment method
   </message>
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc
index d88577c..00bbedf 100644
--- a/components/previews/core/previews_features.cc
+++ b/components/previews/core/previews_features.cc
@@ -15,5 +15,9 @@
 const base::Feature kClientLoFi{"ClientLoFi",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables the Stale Previews timestamp on Previews infobars.
+const base::Feature kStalePreviewsTimestamp{"StalePreviewsTimestamp",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace previews
diff --git a/components/previews/core/previews_features.h b/components/previews/core/previews_features.h
index 2225bfd5..e83f960 100644
--- a/components/previews/core/previews_features.h
+++ b/components/previews/core/previews_features.h
@@ -12,6 +12,7 @@
 
 extern const base::Feature kOfflinePreviews;
 extern const base::Feature kClientLoFi;
+extern const base::Feature kStalePreviewsTimestamp;
 
 }  // namespace features
 }  // namespace previews
diff --git a/components/sync/base/data_type_histogram.cc b/components/sync/base/data_type_histogram.cc
index b8be026..45f563e 100644
--- a/components/sync/base/data_type_histogram.cc
+++ b/components/sync/base/data_type_histogram.cc
@@ -4,10 +4,23 @@
 
 #include "components/sync/base/data_type_histogram.h"
 
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/sparse_histogram.h"
 
+const char kModelTypeMemoryHistogramPrefix[] = "Sync.ModelTypeMemoryKB.";
+
 void SyncRecordDatatypeBin(const std::string& name, int sample, int value) {
   base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
       name, base::HistogramBase::kUmaTargetedHistogramFlag);
   histogram->AddCount(sample, value);
 }
+
+void SyncRecordMemoryKbHistogram(const std::string& histogram_name_prefix,
+                                 syncer::ModelType model_type,
+                                 size_t value) {
+  std::string type_string;
+  if (RealModelTypeToNotificationType(model_type, &type_string)) {
+    std::string full_histogram_name = histogram_name_prefix + type_string;
+    base::UmaHistogramCounts1M(full_histogram_name, value / 1024);
+  }
+}
diff --git a/components/sync/base/data_type_histogram.h b/components/sync/base/data_type_histogram.h
index 642c8848..09cc6f3 100644
--- a/components/sync/base/data_type_histogram.h
+++ b/components/sync/base/data_type_histogram.h
@@ -11,12 +11,21 @@
 #include "base/time/time.h"
 #include "components/sync/base/model_type.h"
 
+// Prefix for histogram recording datatype's memory usage.
+extern const char kModelTypeMemoryHistogramPrefix[];
+
 // This function adds |value| to |sample| bucket of histogram |name|. |value|
 // should be greater or equal to 1 and |name| can be variable. DataTypes are
 // mapped to proper |sample| bucket by using ModelTypeToHistogramInt() function.
 // So different DataTypes play the role of different buckets in this histogram.
 void SyncRecordDatatypeBin(const std::string& name, int sample, int value);
 
+// Converts memory size |value| into kilobytes and records it into |model_type|
+// related histogram with prefix |histogram_name_prefix|.
+void SyncRecordMemoryKbHistogram(const std::string& histogram_name_prefix,
+                                 syncer::ModelType model_type,
+                                 size_t value);
+
 // For now, this just implements UMA_HISTOGRAM_LONG_TIMES. This can be adjusted
 // if we feel the min, max, or bucket count amount are not appropriate.
 #define SYNC_FREQ_HISTOGRAM(name, time)                                        \
diff --git a/components/sync/driver/data_type_controller.h b/components/sync/driver/data_type_controller.h
index 7f9aecc..8fd7bd8 100644
--- a/components/sync/driver/data_type_controller.h
+++ b/components/sync/driver/data_type_controller.h
@@ -162,6 +162,9 @@
   // Used to display entity counts in chrome://sync-internals.
   virtual void GetStatusCounters(const StatusCountersCallback& callback) = 0;
 
+  // Estimates memory usage of type and records it into histogram.
+  virtual void RecordMemoryUsageHistogram() = 0;
+
  protected:
   explicit DataTypeController(ModelType type);
 
diff --git a/components/sync/driver/directory_data_type_controller.cc b/components/sync/driver/directory_data_type_controller.cc
index a03ee3d..3b2b879 100644
--- a/components/sync/driver/directory_data_type_controller.cc
+++ b/components/sync/driver/directory_data_type_controller.cc
@@ -9,6 +9,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "components/sync/base/data_type_histogram.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/engine/model_type_configurer.h"
 #include "components/sync/syncable/syncable_read_transaction.h"
@@ -83,6 +84,14 @@
   callback.Run(type(), counters);
 }
 
+void DirectoryDataTypeController::RecordMemoryUsageHistogram() {
+  syncer::syncable::Directory* directory =
+      sync_client_->GetSyncService()->GetUserShare()->directory.get();
+  size_t memory_usage = directory->EstimateMemoryUsageByType(type());
+  SyncRecordMemoryKbHistogram(kModelTypeMemoryHistogramPrefix, type(),
+                              memory_usage);
+}
+
 // static
 std::unique_ptr<base::ListValue>
 DirectoryDataTypeController::GetAllNodesForTypeFromDirectory(
diff --git a/components/sync/driver/directory_data_type_controller.h b/components/sync/driver/directory_data_type_controller.h
index a521be1d..7c3f523 100644
--- a/components/sync/driver/directory_data_type_controller.h
+++ b/components/sync/driver/directory_data_type_controller.h
@@ -49,6 +49,7 @@
 
   void GetAllNodes(const AllNodesCallback& callback) override;
   void GetStatusCounters(const StatusCountersCallback& callback) override;
+  void RecordMemoryUsageHistogram() override;
 
   // Returns a ListValue representing all nodes for a specified type by querying
   // the directory.
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc
index 8e98059..5f67856 100644
--- a/components/sync/driver/model_type_controller.cc
+++ b/components/sync/driver/model_type_controller.cc
@@ -236,6 +236,11 @@
                  base::Bind(&ModelTypeDebugInfo::GetStatusCounters, callback));
 }
 
+void ModelTypeController::RecordMemoryUsageHistogram() {
+  PostBridgeTask(FROM_HERE,
+                 base::Bind(&ModelTypeDebugInfo::RecordMemoryUsageHistogram));
+}
+
 void ModelTypeController::ReportModelError(const ModelError& error) {
   DCHECK(CalledOnValidThread());
   LoadModelsDone(UNRECOVERABLE_ERROR,
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h
index 0e9edd6..496c418 100644
--- a/components/sync/driver/model_type_controller.h
+++ b/components/sync/driver/model_type_controller.h
@@ -50,6 +50,7 @@
   State state() const override;
   void GetAllNodes(const AllNodesCallback& callback) override;
   void GetStatusCounters(const StatusCountersCallback& callback) override;
+  void RecordMemoryUsageHistogram() override;
 
  private:
   void RecordStartFailure(ConfigureResult result) const;
diff --git a/components/sync/driver/proxy_data_type_controller.cc b/components/sync/driver/proxy_data_type_controller.cc
index 08d3a953..837145b 100644
--- a/components/sync/driver/proxy_data_type_controller.cc
+++ b/components/sync/driver/proxy_data_type_controller.cc
@@ -85,4 +85,6 @@
   callback.Run(type(), counters);
 }
 
+void ProxyDataTypeController::RecordMemoryUsageHistogram() {}
+
 }  // namespace syncer
diff --git a/components/sync/driver/proxy_data_type_controller.h b/components/sync/driver/proxy_data_type_controller.h
index 2036f2a..93b3c13 100644
--- a/components/sync/driver/proxy_data_type_controller.h
+++ b/components/sync/driver/proxy_data_type_controller.h
@@ -35,6 +35,7 @@
   void DeactivateDataType(ModelTypeConfigurer* configurer) override;
   void GetAllNodes(const AllNodesCallback& callback) override;
   void GetStatusCounters(const StatusCountersCallback& callback) override;
+  void RecordMemoryUsageHistogram() override;
 
  private:
   State state_;
diff --git a/components/sync/model/model_type_debug_info.cc b/components/sync/model/model_type_debug_info.cc
index f2f1dfd..58887cc 100644
--- a/components/sync/model/model_type_debug_info.cc
+++ b/components/sync/model/model_type_debug_info.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "components/sync/base/data_type_histogram.h"
 #include "components/sync/model_impl/processor_entity_tracker.h"
 #include "components/sync/protocol/proto_value_conversions.h"
 
@@ -59,6 +60,15 @@
   }
 }
 
+// static
+void ModelTypeDebugInfo::RecordMemoryUsageHistogram(
+    ModelTypeSyncBridge* bridge) {
+  SharedModelTypeProcessor* processor = GetProcessorFromBridge(bridge);
+  size_t memory_usage = processor->EstimateMemoryUsage();
+  SyncRecordMemoryKbHistogram(kModelTypeMemoryHistogramPrefix, processor->type_,
+                              memory_usage);
+}
+
 ModelTypeDebugInfo::ModelTypeDebugInfo() {}
 
 // static
diff --git a/components/sync/model/model_type_debug_info.h b/components/sync/model/model_type_debug_info.h
index 74cc940..e8b94a3 100644
--- a/components/sync/model/model_type_debug_info.h
+++ b/components/sync/model/model_type_debug_info.h
@@ -35,6 +35,10 @@
           callback,
       ModelTypeSyncBridge* bridge);
 
+  // Queries |bridge| for estimate of memory usage and records it in a
+  // histogram.
+  static void RecordMemoryUsageHistogram(ModelTypeSyncBridge* bridge);
+
  private:
   ModelTypeDebugInfo();
 
diff --git a/components/sync/syncable/directory.cc b/components/sync/syncable/directory.cc
index c0a579e..14e0765e 100644
--- a/components/sync/syncable/directory.cc
+++ b/components/sync/syncable/directory.cc
@@ -987,6 +987,42 @@
   }
 }
 
+// Iterates over entries of |map|, sums memory usage estimate of entries whose
+// entry type is |model_type|. Passing owning container will also include memory
+// estimate of EntryKernel.
+template <typename Container>
+size_t EstimateFiteredMapMemoryUsage(const Container& map,
+                                     ModelType model_type) {
+  using base::trace_event::EstimateMemoryUsage;
+  size_t memory_usage = 0;
+  for (const auto& kv : map) {
+    const ModelType entry_type =
+        GetModelTypeFromSpecifics(kv.second->ref(SPECIFICS));
+    if (entry_type == model_type) {
+      memory_usage += EstimateMemoryUsage(kv);
+    }
+  }
+  return memory_usage;
+}
+
+size_t Directory::EstimateMemoryUsageByType(ModelType model_type) {
+  using base::trace_event::EstimateMemoryUsage;
+  ReadTransaction trans(FROM_HERE, this);
+  ScopedKernelLock lock(this);
+
+  size_t memory_usage = 0;
+  memory_usage +=
+      EstimateFiteredMapMemoryUsage(kernel_->metahandles_map, model_type);
+  memory_usage += EstimateFiteredMapMemoryUsage(kernel_->ids_map, model_type);
+  memory_usage +=
+      EstimateFiteredMapMemoryUsage(kernel_->server_tags_map, model_type);
+  memory_usage +=
+      EstimateFiteredMapMemoryUsage(kernel_->client_tags_map, model_type);
+  memory_usage += EstimateMemoryUsage(
+      kernel_->persisted_info.download_progress[model_type]);
+  return memory_usage;
+}
+
 void Directory::SetDownloadProgress(
     ModelType model_type,
     const sync_pb::DataTypeProgressMarker& new_progress) {
@@ -1174,13 +1210,12 @@
                                      ModelType type,
                                      std::vector<int64_t>* result) {
   result->clear();
-  for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin();
-       it != kernel_->metahandles_map.end(); ++it) {
-    EntryKernel* entry = it->second.get();
+  for (const auto& handle_and_kernel : kernel_->metahandles_map) {
+    EntryKernel* entry = handle_and_kernel.second.get();
     const ModelType entry_type =
         GetModelTypeFromSpecifics(entry->ref(SPECIFICS));
     if (entry_type == type)
-      result->push_back(it->first);
+      result->push_back(handle_and_kernel.first);
   }
 }
 
diff --git a/components/sync/syncable/directory.h b/components/sync/syncable/directory.h
index 7e9ff063..5ac3296 100644
--- a/components/sync/syncable/directory.h
+++ b/components/sync/syncable/directory.h
@@ -292,6 +292,10 @@
   // Adds memory statistics to |pmd| for chrome://tracing.
   void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
 
+  // Estimates memory usage of entries and corresponding indices of type
+  // |model_type|.
+  size_t EstimateMemoryUsageByType(ModelType model_type);
+
   // Gets/Increments transaction version of a model type. Must be called when
   // holding kernel mutex.
   int64_t GetTransactionVersion(ModelType type) const;
diff --git a/components/test/data/update_client/runaction_test_win.crx3 b/components/test/data/update_client/runaction_test_win.crx3
index 9cd82f0..4837214 100644
--- a/components/test/data/update_client/runaction_test_win.crx3
+++ b/components/test/data/update_client/runaction_test_win.crx3
Binary files differ
diff --git a/components/test/data/web_database/version_72.sql b/components/test/data/web_database/version_72.sql
deleted file mode 100644
index 9b3935a..0000000
--- a/components/test/data/web_database/version_72.sql
+++ /dev/null
@@ -1,25 +0,0 @@
-PRAGMA foreign_keys=OFF;
-BEGIN TRANSACTION;
-CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
-INSERT INTO "meta" VALUES('mmap_status','-1');
-INSERT INTO "meta" VALUES('version','72');
-INSERT INTO "meta" VALUES('last_compatible_version','72');
-CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
-CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,instant_url VARCHAR,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR,alternate_urls VARCHAR,search_terms_replacement_key VARCHAR,image_url VARCHAR,search_url_post_params VARCHAR,suggest_url_post_params VARCHAR,instant_url_post_params VARCHAR,image_url_post_params VARCHAR,new_tab_url VARCHAR, last_visited INTEGER DEFAULT 0);
-CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, date_created INTEGER DEFAULT 0, date_last_used INTEGER DEFAULT 0, count INTEGER DEFAULT 1, PRIMARY KEY (name, value));
-CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
-CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, street_address VARCHAR, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, sorting_code VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', language_code VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0);
-CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, full_name VARCHAR);
-CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
-CREATE TABLE autofill_profile_phones ( guid VARCHAR, number VARCHAR);
-CREATE TABLE autofill_profiles_trash ( guid VARCHAR);
-CREATE TABLE masked_credit_cards (id VARCHAR,status VARCHAR,name_on_card VARCHAR,network VARCHAR,last_four VARCHAR,exp_month INTEGER DEFAULT 0,exp_year INTEGER DEFAULT 0);
-CREATE TABLE unmasked_credit_cards (id VARCHAR,card_number_encrypted VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, unmask_date INTEGER NOT NULL DEFAULT 0);
-CREATE TABLE server_card_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
-CREATE TABLE server_addresses (id VARCHAR,company_name VARCHAR,street_address VARCHAR,address_1 VARCHAR,address_2 VARCHAR,address_3 VARCHAR,address_4 VARCHAR,postal_code VARCHAR,sorting_code VARCHAR,country_code VARCHAR,language_code VARCHAR, recipient_name VARCHAR, phone_number VARCHAR);
-CREATE TABLE server_address_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, has_converted BOOL NOT NULL DEFAULT FALSE);
-CREATE TABLE autofill_sync_metadata (storage_key VARCHAR PRIMARY KEY NOT NULL,value BLOB);
-CREATE TABLE autofill_model_type_state (id INTEGER PRIMARY KEY, value BLOB);
-CREATE INDEX autofill_name ON autofill (name);
-CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
-COMMIT;
diff --git a/components/ui_devtools/BUILD.gn b/components/ui_devtools/BUILD.gn
index eab5c09..bb1d83b 100644
--- a/components/ui_devtools/BUILD.gn
+++ b/components/ui_devtools/BUILD.gn
@@ -52,7 +52,7 @@
   outputs = _protocol_generated
 }
 
-source_set("ui_devtools") {
+component("ui_devtools") {
   sources = rebase_path(_protocol_generated, ".", target_gen_dir)
   sources += [
     "devtools_base_agent.h",
diff --git a/components/ui_devtools/README.md b/components/ui_devtools/README.md
new file mode 100644
index 0000000..71c9bbb
--- /dev/null
+++ b/components/ui_devtools/README.md
@@ -0,0 +1,3 @@
+# Inspecting Chrome Native UI with DevTools.
+
+https://www.chromium.org/developers/how-tos/inspecting-ash
diff --git a/components/ui_devtools/devtools_base_agent.h b/components/ui_devtools/devtools_base_agent.h
index 0b66d82..da1c6fe 100644
--- a/components/ui_devtools/devtools_base_agent.h
+++ b/components/ui_devtools/devtools_base_agent.h
@@ -7,8 +7,7 @@
 
 #include "components/ui_devtools/Protocol.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 class UiDevToolsAgent {
  public:
@@ -39,12 +38,12 @@
 
   // Common methods between all generated Backends, subclasses may
   // choose to override them (but not necessary).
-  ui::devtools::protocol::Response enable() override {
-    return ui::devtools::protocol::Response::OK();
+  ui_devtools::protocol::Response enable() override {
+    return ui_devtools::protocol::Response::OK();
   };
 
-  ui::devtools::protocol::Response disable() override {
-    return ui::devtools::protocol::Response::OK();
+  ui_devtools::protocol::Response disable() override {
+    return ui_devtools::protocol::Response::OK();
   };
 
  protected:
@@ -59,7 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(UiDevToolsBaseAgent);
 };
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
 
 #endif  // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_BASE_AGENT_H_
diff --git a/components/ui_devtools/devtools_client.cc b/components/ui_devtools/devtools_client.cc
index 4c2a1fc..6640fa9 100644
--- a/components/ui_devtools/devtools_client.cc
+++ b/components/ui_devtools/devtools_client.cc
@@ -6,8 +6,7 @@
 
 #include "components/ui_devtools/devtools_server.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 UiDevToolsClient::UiDevToolsClient(const std::string& name,
                                    UiDevToolsServer* server)
@@ -68,5 +67,4 @@
   NOTIMPLEMENTED();
 }
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/devtools_client.h b/components/ui_devtools/devtools_client.h
index 1812556..b9dfe88 100644
--- a/components/ui_devtools/devtools_client.h
+++ b/components/ui_devtools/devtools_client.h
@@ -11,9 +11,9 @@
 #include "components/ui_devtools/Forward.h"
 #include "components/ui_devtools/Protocol.h"
 #include "components/ui_devtools/devtools_base_agent.h"
+#include "components/ui_devtools/devtools_export.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 class UiDevToolsServer;
 
@@ -21,7 +21,7 @@
 // this class and attach the corresponding backends/frontends (i.e: DOM, CSS,
 // etc). This client is then attached to the UiDevToolsServer and all messages
 // from this client are sent over the web socket owned by the server.
-class UiDevToolsClient : public protocol::FrontendChannel {
+class UI_DEVTOOLS_EXPORT UiDevToolsClient : public protocol::FrontendChannel {
  public:
   static const int kNotConnected = -1;
 
@@ -57,7 +57,6 @@
   DISALLOW_COPY_AND_ASSIGN(UiDevToolsClient);
 };
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
 
 #endif  // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_CLIENT_H_
diff --git a/components/ui_devtools/devtools_server.cc b/components/ui_devtools/devtools_server.cc
index fd0e35b..c8fd76c1 100644
--- a/components/ui_devtools/devtools_server.cc
+++ b/components/ui_devtools/devtools_server.cc
@@ -21,8 +21,7 @@
 #include "net/socket/server_socket.h"
 #include "net/socket/tcp_server_socket.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 namespace {
 const char kChromeDeveloperToolsPrefix[] =
@@ -182,5 +181,4 @@
   connections_.erase(it);
 }
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/devtools_server.h b/components/ui_devtools/devtools_server.h
index 04483cc..f5bce62 100644
--- a/components/ui_devtools/devtools_server.h
+++ b/components/ui_devtools/devtools_server.h
@@ -14,13 +14,14 @@
 #include "components/ui_devtools/Forward.h"
 #include "components/ui_devtools/Protocol.h"
 #include "components/ui_devtools/devtools_client.h"
+#include "components/ui_devtools/devtools_export.h"
 #include "components/ui_devtools/string_util.h"
 #include "net/server/http_server.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
-class UiDevToolsServer : public net::HttpServer::Delegate {
+class UI_DEVTOOLS_EXPORT UiDevToolsServer
+    : public NON_EXPORTED_BASE(net::HttpServer::Delegate) {
  public:
   ~UiDevToolsServer() override;
 
@@ -68,7 +69,6 @@
   DISALLOW_COPY_AND_ASSIGN(UiDevToolsServer);
 };
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
 
 #endif  // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_SERVER_H_
diff --git a/components/ui_devtools/inspector_protocol_config.json b/components/ui_devtools/inspector_protocol_config.json
index 9ad3815..76292154 100644
--- a/components/ui_devtools/inspector_protocol_config.json
+++ b/components/ui_devtools/inspector_protocol_config.json
@@ -3,7 +3,7 @@
         "path": "protocol.json",
         "package": "components/ui_devtools",
         "output": "",
-        "namespace": ["ui", "devtools", "protocol"],
+        "namespace": ["ui_devtools", "protocol"],
         "export_macro": "UI_DEVTOOLS_EXPORT",
         "export_header": "components/ui_devtools/devtools_export.h"
     },
diff --git a/components/ui_devtools/string_util.cc b/components/ui_devtools/string_util.cc
index 0b936a38..ade4b6f3 100644
--- a/components/ui_devtools/string_util.cc
+++ b/components/ui_devtools/string_util.cc
@@ -7,8 +7,7 @@
 #include "base/strings/string_util.h"
 #include "components/ui_devtools/Protocol.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 namespace protocol {
 
 // static
@@ -20,5 +19,4 @@
 };
 
 }  // namespace protocol
-}  // namespace ws
-}  // namespace ui
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/string_util.h b/components/ui_devtools/string_util.h
index d08b8b6f..8f12102 100644
--- a/components/ui_devtools/string_util.h
+++ b/components/ui_devtools/string_util.h
@@ -10,8 +10,7 @@
 #include "base/json/json_reader.h"
 #include "base/strings/string_number_conversions.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 using String = std::string;
 
@@ -28,9 +27,7 @@
   void reserveCapacity(std::size_t size) { s_.reserve(size); }
   void append(const String& s) { s_ += s; }
   void append(char c) { s_ += c; }
-  void append(const char* data, unsigned int length) {
-    s_.append(data, length);
-  }
+  void append(const char* data, size_t length) { s_.append(data, length); }
   String toString() { return s_; }
 };
 
@@ -76,7 +73,6 @@
 };
 
 }  // namespace protocol
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
 
 #endif  // COMPONENTS_UI_DEVTOOLS_STRING_UTIL_H_
diff --git a/components/ui_devtools/switches.cc b/components/ui_devtools/switches.cc
index c76f5b4..b4762aa 100644
--- a/components/ui_devtools/switches.cc
+++ b/components/ui_devtools/switches.cc
@@ -4,12 +4,10 @@
 
 #include "components/ui_devtools/switches.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 // Enables DevTools server for UI (mus, ash, etc). Value should be the port the
 // server is started on. Default port is 9332.
 const char kEnableUiDevTools[] = "enable-ui-devtools";
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/switches.h b/components/ui_devtools/switches.h
index d0bb577..4d96c9ca 100644
--- a/components/ui_devtools/switches.h
+++ b/components/ui_devtools/switches.h
@@ -7,12 +7,10 @@
 
 #include "components/ui_devtools/devtools_export.h"
 
-namespace ui {
-namespace devtools {
+namespace ui_devtools {
 
 extern UI_DEVTOOLS_EXPORT const char kEnableUiDevTools[];
 
-}  // namespace devtools
-}  // namespace ui
+}  // namespace ui_devtools
 
 #endif  // COMPONENTS_UI_DEVTOOLS_SWITCHES_H_
diff --git a/components/ui_devtools/views/BUILD.gn b/components/ui_devtools/views/BUILD.gn
new file mode 100644
index 0000000..514fadf
--- /dev/null
+++ b/components/ui_devtools/views/BUILD.gn
@@ -0,0 +1,62 @@
+# 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.
+
+import("//build/config/ui.gni")
+
+source_set("views") {
+  cflags = []
+  if (is_win) {
+    cflags += [ "/wd4800" ]  # Value forced to bool.
+  }
+
+  sources = [
+    "ui_devtools_css_agent.cc",
+    "ui_devtools_css_agent.h",
+    "ui_devtools_dom_agent.cc",
+    "ui_devtools_dom_agent.h",
+    "ui_element.cc",
+    "ui_element.h",
+    "ui_element_delegate.h",
+    "view_element.cc",
+    "view_element.h",
+    "widget_element.cc",
+    "widget_element.h",
+    "window_element.cc",
+    "window_element.h",
+  ]
+
+  deps = [
+    "//components/ui_devtools",
+    "//skia",
+    "//ui/aura",
+    "//ui/views",
+    "//ui/wm:wm",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  cflags = []
+  if (is_win) {
+    cflags += [ "/wd4800" ]  # Value forced to bool.
+  }
+
+  sources = [
+    "ui_devtools_unittest.cc",
+  ]
+
+  deps = [
+    ":views",
+    "//components/ui_devtools",
+    "//skia",
+    "//testing/gtest",
+    "//ui/aura",
+    "//ui/views",
+    "//ui/views:test_support",
+    "//ui/wm:wm",
+  ]
+
+  configs += [ "//build/config:precompiled_headers" ]
+}
diff --git a/components/ui_devtools/views/DEPS b/components/ui_devtools/views/DEPS
new file mode 100644
index 0000000..35272fdb
--- /dev/null
+++ b/components/ui_devtools/views/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+third_party/skia/include/core",
+  "+ui"
+]
diff --git a/ash/devtools/OWNERS b/components/ui_devtools/views/OWNERS
similarity index 100%
rename from ash/devtools/OWNERS
rename to components/ui_devtools/views/OWNERS
diff --git a/ash/devtools/ash_devtools_css_agent.cc b/components/ui_devtools/views/ui_devtools_css_agent.cc
similarity index 70%
rename from ash/devtools/ash_devtools_css_agent.cc
rename to components/ui_devtools/views/ui_devtools_css_agent.cc
index 90c2ed2..62a4be2 100644
--- a/ash/devtools/ash_devtools_css_agent.cc
+++ b/components/ui_devtools/views/ui_devtools_css_agent.cc
@@ -2,18 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/ash_devtools_css_agent.h"
+#include "components/ui_devtools/views/ui_devtools_css_agent.h"
 
-#include "ash/devtools/ui_element.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
+#include "components/ui_devtools/views/ui_element.h"
 #include "ui/aura/window.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 namespace {
 
-using namespace ui::devtools::protocol;
+using namespace ui_devtools::protocol;
 
 const char kHeight[] = "height";
 const char kWidth[] = "width";
@@ -66,8 +65,8 @@
       .build();
 }
 
-ui::devtools::protocol::Response NodeNotFoundError(int node_id) {
-  return ui::devtools::protocol::Response::Error(
+ui_devtools::protocol::Response NodeNotFoundError(int node_id) {
+  return ui_devtools::protocol::Response::Error(
       "Node with id=" + std::to_string(node_id) + " not found");
 }
 
@@ -100,57 +99,57 @@
 
 }  // namespace
 
-AshDevToolsCSSAgent::AshDevToolsCSSAgent(AshDevToolsDOMAgent* dom_agent)
+UIDevToolsCSSAgent::UIDevToolsCSSAgent(UIDevToolsDOMAgent* dom_agent)
     : dom_agent_(dom_agent) {
   DCHECK(dom_agent_);
 }
 
-AshDevToolsCSSAgent::~AshDevToolsCSSAgent() {
+UIDevToolsCSSAgent::~UIDevToolsCSSAgent() {
   disable();
 }
 
-ui::devtools::protocol::Response AshDevToolsCSSAgent::enable() {
+ui_devtools::protocol::Response UIDevToolsCSSAgent::enable() {
   dom_agent_->AddObserver(this);
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-ui::devtools::protocol::Response AshDevToolsCSSAgent::disable() {
+ui_devtools::protocol::Response UIDevToolsCSSAgent::disable() {
   dom_agent_->RemoveObserver(this);
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-ui::devtools::protocol::Response AshDevToolsCSSAgent::getMatchedStylesForNode(
+ui_devtools::protocol::Response UIDevToolsCSSAgent::getMatchedStylesForNode(
     int node_id,
-    ui::devtools::protocol::Maybe<ui::devtools::protocol::CSS::CSSStyle>*
+    ui_devtools::protocol::Maybe<ui_devtools::protocol::CSS::CSSStyle>*
         inline_style) {
   *inline_style = GetStylesForNode(node_id);
   if (!inline_style)
     return NodeNotFoundError(node_id);
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-ui::devtools::protocol::Response AshDevToolsCSSAgent::setStyleTexts(
-    std::unique_ptr<ui::devtools::protocol::Array<
-        ui::devtools::protocol::CSS::StyleDeclarationEdit>> edits,
+ui_devtools::protocol::Response UIDevToolsCSSAgent::setStyleTexts(
+    std::unique_ptr<ui_devtools::protocol::Array<
+        ui_devtools::protocol::CSS::StyleDeclarationEdit>> edits,
     std::unique_ptr<
-        ui::devtools::protocol::Array<ui::devtools::protocol::CSS::CSSStyle>>*
+        ui_devtools::protocol::Array<ui_devtools::protocol::CSS::CSSStyle>>*
         result) {
   std::unique_ptr<
-      ui::devtools::protocol::Array<ui::devtools::protocol::CSS::CSSStyle>>
-      updated_styles = ui::devtools::protocol::Array<
-          ui::devtools::protocol::CSS::CSSStyle>::create();
+      ui_devtools::protocol::Array<ui_devtools::protocol::CSS::CSSStyle>>
+      updated_styles = ui_devtools::protocol::Array<
+          ui_devtools::protocol::CSS::CSSStyle>::create();
   for (size_t i = 0; i < edits->length(); i++) {
     auto* edit = edits->get(i);
     int node_id;
     if (!base::StringToInt(edit->getStyleSheetId(), &node_id))
-      return ui::devtools::protocol::Response::Error("Invalid node id");
+      return ui_devtools::protocol::Response::Error("Invalid node id");
 
     gfx::Rect updated_bounds;
     bool visible = false;
     if (!GetPropertiesForNodeId(node_id, &updated_bounds, &visible))
       return NodeNotFoundError(node_id);
 
-    ui::devtools::protocol::Response response(
+    ui_devtools::protocol::Response response(
         ParseProperties(edit->getText(), &updated_bounds, &visible));
     if (!response.isSuccess())
       return response;
@@ -161,15 +160,15 @@
       return NodeNotFoundError(node_id);
   }
   *result = std::move(updated_styles);
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-void AshDevToolsCSSAgent::OnNodeBoundsChanged(int node_id) {
+void UIDevToolsCSSAgent::OnNodeBoundsChanged(int node_id) {
   InvalidateStyleSheet(node_id);
 }
 
-std::unique_ptr<ui::devtools::protocol::CSS::CSSStyle>
-AshDevToolsCSSAgent::GetStylesForNode(int node_id) {
+std::unique_ptr<ui_devtools::protocol::CSS::CSSStyle>
+UIDevToolsCSSAgent::GetStylesForNode(int node_id) {
   gfx::Rect bounds;
   bool visible = false;
   return GetPropertiesForNodeId(node_id, &bounds, &visible)
@@ -177,14 +176,14 @@
              : nullptr;
 }
 
-void AshDevToolsCSSAgent::InvalidateStyleSheet(int node_id) {
+void UIDevToolsCSSAgent::InvalidateStyleSheet(int node_id) {
   // The stylesheetId for each node is equivalent to its node_id (as a string).
   frontend()->styleSheetChanged(base::IntToString(node_id));
 }
 
-bool AshDevToolsCSSAgent::GetPropertiesForNodeId(int node_id,
-                                                 gfx::Rect* bounds,
-                                                 bool* visible) {
+bool UIDevToolsCSSAgent::GetPropertiesForNodeId(int node_id,
+                                                gfx::Rect* bounds,
+                                                bool* visible) {
   UIElement* ui_element = dom_agent_->GetElementFromNodeId(node_id);
   if (ui_element) {
     ui_element->GetBounds(bounds);
@@ -194,9 +193,9 @@
   return false;
 }
 
-bool AshDevToolsCSSAgent::SetPropertiesForNodeId(int node_id,
-                                                 const gfx::Rect& bounds,
-                                                 bool visible) {
+bool UIDevToolsCSSAgent::SetPropertiesForNodeId(int node_id,
+                                                const gfx::Rect& bounds,
+                                                bool visible) {
   UIElement* ui_element = dom_agent_->GetElementFromNodeId(node_id);
   if (ui_element) {
     ui_element->SetBounds(bounds);
@@ -206,5 +205,4 @@
   return false;
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/views/ui_devtools_css_agent.h b/components/ui_devtools/views/ui_devtools_css_agent.h
new file mode 100644
index 0000000..ef88dccc
--- /dev/null
+++ b/components/ui_devtools/views/ui_devtools_css_agent.h
@@ -0,0 +1,53 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_CSS_AGENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_CSS_AGENT_H_
+
+#include "base/macros.h"
+#include "components/ui_devtools/CSS.h"
+#include "components/ui_devtools/views/ui_devtools_dom_agent.h"
+
+namespace ui_devtools {
+
+class UIDevToolsCSSAgent : public ui_devtools::UiDevToolsBaseAgent<
+                               ui_devtools::protocol::CSS::Metainfo>,
+                           public UIDevToolsDOMAgentObserver {
+ public:
+  explicit UIDevToolsCSSAgent(UIDevToolsDOMAgent* dom_agent);
+  ~UIDevToolsCSSAgent() override;
+
+  // CSS::Backend:
+  ui_devtools::protocol::Response enable() override;
+  ui_devtools::protocol::Response disable() override;
+  ui_devtools::protocol::Response getMatchedStylesForNode(
+      int node_id,
+      ui_devtools::protocol::Maybe<ui_devtools::protocol::CSS::CSSStyle>*
+          inline_style) override;
+  ui_devtools::protocol::Response setStyleTexts(
+      std::unique_ptr<ui_devtools::protocol::Array<
+          ui_devtools::protocol::CSS::StyleDeclarationEdit>> edits,
+      std::unique_ptr<
+          ui_devtools::protocol::Array<ui_devtools::protocol::CSS::CSSStyle>>*
+          result) override;
+
+  // UIDevToolsDOMAgentObserver:
+  void OnNodeBoundsChanged(int node_id) override;
+
+ private:
+  std::unique_ptr<ui_devtools::protocol::CSS::CSSStyle> GetStylesForNode(
+      int node_id);
+  void InvalidateStyleSheet(int node_id);
+  bool GetPropertiesForNodeId(int node_id, gfx::Rect* bounds, bool* visible);
+  bool SetPropertiesForNodeId(int node_id,
+                              const gfx::Rect& bounds,
+                              bool visible);
+  UIDevToolsDOMAgent* dom_agent_;
+
+  DISALLOW_COPY_AND_ASSIGN(UIDevToolsCSSAgent);
+};
+
+}  // namespace ui_devtools
+
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_CSS_AGENT_H_
diff --git a/ash/devtools/ash_devtools_dom_agent.cc b/components/ui_devtools/views/ui_devtools_dom_agent.cc
similarity index 78%
rename from ash/devtools/ash_devtools_dom_agent.cc
rename to components/ui_devtools/views/ui_devtools_dom_agent.cc
index 72fc8e3..3adba64e 100644
--- a/ash/devtools/ash_devtools_dom_agent.cc
+++ b/components/ui_devtools/views/ui_devtools_dom_agent.cc
@@ -2,14 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/ash_devtools_dom_agent.h"
+#include "components/ui_devtools/views/ui_devtools_dom_agent.h"
 
-#include "ash/devtools/ui_element.h"
-#include "ash/devtools/view_element.h"
-#include "ash/devtools/widget_element.h"
-#include "ash/devtools/window_element.h"
-#include "ash/public/cpp/shell_window_ids.h"
 #include "components/ui_devtools/devtools_server.h"
+#include "components/ui_devtools/views/ui_element.h"
+#include "components/ui_devtools/views/view_element.h"
+#include "components/ui_devtools/views/widget_element.h"
+#include "components/ui_devtools/views/window_element.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/env.h"
@@ -23,11 +22,10 @@
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/window_util.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 namespace {
 
-using namespace ui::devtools::protocol;
+using namespace ui_devtools::protocol;
 // TODO(mhashmi): Make ids reusable
 
 std::unique_ptr<DOM::Node> BuildNode(
@@ -42,7 +40,7 @@
                                         .setNodeType(kDomElementNodeType)
                                         .setAttributes(std::move(attributes))
                                         .build();
-  node->setChildNodeCount(children->length());
+  node->setChildNodeCount(static_cast<int>(children->length()));
   node->setChildren(std::move(children));
   return node;
 }
@@ -111,48 +109,47 @@
                                         .setNodeType(kDomElementNodeType)
                                         .setAttributes(GetAttributes(root))
                                         .build();
-  node->setChildNodeCount(children->length());
+  node->setChildNodeCount(static_cast<int>(children->length()));
   node->setChildren(std::move(children));
   return node;
 }
 
 }  // namespace
 
-AshDevToolsDOMAgent::AshDevToolsDOMAgent() : is_building_tree_(false) {
+UIDevToolsDOMAgent::UIDevToolsDOMAgent() : is_building_tree_(false) {
   aura::Env::GetInstance()->AddObserver(this);
 }
 
-AshDevToolsDOMAgent::~AshDevToolsDOMAgent() {
+UIDevToolsDOMAgent::~UIDevToolsDOMAgent() {
   aura::Env::GetInstance()->RemoveObserver(this);
   Reset();
 }
 
-ui::devtools::protocol::Response AshDevToolsDOMAgent::disable() {
+ui_devtools::protocol::Response UIDevToolsDOMAgent::disable() {
   Reset();
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-ui::devtools::protocol::Response AshDevToolsDOMAgent::getDocument(
-    std::unique_ptr<ui::devtools::protocol::DOM::Node>* out_root) {
+ui_devtools::protocol::Response UIDevToolsDOMAgent::getDocument(
+    std::unique_ptr<ui_devtools::protocol::DOM::Node>* out_root) {
   *out_root = BuildInitialTree();
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-ui::devtools::protocol::Response AshDevToolsDOMAgent::highlightNode(
-    std::unique_ptr<ui::devtools::protocol::DOM::HighlightConfig>
+ui_devtools::protocol::Response UIDevToolsDOMAgent::highlightNode(
+    std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig>
         highlight_config,
-    ui::devtools::protocol::Maybe<int> node_id) {
+    ui_devtools::protocol::Maybe<int> node_id) {
   return HighlightNode(std::move(highlight_config), node_id.fromJust());
 }
 
-ui::devtools::protocol::Response AshDevToolsDOMAgent::hideHighlight() {
+ui_devtools::protocol::Response UIDevToolsDOMAgent::hideHighlight() {
   if (widget_for_highlighting_ && widget_for_highlighting_->IsVisible())
     widget_for_highlighting_->Hide();
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-void AshDevToolsDOMAgent::OnUIElementAdded(UIElement* parent,
-                                           UIElement* child) {
+void UIDevToolsDOMAgent::OnUIElementAdded(UIElement* parent, UIElement* child) {
   // When parent is null, only need to update |node_id_to_ui_element_|.
   if (!parent) {
     node_id_to_ui_element_[child->node_id()] = child;
@@ -171,8 +168,8 @@
                                 BuildTreeForUIElement(child));
 }
 
-void AshDevToolsDOMAgent::OnUIElementReordered(UIElement* parent,
-                                               UIElement* child) {
+void UIDevToolsDOMAgent::OnUIElementReordered(UIElement* parent,
+                                              UIElement* child) {
   DCHECK(node_id_to_ui_element_.count(parent->node_id()));
 
   const auto& children = parent->children();
@@ -184,47 +181,46 @@
                                 BuildDomNodeFromUIElement(child));
 }
 
-void AshDevToolsDOMAgent::OnUIElementRemoved(UIElement* ui_element) {
+void UIDevToolsDOMAgent::OnUIElementRemoved(UIElement* ui_element) {
   DCHECK(node_id_to_ui_element_.count(ui_element->node_id()));
 
   RemoveDomNode(ui_element);
   node_id_to_ui_element_.erase(ui_element->node_id());
 }
 
-void AshDevToolsDOMAgent::OnUIElementBoundsChanged(UIElement* ui_element) {
+void UIDevToolsDOMAgent::OnUIElementBoundsChanged(UIElement* ui_element) {
   for (auto& observer : observers_)
     observer.OnNodeBoundsChanged(ui_element->node_id());
 }
 
-bool AshDevToolsDOMAgent::IsHighlightingWindow(aura::Window* window) {
+bool UIDevToolsDOMAgent::IsHighlightingWindow(aura::Window* window) {
   return widget_for_highlighting_ &&
          GetWidgetFromWindow(window) == widget_for_highlighting_.get();
 }
 
-void AshDevToolsDOMAgent::AddObserver(AshDevToolsDOMAgentObserver* observer) {
+void UIDevToolsDOMAgent::AddObserver(UIDevToolsDOMAgentObserver* observer) {
   observers_.AddObserver(observer);
 }
 
-void AshDevToolsDOMAgent::RemoveObserver(
-    AshDevToolsDOMAgentObserver* observer) {
+void UIDevToolsDOMAgent::RemoveObserver(UIDevToolsDOMAgentObserver* observer) {
   observers_.RemoveObserver(observer);
 }
 
-UIElement* AshDevToolsDOMAgent::GetElementFromNodeId(int node_id) {
+UIElement* UIDevToolsDOMAgent::GetElementFromNodeId(int node_id) {
   return node_id_to_ui_element_[node_id];
 }
 
-void AshDevToolsDOMAgent::OnHostInitialized(aura::WindowTreeHost* host) {
+void UIDevToolsDOMAgent::OnHostInitialized(aura::WindowTreeHost* host) {
   root_windows_.push_back(host->window());
 }
 
-void AshDevToolsDOMAgent::OnNodeBoundsChanged(int node_id) {
+void UIDevToolsDOMAgent::OnNodeBoundsChanged(int node_id) {
   for (auto& observer : observers_)
     observer.OnNodeBoundsChanged(node_id);
 }
 
-std::unique_ptr<ui::devtools::protocol::DOM::Node>
-AshDevToolsDOMAgent::BuildInitialTree() {
+std::unique_ptr<ui_devtools::protocol::DOM::Node>
+UIDevToolsDOMAgent::BuildInitialTree() {
   is_building_tree_ = true;
   std::unique_ptr<Array<DOM::Node>> children = Array<DOM::Node>::create();
 
@@ -240,14 +236,14 @@
     children->addItem(BuildTreeForUIElement(window_element));
     window_element_root_->AddChild(window_element);
   }
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root_node = BuildNode(
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root_node = BuildNode(
       "root", nullptr, std::move(children), window_element_root_->node_id());
   is_building_tree_ = false;
   return root_node;
 }
 
-std::unique_ptr<ui::devtools::protocol::DOM::Node>
-AshDevToolsDOMAgent::BuildTreeForUIElement(UIElement* ui_element) {
+std::unique_ptr<ui_devtools::protocol::DOM::Node>
+UIDevToolsDOMAgent::BuildTreeForUIElement(UIElement* ui_element) {
   if (ui_element->type() == UIElementType::WINDOW) {
     return BuildTreeForWindow(
         ui_element,
@@ -264,7 +260,7 @@
   return nullptr;
 }
 
-std::unique_ptr<DOM::Node> AshDevToolsDOMAgent::BuildTreeForWindow(
+std::unique_ptr<DOM::Node> UIDevToolsDOMAgent::BuildTreeForWindow(
     UIElement* window_element_root,
     aura::Window* window) {
   std::unique_ptr<Array<DOM::Node>> children = Array<DOM::Node>::create();
@@ -283,13 +279,13 @@
     children->addItem(BuildTreeForWindow(window_element, child));
     window_element_root->AddChild(window_element);
   }
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> node =
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> node =
       BuildNode("Window", GetAttributes(window_element_root),
                 std::move(children), window_element_root->node_id());
   return node;
 }
 
-std::unique_ptr<DOM::Node> AshDevToolsDOMAgent::BuildTreeForRootWidget(
+std::unique_ptr<DOM::Node> UIDevToolsDOMAgent::BuildTreeForRootWidget(
     UIElement* widget_element,
     views::Widget* widget) {
   std::unique_ptr<Array<DOM::Node>> children = Array<DOM::Node>::create();
@@ -300,13 +296,13 @@
   children->addItem(BuildTreeForView(view_element, widget->GetRootView()));
   widget_element->AddChild(view_element);
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> node =
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> node =
       BuildNode("Widget", GetAttributes(widget_element), std::move(children),
                 widget_element->node_id());
   return node;
 }
 
-std::unique_ptr<DOM::Node> AshDevToolsDOMAgent::BuildTreeForView(
+std::unique_ptr<DOM::Node> UIDevToolsDOMAgent::BuildTreeForView(
     UIElement* view_element,
     views::View* view) {
   std::unique_ptr<Array<DOM::Node>> children = Array<DOM::Node>::create();
@@ -317,20 +313,20 @@
     children->addItem(BuildTreeForView(view_element_child, child));
     view_element->AddChild(view_element_child);
   }
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> node =
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> node =
       BuildNode("View", GetAttributes(view_element), std::move(children),
                 view_element->node_id());
   return node;
 }
 
-void AshDevToolsDOMAgent::RemoveDomNode(UIElement* ui_element) {
+void UIDevToolsDOMAgent::RemoveDomNode(UIElement* ui_element) {
   for (auto* child_element : ui_element->children())
     RemoveDomNode(child_element);
   frontend()->childNodeRemoved(ui_element->parent()->node_id(),
                                ui_element->node_id());
 }
 
-void AshDevToolsDOMAgent::Reset() {
+void UIDevToolsDOMAgent::Reset() {
   is_building_tree_ = false;
   widget_for_highlighting_.reset();
   window_element_root_.reset();
@@ -338,7 +334,7 @@
   observers_.Clear();
 }
 
-void AshDevToolsDOMAgent::InitializeHighlightingWidget() {
+void UIDevToolsDOMAgent::InitializeHighlightingWidget() {
   DCHECK(!widget_for_highlighting_);
   widget_for_highlighting_.reset(new views::Widget);
   views::Widget::InitParams params;
@@ -347,12 +343,13 @@
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.opacity = views::Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW;
   params.name = "HighlightingWidget";
+  params.parent = root_windows()[0];
   params.keep_on_top = true;
   params.accept_events = false;
   widget_for_highlighting_->Init(params);
 }
 
-void AshDevToolsDOMAgent::UpdateHighlight(
+void UIDevToolsDOMAgent::UpdateHighlight(
     const std::pair<aura::Window*, gfx::Rect>& window_and_bounds,
     SkColor background,
     SkColor border) {
@@ -377,8 +374,8 @@
   widget_for_highlighting_->GetNativeWindow()->SetBounds(bounds);
 }
 
-ui::devtools::protocol::Response AshDevToolsDOMAgent::HighlightNode(
-    std::unique_ptr<ui::devtools::protocol::DOM::HighlightConfig>
+ui_devtools::protocol::Response UIDevToolsDOMAgent::HighlightNode(
+    std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig>
         highlight_config,
     int node_id) {
   if (!widget_for_highlighting_)
@@ -390,8 +387,7 @@
           : std::make_pair<aura::Window*, gfx::Rect>(nullptr, gfx::Rect());
 
   if (!window_and_bounds.first) {
-    return ui::devtools::protocol::Response::Error(
-        "No node found with that id");
+    return ui_devtools::protocol::Response::Error("No node found with that id");
   }
   SkColor border_color =
       RGBAToSkColor(highlight_config->getBorderColor(nullptr));
@@ -402,8 +398,7 @@
   if (!widget_for_highlighting_->IsVisible())
     widget_for_highlighting_->Show();
 
-  return ui::devtools::protocol::Response::OK();
+  return ui_devtools::protocol::Response::OK();
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/views/ui_devtools_dom_agent.h b/components/ui_devtools/views/ui_devtools_dom_agent.h
new file mode 100644
index 0000000..701547f6
--- /dev/null
+++ b/components/ui_devtools/views/ui_devtools_dom_agent.h
@@ -0,0 +1,104 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_DOM_AGENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_DOM_AGENT_H_
+
+#include "components/ui_devtools/DOM.h"
+#include "components/ui_devtools/devtools_base_agent.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
+#include "ui/aura/env_observer.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace aura {
+class Window;
+}
+
+namespace ui_devtools {
+
+class UIElement;
+
+class UIDevToolsDOMAgentObserver {
+ public:
+  // TODO(thanhph): Use UIElement* as input argument instead.
+  virtual void OnNodeBoundsChanged(int node_id) = 0;
+};
+
+class UIDevToolsDOMAgent : public ui_devtools::UiDevToolsBaseAgent<
+                               ui_devtools::protocol::DOM::Metainfo>,
+                           public UIElementDelegate,
+                           public aura::EnvObserver {
+ public:
+  UIDevToolsDOMAgent();
+  ~UIDevToolsDOMAgent() override;
+
+  // DOM::Backend:
+  ui_devtools::protocol::Response disable() override;
+  ui_devtools::protocol::Response getDocument(
+      std::unique_ptr<ui_devtools::protocol::DOM::Node>* out_root) override;
+  ui_devtools::protocol::Response highlightNode(
+      std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig>
+          highlight_config,
+      ui_devtools::protocol::Maybe<int> node_id) override;
+  ui_devtools::protocol::Response hideHighlight() override;
+
+  // UIElementDelegate:
+  void OnUIElementAdded(UIElement* parent, UIElement* child) override;
+  void OnUIElementReordered(UIElement* parent, UIElement* child) override;
+  void OnUIElementRemoved(UIElement* ui_element) override;
+  void OnUIElementBoundsChanged(UIElement* ui_element) override;
+  bool IsHighlightingWindow(aura::Window* window) override;
+
+  void AddObserver(UIDevToolsDOMAgentObserver* observer);
+  void RemoveObserver(UIDevToolsDOMAgentObserver* observer);
+  UIElement* GetElementFromNodeId(int node_id);
+  UIElement* window_element_root() const { return window_element_root_.get(); };
+  const std::vector<aura::Window*>& root_windows() const {
+    return root_windows_;
+  };
+
+ private:
+  // aura::EnvObserver:
+  void OnWindowInitialized(aura::Window* window) override {}
+  void OnHostInitialized(aura::WindowTreeHost* host) override;
+
+  void OnNodeBoundsChanged(int node_id);
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> BuildInitialTree();
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> BuildTreeForUIElement(
+      UIElement* ui_element);
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> BuildTreeForWindow(
+      UIElement* window_element_root,
+      aura::Window* window);
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> BuildTreeForRootWidget(
+      UIElement* widget_element,
+      views::Widget* widget);
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> BuildTreeForView(
+      UIElement* view_element,
+      views::View* view);
+  void RemoveDomNode(UIElement* ui_element);
+  void Reset();
+  void InitializeHighlightingWidget();
+  void UpdateHighlight(
+      const std::pair<aura::Window*, gfx::Rect>& window_and_bounds,
+      SkColor background,
+      SkColor border);
+  ui_devtools::protocol::Response HighlightNode(
+      std::unique_ptr<ui_devtools::protocol::DOM::HighlightConfig>
+          highlight_config,
+      int node_id);
+
+  bool is_building_tree_;
+  std::unique_ptr<UIElement> window_element_root_;
+  std::unordered_map<int, UIElement*> node_id_to_ui_element_;
+  std::unique_ptr<views::Widget> widget_for_highlighting_;
+  std::vector<aura::Window*> root_windows_;
+  base::ObserverList<UIDevToolsDOMAgentObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(UIDevToolsDOMAgent);
+};
+
+}  // namespace ui_devtools
+
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_DEVTOOLS_DOM_AGENT_H_
diff --git a/ash/devtools/ash_devtools_unittest.cc b/components/ui_devtools/views/ui_devtools_unittest.cc
similarity index 81%
rename from ash/devtools/ash_devtools_unittest.cc
rename to components/ui_devtools/views/ui_devtools_unittest.cc
index 90ed0be..e0fed67d 100644
--- a/ash/devtools/ash_devtools_unittest.cc
+++ b/components/ui_devtools/views/ui_devtools_unittest.cc
@@ -2,29 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/ash_devtools_css_agent.h"
-#include "ash/devtools/ash_devtools_dom_agent.h"
-#include "ash/devtools/ui_element.h"
-#include "ash/devtools/view_element.h"
-#include "ash/devtools/widget_element.h"
-#include "ash/devtools/window_element.h"
-#include "ash/shell.h"
-#include "ash/test/ash_test_base.h"
-#include "ash/wm/widget_finder.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "components/ui_devtools/views/ui_devtools_css_agent.h"
+#include "components/ui_devtools/views/ui_devtools_dom_agent.h"
+#include "components/ui_devtools/views/ui_element.h"
+#include "components/ui_devtools/views/view_element.h"
+#include "components/ui_devtools/views/widget_element.h"
+#include "components/ui_devtools/views/window_element.h"
 #include "ui/aura/client/window_parenting_client.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/display/display.h"
 #include "ui/views/background.h"
+#include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/native_widget_private.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
-namespace ash {
+namespace ui_devtools {
 namespace {
 
-using namespace ui::devtools::protocol;
+using namespace ui_devtools::protocol;
 
 const int kDefaultChildNodeCount = -1;
 const SkColor kBackgroundColor = SK_ColorRED;
@@ -88,7 +86,7 @@
 
 bool Equals(aura::Window* window, DOM::Node* node) {
   int children_count = static_cast<int>(window->children().size());
-  if (GetInternalWidgetForWindow(window))
+  if (views::Widget::GetWidgetForNativeView(window))
     children_count++;
   return "Window" == node->getNodeName() &&
          window->GetName() == GetAttributeValue("name", node) &&
@@ -173,53 +171,83 @@
   aura::Window* highlighting_window = GetHighlightingWindow(root_window);
   EXPECT_TRUE(highlighting_window->IsVisible());
   EXPECT_EQ(bounds, highlighting_window->GetBoundsInScreen());
-  EXPECT_EQ(kBackgroundColor, GetInternalWidgetForWindow(highlighting_window)
-                                  ->GetRootView()
-                                  ->background()
-                                  ->get_color());
+  EXPECT_EQ(kBackgroundColor,
+            views::Widget::GetWidgetForNativeView(highlighting_window)
+                ->GetRootView()
+                ->background()
+                ->get_color());
 }
 
 }  // namespace
 
-class AshDevToolsTest : public test::AshTestBase {
+class UIDevToolsTest : public views::ViewsTestBase {
  public:
-  AshDevToolsTest() {}
-  ~AshDevToolsTest() override {}
+  UIDevToolsTest() {}
+  ~UIDevToolsTest() override {}
 
   views::internal::NativeWidgetPrivate* CreateTestNativeWidget() {
     views::Widget* widget = new views::Widget;
     views::Widget::InitParams params;
     params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
+    params.parent = GetPrimaryRootWindow();
     widget->Init(params);
     return widget->native_widget_private();
   }
 
   std::unique_ptr<views::Widget> CreateTestWidget(const gfx::Rect& bounds) {
-    return AshTestBase::CreateTestWidget(nullptr, kShellWindowId_Invalid,
-                                         bounds);
+    std::unique_ptr<views::Widget> widget(new views::Widget);
+    views::Widget::InitParams params;
+    params.delegate = nullptr;
+    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    params.bounds = bounds;
+    params.parent = GetPrimaryRootWindow();
+    widget->Init(params);
+    widget->Show();
+    return widget;
+  }
+
+  std::unique_ptr<aura::Window> CreateChildWindow(
+      aura::Window* parent,
+      aura::client::WindowType type = aura::client::WINDOW_TYPE_NORMAL) {
+    std::unique_ptr<aura::Window> window =
+        base::MakeUnique<aura::Window>(nullptr, type);
+    window->Init(ui::LAYER_NOT_DRAWN);
+    window->SetBounds(gfx::Rect());
+    parent->AddChild(window.get());
+    window->Show();
+    return window;
   }
 
   void SetUp() override {
     fake_frontend_channel_ = base::MakeUnique<FakeFrontendChannel>();
     uber_dispatcher_ =
         base::MakeUnique<UberDispatcher>(fake_frontend_channel_.get());
-    dom_agent_ = base::MakeUnique<devtools::AshDevToolsDOMAgent>();
+    dom_agent_ = base::MakeUnique<ui_devtools::UIDevToolsDOMAgent>();
     dom_agent_->Init(uber_dispatcher_.get());
     css_agent_ =
-        base::MakeUnique<devtools::AshDevToolsCSSAgent>(dom_agent_.get());
+        base::MakeUnique<ui_devtools::UIDevToolsCSSAgent>(dom_agent_.get());
     css_agent_->Init(uber_dispatcher_.get());
     css_agent_->enable();
+
     // We need to create |dom_agent| first to observe creation of
-    // WindowTreeHosts in AshTestBase::SetUp().
-    AshTestBase::SetUp();
+    // WindowTreeHosts in ViewTestBase::SetUp().
+    views::ViewsTestBase::SetUp();
+
+    top_window = CreateChildWindow(GetPrimaryRootWindow());
+    top_default_container_window = CreateChildWindow(GetPrimaryRootWindow());
+    top_overlay_window = CreateChildWindow(GetPrimaryRootWindow(),
+                                           aura::client::WINDOW_TYPE_UNKNOWN);
   }
 
   void TearDown() override {
+    top_overlay_window.reset();
+    top_default_container_window.reset();
+    top_window.reset();
     css_agent_.reset();
     dom_agent_.reset();
     uber_dispatcher_.reset();
     fake_frontend_channel_.reset();
-    AshTestBase::TearDown();
+    views::ViewsTestBase::TearDown();
   }
 
   void ExpectChildNodeInserted(int parent_id, int prev_sibling_id) {
@@ -299,19 +327,23 @@
     return dom_agent()->root_windows()[0];
   }
 
-  devtools::AshDevToolsCSSAgent* css_agent() { return css_agent_.get(); }
-  devtools::AshDevToolsDOMAgent* dom_agent() { return dom_agent_.get(); }
+  ui_devtools::UIDevToolsCSSAgent* css_agent() { return css_agent_.get(); }
+  ui_devtools::UIDevToolsDOMAgent* dom_agent() { return dom_agent_.get(); }
+
+  std::unique_ptr<aura::Window> top_overlay_window;
+  std::unique_ptr<aura::Window> top_window;
+  std::unique_ptr<aura::Window> top_default_container_window;
 
  private:
   std::unique_ptr<UberDispatcher> uber_dispatcher_;
   std::unique_ptr<FakeFrontendChannel> fake_frontend_channel_;
-  std::unique_ptr<devtools::AshDevToolsDOMAgent> dom_agent_;
-  std::unique_ptr<devtools::AshDevToolsCSSAgent> css_agent_;
+  std::unique_ptr<ui_devtools::UIDevToolsDOMAgent> dom_agent_;
+  std::unique_ptr<ui_devtools::UIDevToolsCSSAgent> css_agent_;
 
-  DISALLOW_COPY_AND_ASSIGN(AshDevToolsTest);
+  DISALLOW_COPY_AND_ASSIGN(UIDevToolsTest);
 };
 
-TEST_F(AshDevToolsTest, GetDocumentWithWindowWidgetView) {
+TEST_F(UIDevToolsTest, GetDocumentWithWindowWidgetView) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* parent_window = widget->GetNativeWindow();
@@ -322,7 +354,7 @@
   views::View* child_view = new TestView("child_view");
   widget->GetRootView()->AddChildView(child_view);
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(parent_window, root.get());
@@ -339,13 +371,13 @@
   Compare(child_view, widget_children->get(0)->getChildren(nullptr)->get(1));
 }
 
-TEST_F(AshDevToolsTest, GetDocumentNativeWidgetOwnsWidget) {
+TEST_F(UIDevToolsTest, GetDocumentNativeWidgetOwnsWidget) {
   views::internal::NativeWidgetPrivate* native_widget_private =
       CreateTestNativeWidget();
   views::Widget* widget = native_widget_private->GetWidget();
   aura::Window* parent_window = widget->GetNativeWindow();
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(parent_window, root.get());
@@ -356,9 +388,12 @@
   widget->CloseNow();
 }
 
-TEST_F(AshDevToolsTest, WindowAddedChildNodeInserted) {
+TEST_F(UIDevToolsTest, WindowAddedChildNodeInserted) {
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<aura::Window> window_child =
+      CreateChildWindow(top_window.get());
+
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   aura::Window* root_window = GetPrimaryRootWindow();
@@ -372,9 +407,12 @@
   ExpectChildNodeInserted(parent_node->getNodeId(), sibling_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, WindowDestroyedChildNodeRemoved) {
+TEST_F(UIDevToolsTest, WindowDestroyedChildNodeRemoved) {
+  std::unique_ptr<aura::Window> child_1 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_2 = CreateChildWindow(child_1.get());
+
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   aura::Window* root_window = GetPrimaryRootWindow();
@@ -388,13 +426,18 @@
 
   Compare(parent_window, parent_node);
   Compare(child_window, child_node);
-  delete child_window;
+  child_2.reset();
   ExpectChildNodeRemoved(parent_node->getNodeId(), child_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRearranged) {
+TEST_F(UIDevToolsTest, WindowReorganizedChildNodeRearranged) {
+  std::unique_ptr<aura::Window> child_1 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_2 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_11 = CreateChildWindow(child_1.get());
+  std::unique_ptr<aura::Window> child_21 = CreateChildWindow(child_2.get());
+
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   aura::Window* root_window = GetPrimaryRootWindow();
@@ -420,7 +463,12 @@
   ExpectChildNodeInserted(target_node->getNodeId(), sibling_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRemovedAndInserted) {
+TEST_F(UIDevToolsTest, WindowReorganizedChildNodeRemovedAndInserted) {
+  std::unique_ptr<aura::Window> child_1 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_2 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_21 = CreateChildWindow(child_2.get());
+  std::unique_ptr<aura::Window> child_22 = CreateChildWindow(child_2.get());
+
   aura::Window* root_window = GetPrimaryRootWindow();
   aura::Window* rotation_window = root_window->children()[0];
   aura::Window* parent_window = rotation_window->children()[0];
@@ -428,7 +476,7 @@
   std::unique_ptr<aura::Window> child_window(CreateChildWindow(parent_window));
 
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
   DOM::Node* root_node =
       root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0);
@@ -450,9 +498,13 @@
   ExpectChildNodeInserted(target_node->getNodeId(), sibling_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, WindowStackingChangedChildNodeRemovedAndInserted) {
+TEST_F(UIDevToolsTest, WindowStackingChangedChildNodeRemovedAndInserted) {
+  std::unique_ptr<aura::Window> child_11 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_12 = CreateChildWindow(top_window.get());
+  std::unique_ptr<aura::Window> child_13 = CreateChildWindow(top_window.get());
+
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   aura::Window* root_window = GetPrimaryRootWindow();
@@ -474,14 +526,14 @@
   ExpectChildNodeInserted(parent_id, sibling_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, ViewInserted) {
+TEST_F(UIDevToolsTest, ViewInserted) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* window = widget->GetNativeWindow();
   widget->Show();
 
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(window, root.get());
@@ -498,7 +550,7 @@
                           sibling_view_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, ViewRemoved) {
+TEST_F(UIDevToolsTest, ViewRemoved) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   // Need to store |view| in unique_ptr because it is removed from the widget
@@ -510,7 +562,7 @@
   root_view->AddChildView(child_view.get());
 
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(window, root.get());
@@ -528,7 +580,7 @@
                          child_view_node->getNodeId());
 }
 
-TEST_F(AshDevToolsTest, ViewRearranged) {
+TEST_F(UIDevToolsTest, ViewRearranged) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* window = widget->GetNativeWindow();
@@ -545,7 +597,7 @@
   parent_view->AddChildView(child_view_1);
 
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(window, root.get());
@@ -581,7 +633,7 @@
   ExpectChildNodeInserted(target_view_node->getNodeId(), 0);
 }
 
-TEST_F(AshDevToolsTest, ViewRearrangedRemovedAndInserted) {
+TEST_F(UIDevToolsTest, ViewRearrangedRemovedAndInserted) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* window = widget->GetNativeWindow();
@@ -595,7 +647,7 @@
   parent_view->AddChildView(child_view);
 
   // Initialize DOMAgent
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(window, root.get());
@@ -620,14 +672,14 @@
   ExpectChildNodeInserted(target_view_node->getNodeId(), 0);
 }
 
-TEST_F(AshDevToolsTest, WindowWidgetViewHighlight) {
+TEST_F(UIDevToolsTest, WindowWidgetViewHighlight) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(0, 0, 400, 400)));
   aura::Window* parent_window = widget->GetNativeWindow();
   std::unique_ptr<aura::Window> window(CreateChildWindow(parent_window));
   views::View* root_view = widget->GetRootView();
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(parent_window, root.get());
@@ -640,9 +692,9 @@
 
   HighlightNode(window_node->getNodeId());
   ExpectHighlighted(window->GetBoundsInScreen(), GetPrimaryRootWindow());
-  devtools::UIElement* element =
+  ui_devtools::UIElement* element =
       dom_agent()->GetElementFromNodeId(window_node->getNodeId());
-  ASSERT_EQ(devtools::UIElementType::WINDOW, element->type());
+  ASSERT_EQ(ui_devtools::UIElementType::WINDOW, element->type());
   EXPECT_EQ(element->GetNodeWindowAndBounds().first, window.get());
   EXPECT_EQ(element->GetNodeWindowAndBounds().second,
             window->GetBoundsInScreen());
@@ -653,7 +705,7 @@
   ExpectHighlighted(widget->GetWindowBoundsInScreen(), GetPrimaryRootWindow());
 
   element = dom_agent()->GetElementFromNodeId(widget_node->getNodeId());
-  ASSERT_EQ(devtools::UIElementType::WIDGET, element->type());
+  ASSERT_EQ(ui_devtools::UIElementType::WIDGET, element->type());
   EXPECT_EQ(element->GetNodeWindowAndBounds().first, widget->GetNativeWindow());
   EXPECT_EQ(element->GetNodeWindowAndBounds().second,
             widget->GetWindowBoundsInScreen());
@@ -664,7 +716,7 @@
   ExpectHighlighted(root_view->GetBoundsInScreen(), GetPrimaryRootWindow());
 
   element = dom_agent()->GetElementFromNodeId(root_view_node->getNodeId());
-  ASSERT_EQ(devtools::UIElementType::VIEW, element->type());
+  ASSERT_EQ(ui_devtools::UIElementType::VIEW, element->type());
   EXPECT_EQ(element->GetNodeWindowAndBounds().first,
             root_view->GetWidget()->GetNativeWindow());
   EXPECT_EQ(element->GetNodeWindowAndBounds().second,
@@ -677,15 +729,16 @@
   EXPECT_FALSE(GetHighlightingWindow(GetPrimaryRootWindow())->IsVisible());
 }
 
-int GetNodeIdFromWindow(devtools::UIElement* ui_element, aura::Window* window) {
+int GetNodeIdFromWindow(ui_devtools::UIElement* ui_element,
+                        aura::Window* window) {
   for (auto* child : ui_element->children()) {
-    if (child->type() == devtools::UIElementType::WINDOW &&
-        static_cast<devtools::WindowElement*>(child)->window() == window) {
+    if (child->type() == ui_devtools::UIElementType::WINDOW &&
+        static_cast<ui_devtools::WindowElement*>(child)->window() == window) {
       return child->node_id();
     }
   }
   for (auto* child : ui_element->children()) {
-    if (child->type() == devtools::UIElementType::WINDOW) {
+    if (child->type() == ui_devtools::UIElementType::WINDOW) {
       int node_id = GetNodeIdFromWindow(child, window);
       if (node_id > 0)
         return node_id;
@@ -697,7 +750,7 @@
 // TODO(thanhph): Make test AshDevToolsTest.MultipleDisplayHighlight work with
 // multiple displays. https://crbug.com/726831.
 
-TEST_F(AshDevToolsTest, WindowWidgetViewGetMatchedStylesForNode) {
+TEST_F(UIDevToolsTest, WindowWidgetViewGetMatchedStylesForNode) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* parent_window = widget->GetNativeWindow();
@@ -709,7 +762,7 @@
   widget->SetBounds(widget_bounds);
   widget->GetRootView()->SetBoundsRect(view_bounds);
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(parent_window, root.get());
@@ -723,13 +776,13 @@
                     view_bounds);
 }
 
-TEST_F(AshDevToolsTest, WindowWidgetViewStyleSheetChanged) {
+TEST_F(UIDevToolsTest, WindowWidgetViewStyleSheetChanged) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(1, 1, 1, 1)));
   aura::Window* widget_window = widget->GetNativeWindow();
   std::unique_ptr<aura::Window> child(CreateChildWindow(widget_window));
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   gfx::Rect child_bounds(2, 2, 3, 3);
@@ -747,21 +800,20 @@
   EXPECT_EQ(1, GetStyleSheetChangedCount(widget_node->getNodeId()));
   EXPECT_EQ(
       1, GetStyleSheetChangedCount(widget_node_children->get(1)->getNodeId()));
-  EXPECT_EQ(2,
-            GetStyleSheetChangedCount(widget_node_children->get(0)
-                                          ->getChildren(nullptr)
-                                          ->get(0)
-                                          ->getNodeId()));
+  EXPECT_EQ(2, GetStyleSheetChangedCount(widget_node_children->get(0)
+                                             ->getChildren(nullptr)
+                                             ->get(0)
+                                             ->getNodeId()));
 }
 
-TEST_F(AshDevToolsTest, WindowWidgetViewSetStyleText) {
+TEST_F(UIDevToolsTest, WindowWidgetViewSetStyleText) {
   std::unique_ptr<views::Widget> widget(
       CreateTestWidget(gfx::Rect(0, 0, 400, 400)));
   aura::Window* parent_window = widget->GetNativeWindow();
   std::unique_ptr<aura::Window> window(CreateChildWindow(parent_window));
   views::View* root_view = widget->GetRootView();
 
-  std::unique_ptr<ui::devtools::protocol::DOM::Node> root;
+  std::unique_ptr<ui_devtools::protocol::DOM::Node> root;
   dom_agent()->getDocument(&root);
 
   DOM::Node* parent_node = FindInRoot(parent_window, root.get());
@@ -826,4 +878,4 @@
   EXPECT_TRUE(root_view->visible());
 }
 
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/ash/devtools/ui_element.cc b/components/ui_devtools/views/ui_element.cc
similarity index 81%
rename from ash/devtools/ui_element.cc
rename to components/ui_devtools/views/ui_element.cc
index 0249d82..a44ff16 100644
--- a/ash/devtools/ui_element.cc
+++ b/components/ui_devtools/views/ui_element.cc
@@ -2,17 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/ui_element.h"
+#include "components/ui_devtools/views/ui_element.h"
 
 #include <algorithm>
 
-#include "ash/devtools/ui_element_delegate.h"
-#include "ash/devtools/view_element.h"
-#include "ash/devtools/widget_element.h"
-#include "ash/devtools/window_element.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
+#include "components/ui_devtools/views/view_element.h"
+#include "components/ui_devtools/views/widget_element.h"
+#include "components/ui_devtools/views/window_element.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 namespace {
 
 static int node_ids = 0;
@@ -63,7 +62,7 @@
   children_.erase(iter);
 
   // Move child to new position |new_index| in vector |children_|.
-  new_index = std::min(children_.size() - 1, static_cast<size_t>(new_index));
+  new_index = std::min(static_cast<int>(children_.size()) - 1, new_index);
   iter = children_.begin() + new_index;
   children_.insert(iter, child);
   delegate()->OnUIElementReordered(child->parent(), child);
@@ -76,5 +75,4 @@
   delegate_->OnUIElementAdded(0, this);
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/ash/devtools/ui_element.h b/components/ui_devtools/views/ui_element.h
similarity index 89%
rename from ash/devtools/ui_element.h
rename to components/ui_devtools/views/ui_element.h
index 8c752f1..dcd614a0 100644
--- a/ash/devtools/ui_element.h
+++ b/components/ui_devtools/views/ui_element.h
@@ -2,26 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_DEVTOOLS_UI_ELEMENT_H_
-#define ASH_DEVTOOLS_UI_ELEMENT_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_H_
 
 #include <vector>
 
-#include "ash/ash_export.h"
 #include "base/macros.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/view.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 class UIElementDelegate;
 
 // UIElement type.
 enum UIElementType { WINDOW, WIDGET, VIEW };
 
-class ASH_EXPORT UIElement {
+class UIElement {
  public:
   virtual ~UIElement();
   int node_id() const { return node_id_; };
@@ -72,7 +70,6 @@
   DISALLOW_COPY_AND_ASSIGN(UIElement);
 };
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
 
-#endif  // ASH_DEVTOOLS_UI_ELEMENT_H_
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_H_
diff --git a/ash/devtools/ui_element_delegate.h b/components/ui_devtools/views/ui_element_delegate.h
similarity index 76%
rename from ash/devtools/ui_element_delegate.h
rename to components/ui_devtools/views/ui_element_delegate.h
index 369b90b7..1f49c60f 100644
--- a/ash/devtools/ui_element_delegate.h
+++ b/components/ui_devtools/views/ui_element_delegate.h
@@ -2,21 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_DEVTOOLS_UI_ELEMENT_DELEGATE_H_
-#define ASH_DEVTOOLS_UI_ELEMENT_DELEGATE_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_DELEGATE_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_DELEGATE_H_
 
 #include <vector>
 
-#include "ash/ash_export.h"
 #include "base/macros.h"
 #include "ui/aura/window.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 class UIElement;
 
-class ASH_EXPORT UIElementDelegate {
+class UIElementDelegate {
  public:
   UIElementDelegate(){};
   virtual ~UIElementDelegate(){};
@@ -38,7 +36,6 @@
   DISALLOW_COPY_AND_ASSIGN(UIElementDelegate);
 };
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
 
-#endif  // ASH_DEVTOOLS_UI_ELEMENT_DELEGATE_H_
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_DELEGATE_H_
diff --git a/ash/devtools/view_element.cc b/components/ui_devtools/views/view_element.cc
similarity index 93%
rename from ash/devtools/view_element.cc
rename to components/ui_devtools/views/view_element.cc
index 862a454..e7080110 100644
--- a/ash/devtools/view_element.cc
+++ b/components/ui_devtools/views/view_element.cc
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/view_element.h"
+#include "components/ui_devtools/views/view_element.h"
 
-#include "ash/devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
 #include "ui/views/widget/widget.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 ViewElement::ViewElement(views::View* view,
                          UIElementDelegate* ui_element_delegate,
@@ -85,5 +84,4 @@
   return static_cast<ViewElement*>(element)->view_;
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/ash/devtools/view_element.h b/components/ui_devtools/views/view_element.h
similarity index 78%
rename from ash/devtools/view_element.h
rename to components/ui_devtools/views/view_element.h
index a5f0a38..37e46cc 100644
--- a/ash/devtools/view_element.h
+++ b/components/ui_devtools/views/view_element.h
@@ -2,23 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_DEVTOOLS_VIEW_ELEMENT_H_
-#define ASH_DEVTOOLS_VIEW_ELEMENT_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_VIEW_ELEMENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_VIEW_ELEMENT_H_
 
-#include "ash/ash_export.h"
-#include "ash/devtools/ui_element.h"
 #include "base/macros.h"
+#include "components/ui_devtools/views/ui_element.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/view.h"
 #include "ui/views/view_observer.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 class UIElementDelegate;
 
-class ASH_EXPORT ViewElement : public views::ViewObserver, public UIElement {
+class ViewElement : public views::ViewObserver, public UIElement {
  public:
   ViewElement(views::View* view,
               UIElementDelegate* ui_element_delegate,
@@ -46,7 +44,6 @@
   DISALLOW_COPY_AND_ASSIGN(ViewElement);
 };
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
 
-#endif  // ASH_DEVTOOLS_VIEW_ELEMENT_H_
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_VIEW_ELEMENT_H_
diff --git a/ash/devtools/widget_element.cc b/components/ui_devtools/views/widget_element.cc
similarity index 91%
rename from ash/devtools/widget_element.cc
rename to components/ui_devtools/views/widget_element.cc
index ec07a1f..7f87219b 100644
--- a/ash/devtools/widget_element.cc
+++ b/components/ui_devtools/views/widget_element.cc
@@ -2,12 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/widget_element.h"
+#include "components/ui_devtools/views/widget_element.h"
 
-#include "ash/devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 WidgetElement::WidgetElement(views::Widget* widget,
                              UIElementDelegate* ui_element_delegate,
@@ -69,5 +68,4 @@
   return static_cast<WidgetElement*>(element)->widget_;
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/ash/devtools/widget_element.h b/components/ui_devtools/views/widget_element.h
similarity index 74%
rename from ash/devtools/widget_element.h
rename to components/ui_devtools/views/widget_element.h
index c871578..9acc5eb 100644
--- a/ash/devtools/widget_element.h
+++ b/components/ui_devtools/views/widget_element.h
@@ -2,26 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_DEVTOOLS_WIDGET_ELEMENT_H_
-#define ASH_DEVTOOLS_WIDGET_ELEMENT_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_WIDGET_ELEMENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_WIDGET_ELEMENT_H_
 
-#include "ash/ash_export.h"
-#include "ash/devtools/ui_element.h"
 #include "base/macros.h"
+#include "components/ui_devtools/views/ui_element.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_observer.h"
 #include "ui/views/widget/widget_removals_observer.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
 class UIElementDelegate;
 
-class ASH_EXPORT WidgetElement : public views::WidgetRemovalsObserver,
-                                 public views::WidgetObserver,
-                                 public UIElement {
+class WidgetElement : public views::WidgetRemovalsObserver,
+                      public views::WidgetObserver,
+                      public UIElement {
  public:
   WidgetElement(views::Widget* widget,
                 UIElementDelegate* ui_element_delegate,
@@ -51,7 +49,6 @@
   DISALLOW_COPY_AND_ASSIGN(WidgetElement);
 };
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
 
-#endif  // ASH_DEVTOOLS_WIDGET_ELEMENT_H_
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_WIDGET_ELEMENT_H_
diff --git a/ash/devtools/window_element.cc b/components/ui_devtools/views/window_element.cc
similarity index 93%
rename from ash/devtools/window_element.cc
rename to components/ui_devtools/views/window_element.cc
index fa9ee2c..7faa860 100644
--- a/ash/devtools/window_element.cc
+++ b/components/ui_devtools/views/window_element.cc
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/devtools/window_element.h"
+#include "components/ui_devtools/views/window_element.h"
 
-#include "ash/devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/ui_element_delegate.h"
 #include "ui/aura/window.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 namespace {
 
 int GetIndexOfChildInParent(aura::Window* window) {
@@ -96,5 +95,4 @@
   return static_cast<WindowElement*>(element)->window_;
 }
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
diff --git a/ash/devtools/window_element.h b/components/ui_devtools/views/window_element.h
similarity index 79%
rename from ash/devtools/window_element.h
rename to components/ui_devtools/views/window_element.h
index 2f4996f4..2574eff 100644
--- a/ash/devtools/window_element.h
+++ b/components/ui_devtools/views/window_element.h
@@ -2,20 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_DEVTOOLS_WINDOW_ELEMENT_H_
-#define ASH_DEVTOOLS_WINDOW_ELEMENT_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_WINDOW_ELEMENT_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_WINDOW_ELEMENT_H_
 
-#include "ash/ash_export.h"
-#include "ash/devtools/ui_element.h"
 #include "base/macros.h"
+#include "components/ui_devtools/views/ui_element.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/geometry/rect.h"
 
-namespace ash {
-namespace devtools {
+namespace ui_devtools {
 
-class ASH_EXPORT WindowElement : public aura::WindowObserver, public UIElement {
+class WindowElement : public aura::WindowObserver, public UIElement {
  public:
   WindowElement(aura::Window* window,
                 UIElementDelegate* ui_element_delegate,
@@ -48,7 +46,6 @@
   DISALLOW_COPY_AND_ASSIGN(WindowElement);
 };
 
-}  // namespace devtools
-}  // namespace ash
+}  // namespace ui_devtools
 
-#endif  // ASH_DEVTOOLS_WINDOW_ELEMENT_H_
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_WINDOW_ELEMENT_H_
diff --git a/components/update_client/action_runner.cc b/components/update_client/action_runner.cc
index 5183fa3..965d857 100644
--- a/components/update_client/action_runner.cc
+++ b/components/update_client/action_runner.cc
@@ -22,10 +22,11 @@
 
 // The SHA256 of the SubjectPublicKeyInfo used to sign the recovery payload.
 // TODO(sorin): inject this value using the Configurator.
+// The CRX id is: gjpmebpgbhcamgdgjcmnjfhggjpgcimm
 constexpr uint8_t kPublicKeySHA256[] = {
-    0xd8, 0x40, 0x46, 0x12, 0xd2, 0x66, 0x9a, 0xf1, 0x0e, 0x64, 0x98,
-    0x36, 0x9d, 0xd5, 0x46, 0xe4, 0x52, 0xe8, 0x9b, 0x2d, 0x9b, 0x76,
-    0x84, 0x06, 0xc5, 0x5c, 0xb3, 0xb8, 0xf4, 0xc5, 0x80, 0x40};
+    0x69, 0xfc, 0x41, 0xf6, 0x17, 0x20, 0xc6, 0x36, 0x92, 0xcd, 0x95,
+    0x76, 0x69, 0xf6, 0x28, 0xcc, 0xbe, 0x98, 0x4b, 0x93, 0x17, 0xd6,
+    0x9c, 0xb3, 0x64, 0x0c, 0x0d, 0x25, 0x61, 0xc5, 0x80, 0x1d};
 
 std::vector<uint8_t> GetHash() {
   return std::vector<uint8_t>{std::begin(kPublicKeySHA256),
diff --git a/components/update_client/action_runner_win.cc b/components/update_client/action_runner_win.cc
index cc02f7ca..f6ce555 100644
--- a/components/update_client/action_runner_win.cc
+++ b/components/update_client/action_runner_win.cc
@@ -16,9 +16,8 @@
 
 namespace {
 
-// TODO(sorin): rename to "ChromeRecovery.exe".
 const base::FilePath::CharType kRecoveryFileName[] =
-    FILE_PATH_LITERAL("recovery.exe");
+    FILE_PATH_LITERAL("ChromeRecovery.exe");
 
 }  // namespace
 
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h
index 97f86ea..3470be1 100644
--- a/components/update_client/test_configurator.h
+++ b/components/update_client/test_configurator.h
@@ -53,11 +53,11 @@
                              0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b,
                              0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17};
 
-// runaction_test_win.crx and its payload id: nieaegbcncggjkpbaogejidgjnnfegoe
-const uint8_t niea_hash[] = {0xd8, 0x40, 0x46, 0x12, 0xd2, 0x66, 0x9a, 0xf1,
-                             0x0e, 0x64, 0x98, 0x36, 0x9d, 0xd5, 0x46, 0xe4,
-                             0x52, 0xe8, 0x9b, 0x2d, 0x9b, 0x76, 0x84, 0x06,
-                             0xc5, 0x5c, 0xb3, 0xb8, 0xf4, 0xc5, 0x80, 0x40};
+// runaction_test_win.crx and its payload id: gjpmebpgbhcamgdgjcmnjfhggjpgcimm
+const uint8_t gjpm_hash[] = {0x69, 0xfc, 0x41, 0xf6, 0x17, 0x20, 0xc6, 0x36,
+                             0x92, 0xcd, 0x95, 0x76, 0x69, 0xf6, 0x28, 0xcc,
+                             0xbe, 0x98, 0x4b, 0x93, 0x17, 0xd6, 0x9c, 0xb3,
+                             0x64, 0x0c, 0x0d, 0x25, 0x61, 0xc5, 0x80, 0x1d};
 
 class TestConfigurator : public Configurator {
  public:
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 03da14c..1275614 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -3045,7 +3045,7 @@
 
       <?xml version='1.0' encoding='UTF-8'?>
       <response protocol='3.1'>
-        <app appid='nieaegbcncggjkpbaogejidgjnnfegoe'>
+        <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
           <updatecheck status='ok'>
             <urls>
               <url codebase='http://localhost/download/'/>
@@ -3053,12 +3053,11 @@
             <manifest version='1.0' prodversionmin='11.0.1.0'>
               <packages>
                 <package name='runaction_test_win.crx3'
-                         hash_sha256='22deba85698e9ce1b923ad9839741adfd41db7ac35
-                                      8365664e47996dc8e83ec2'/>
+                         hash_sha256='89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea'/>
               </packages>
             </manifest>
             <actions>"
-             <action run='recovery.crx3'/>"
+             <action run='ChromeRecovery.crx3'/>"
             </actions>"
           </updatecheck>
         </app>
@@ -3067,14 +3066,14 @@
       EXPECT_TRUE(enabled_component_updates);
       EXPECT_EQ(1u, ids_to_check.size());
 
-      const std::string id = "nieaegbcncggjkpbaogejidgjnnfegoe";
+      const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
       EXPECT_EQ(id, ids_to_check[0]);
       EXPECT_EQ(1u, components.count(id));
 
       ProtocolParser::Result::Manifest::Package package;
       package.name = "runaction_test_win.crx3";
       package.hash_sha256 =
-          "22deba85698e9ce1b923ad9839741adfd41db7ac358365664e47996dc8e83ec2";
+          "89290a0d2ff21ca5b45e109c6cc859ab5fe294e19c102d54acd321429c372cea";
 
       ProtocolParser::Result result;
       result.extension_id = id;
@@ -3083,7 +3082,7 @@
       result.manifest.version = "1.0";
       result.manifest.browser_min_version = "11.0.1.0";
       result.manifest.packages.push_back(package);
-      result.action_run = "recovery.crx3";
+      result.action_run = "ChromeRecovery.crx3";
 
       auto& component = components.at(id);
       component->SetParseResult(result);
@@ -3166,12 +3165,12 @@
 
   // The action is a program which returns 1877345072 as a hardcoded value.
   update_client->Install(
-      std::string("nieaegbcncggjkpbaogejidgjnnfegoe"),
+      std::string("gjpmebpgbhcamgdgjcmnjfhggjpgcimm"),
       base::Bind([](const std::vector<std::string>& ids,
                     std::vector<CrxComponent>* components) {
         CrxComponent crx;
         crx.name = "test_niea";
-        crx.pk_hash.assign(niea_hash, niea_hash + arraysize(niea_hash));
+        crx.pk_hash.assign(gjpm_hash, gjpm_hash + arraysize(gjpm_hash));
         crx.version = base::Version("0.0");
         crx.installer = base::MakeRefCounted<VersionedTestInstaller>();
         components->push_back(crx);
@@ -3208,17 +3207,17 @@
 
       <?xml version='1.0' encoding='UTF-8'?>
       <response protocol='3.1'>
-        <app appid='nieaegbcncggjkpbaogejidgjnnfegoe'>
+        <app appid='gjpmebpgbhcamgdgjcmnjfhggjpgcimm'>
           <updatecheck status='noupdate'>
             <actions>"
-             <action run='recovery.crx3'/>"
+             <action run=ChromeRecovery.crx3'/>"
             </actions>"
           </updatecheck>
         </app>
       </response>
       */
       EXPECT_EQ(1u, ids_to_check.size());
-      const std::string id = "nieaegbcncggjkpbaogejidgjnnfegoe";
+      const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
       EXPECT_EQ(id, ids_to_check[0]);
       EXPECT_EQ(1u, components.count(id));
 
@@ -3227,7 +3226,7 @@
       ProtocolParser::Result result;
       result.extension_id = id;
       result.status = "noupdate";
-      result.action_run = "recovery.crx3";
+      result.action_run = "ChromeRecovery.crx3";
 
       component->SetParseResult(result);
 
@@ -3276,7 +3275,7 @@
     base::Closure quit_closure = runloop.QuitClosure();
 
     scoped_refptr<ComponentUnpacker> component_unpacker = new ComponentUnpacker(
-        std::vector<uint8_t>(std::begin(niea_hash), std::end(niea_hash)),
+        std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
         TestFilePath("runaction_test_win.crx3"), nullptr, nullptr,
         config()->GetSequencedTaskRunner());
 
@@ -3296,9 +3295,9 @@
   EXPECT_FALSE(unpack_path.empty());
   EXPECT_TRUE(base::DirectoryExists(unpack_path));
   int64_t file_size = 0;
-  EXPECT_TRUE(
-      base::GetFileSize(unpack_path.AppendASCII("recovery.crx3"), &file_size));
-  EXPECT_EQ(44565, file_size);
+  EXPECT_TRUE(base::GetFileSize(unpack_path.AppendASCII("ChromeRecovery.crx3"),
+                                &file_size));
+  EXPECT_EQ(44582, file_size);
 
   base::ScopedTempDir unpack_path_owner;
   EXPECT_TRUE(unpack_path_owner.Set(unpack_path));
@@ -3309,7 +3308,7 @@
           &FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
 
   // The action is a program which returns 1877345072 as a hardcoded value.
-  const std::vector<std::string> ids = {"nieaegbcncggjkpbaogejidgjnnfegoe"};
+  const std::vector<std::string> ids = {"gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
   update_client->Update(
       ids,
       base::Bind(
@@ -3318,7 +3317,7 @@
              std::vector<CrxComponent>* components) {
             CrxComponent crx;
             crx.name = "test_niea";
-            crx.pk_hash.assign(niea_hash, niea_hash + arraysize(niea_hash));
+            crx.pk_hash.assign(gjpm_hash, gjpm_hash + arraysize(gjpm_hash));
             crx.version = base::Version("1.0");
             crx.installer =
                 base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
diff --git a/components/webdata/common/BUILD.gn b/components/webdata/common/BUILD.gn
index c107b5a..1fe0781 100644
--- a/components/webdata/common/BUILD.gn
+++ b/components/webdata/common/BUILD.gn
@@ -58,7 +58,6 @@
     "//components/test/data/web_database/version_69.sql",
     "//components/test/data/web_database/version_70.sql",
     "//components/test/data/web_database/version_71.sql",
-    "//components/test/data/web_database/version_72.sql",
   ]
   outputs = [
     "{{bundle_resources_dir}}/" +
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index 496babf..072f025 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -13,7 +13,7 @@
 // corresponding changes must happen in the unit tests, and new migration test
 // added.  See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
 // static
-const int WebDatabase::kCurrentVersionNumber = 73;
+const int WebDatabase::kCurrentVersionNumber = 72;
 
 const int WebDatabase::kDeprecatedVersionNumber = 51;
 
@@ -29,15 +29,15 @@
   meta_table->SetVersionNumber(version_num);
   if (update_compatible_version_num) {
     meta_table->SetCompatibleVersionNumber(
-        std::min(version_num, kCompatibleVersionNumber));
+          std::min(version_num, kCompatibleVersionNumber));
   }
 }
 
 // Outputs the failed version number as a warning and always returns
 // |sql::INIT_FAILURE|.
 sql::InitStatus FailedMigrationTo(int version_num) {
-  LOG(WARNING) << "Unable to update web database to version " << version_num
-               << ".";
+  LOG(WARNING) << "Unable to update web database to version "
+               << version_num << ".";
   NOTREACHED();
   return sql::INIT_FAILURE;
 }
@@ -46,7 +46,8 @@
 
 WebDatabase::WebDatabase() {}
 
-WebDatabase::~WebDatabase() {}
+WebDatabase::~WebDatabase() {
+}
 
 void WebDatabase::AddTable(WebDatabaseTable* table) {
   tables_[table->GetTypeKey()] = table;
@@ -149,7 +150,8 @@
   DCHECK_GT(current_version, kDeprecatedVersionNumber);
 
   for (int next_version = current_version + 1;
-       next_version <= kCurrentVersionNumber; ++next_version) {
+       next_version <= kCurrentVersionNumber;
+       ++next_version) {
     // Do any database-wide migrations.
     bool update_compatible_version = false;
     if (!MigrateToVersion(next_version, &update_compatible_version))
@@ -173,7 +175,7 @@
 }
 
 bool WebDatabase::MigrateToVersion(int version,
-                                   bool* update_compatible_version) {
+                      bool* update_compatible_version) {
   // Migrate if necessary.
   switch (version) {
     case 58:
@@ -186,9 +188,10 @@
 
 bool WebDatabase::MigrateToVersion58DropWebAppsAndIntents() {
   sql::Transaction transaction(&db_);
-  return transaction.Begin() && db_.Execute("DROP TABLE IF EXISTS web_apps") &&
-         db_.Execute("DROP TABLE IF EXISTS web_app_icons") &&
-         db_.Execute("DROP TABLE IF EXISTS web_intents") &&
-         db_.Execute("DROP TABLE IF EXISTS web_intents_defaults") &&
-         transaction.Commit();
+  return transaction.Begin() &&
+      db_.Execute("DROP TABLE IF EXISTS web_apps") &&
+      db_.Execute("DROP TABLE IF EXISTS web_app_icons") &&
+      db_.Execute("DROP TABLE IF EXISTS web_intents") &&
+      db_.Execute("DROP TABLE IF EXISTS web_intents_defaults") &&
+      transaction.Commit();
 }
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index 1f494485..4417725 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -103,7 +103,7 @@
     source_path = source_path.AppendASCII("web_database");
     source_path = source_path.Append(file);
     return base::PathExists(source_path) &&
-           base::ReadFileToString(source_path, contents);
+        base::ReadFileToString(source_path, contents);
   }
 
   static int VersionFromConnection(sql::Connection* connection) {
@@ -130,7 +130,7 @@
   DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
 };
 
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 73;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 72;
 
 void WebDatabaseMigrationTest::LoadDatabase(
     const base::FilePath::StringType& file) {
@@ -207,7 +207,8 @@
 
 // Versions below 52 are deprecated. This verifies that old databases are razed.
 TEST_F(WebDatabaseMigrationTest, RazeDeprecatedVersionAndReinit) {
-  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_50.sql")));
+  ASSERT_NO_FATAL_FAILURE(
+      LoadDatabase(FILE_PATH_LITERAL("version_50.sql")));
 
   // Verify pre-conditions.  These are expectations for version 50 of the
   // database.
@@ -220,14 +221,14 @@
     ASSERT_TRUE(meta_table.Init(&connection, 50, 50));
 
     ASSERT_FALSE(connection.DoesColumnExist("keywords", "image_url"));
-    ASSERT_FALSE(
-        connection.DoesColumnExist("keywords", "search_url_post_params"));
-    ASSERT_FALSE(
-        connection.DoesColumnExist("keywords", "suggest_url_post_params"));
-    ASSERT_FALSE(
-        connection.DoesColumnExist("keywords", "instant_url_post_params"));
-    ASSERT_FALSE(
-        connection.DoesColumnExist("keywords", "image_url_post_params"));
+    ASSERT_FALSE(connection.DoesColumnExist("keywords",
+                                            "search_url_post_params"));
+    ASSERT_FALSE(connection.DoesColumnExist("keywords",
+                                            "suggest_url_post_params"));
+    ASSERT_FALSE(connection.DoesColumnExist("keywords",
+                                            "instant_url_post_params"));
+    ASSERT_FALSE(connection.DoesColumnExist("keywords",
+                                            "image_url_post_params"));
   }
 
   DoMigration();
@@ -244,21 +245,22 @@
 
     // New columns should have been created.
     EXPECT_TRUE(connection.DoesColumnExist("keywords", "image_url"));
-    EXPECT_TRUE(
-        connection.DoesColumnExist("keywords", "search_url_post_params"));
-    EXPECT_TRUE(
-        connection.DoesColumnExist("keywords", "suggest_url_post_params"));
-    EXPECT_TRUE(
-        connection.DoesColumnExist("keywords", "instant_url_post_params"));
-    EXPECT_TRUE(
-        connection.DoesColumnExist("keywords", "image_url_post_params"));
+    EXPECT_TRUE(connection.DoesColumnExist("keywords",
+                                           "search_url_post_params"));
+    EXPECT_TRUE(connection.DoesColumnExist("keywords",
+                                           "suggest_url_post_params"));
+    EXPECT_TRUE(connection.DoesColumnExist("keywords",
+                                           "instant_url_post_params"));
+    EXPECT_TRUE(connection.DoesColumnExist("keywords",
+                                           "image_url_post_params"));
   }
 }
 
 // Tests that the column |new_tab_url| is added to the keyword table schema for
 // a version 52 database.
 TEST_F(WebDatabaseMigrationTest, MigrateVersion52ToCurrent) {
-  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_52.sql")));
+  ASSERT_NO_FATAL_FAILURE(
+      LoadDatabase(FILE_PATH_LITERAL("version_52.sql")));
 
   // Verify pre-conditions.  These are expectations for version 52 of the
   // database.
@@ -346,11 +348,12 @@
     EXPECT_FALSE(connection.DoesColumnExist("autofill_profile_phones", "type"));
 
     // Data should have been preserved.
-    sql::Statement s_profiles(connection.GetUniqueStatement(
-        "SELECT guid, company_name, street_address, dependent_locality,"
-        " city, state, zipcode, sorting_code, country_code, date_modified,"
-        " origin "
-        "FROM autofill_profiles"));
+    sql::Statement s_profiles(
+        connection.GetUniqueStatement(
+            "SELECT guid, company_name, street_address, dependent_locality,"
+            " city, state, zipcode, sorting_code, country_code, date_modified,"
+            " origin "
+            "FROM autofill_profiles"));
 
     // Address lines 1 and 2.
     ASSERT_TRUE(s_profiles.Step());
@@ -423,8 +426,9 @@
     EXPECT_FALSE(s_profiles.Step());
 
     // Verify the phone number data as well.
-    sql::Statement s_phones(connection.GetUniqueStatement(
-        "SELECT guid, number FROM autofill_profile_phones"));
+    sql::Statement s_phones(
+        connection.GetUniqueStatement(
+            "SELECT guid, number FROM autofill_profile_phones"));
 
     ASSERT_TRUE(s_phones.Step());
     EXPECT_EQ("00000000-0000-0000-0000-000000000001", s_phones.ColumnString(0));
@@ -555,11 +559,12 @@
 
     // Data should have been preserved.  Note that it appears out of order
     // relative to the previous table, as it's been alphabetized.  That's ok.
-    sql::Statement s(connection.GetUniqueStatement(
-        "SELECT name, value, value_lower, date_created, date_last_used,"
-        " count "
-        "FROM autofill "
-        "ORDER BY name, value ASC"));
+    sql::Statement s(
+        connection.GetUniqueStatement(
+            "SELECT name, value, value_lower, date_created, date_last_used,"
+            " count "
+            "FROM autofill "
+            "ORDER BY name, value ASC"));
 
     // "jane.doe@example.org": Timestamps should be parsed correctly, and only
     // the first and last should be kept.
@@ -639,17 +644,19 @@
 
     // Data should have been preserved. Language code should have been set to
     // empty string.
-    sql::Statement s_profiles(connection.GetUniqueStatement(
-        "SELECT guid, company_name, street_address, dependent_locality,"
-        " city, state, zipcode, sorting_code, country_code, date_modified,"
-        " origin, language_code "
-        "FROM autofill_profiles"));
+    sql::Statement s_profiles(
+        connection.GetUniqueStatement(
+            "SELECT guid, company_name, street_address, dependent_locality,"
+            " city, state, zipcode, sorting_code, country_code, date_modified,"
+            " origin, language_code "
+            "FROM autofill_profiles"));
 
     ASSERT_TRUE(s_profiles.Step());
     EXPECT_EQ("00000000-0000-0000-0000-000000000001",
               s_profiles.ColumnString(0));
     EXPECT_EQ(ASCIIToUTF16("Google Inc"), s_profiles.ColumnString16(1));
-    EXPECT_EQ(ASCIIToUTF16("340 Main St"), s_profiles.ColumnString16(2));
+    EXPECT_EQ(ASCIIToUTF16("340 Main St"),
+              s_profiles.ColumnString16(2));
     EXPECT_EQ(base::string16(), s_profiles.ColumnString16(3));
     EXPECT_EQ(ASCIIToUTF16("Los Angeles"), s_profiles.ColumnString16(4));
     EXPECT_EQ(ASCIIToUTF16("CA"), s_profiles.ColumnString16(5));
@@ -682,9 +689,10 @@
         connection.DoesColumnExist("autofill_profile_names", "full_name"));
 
     // Verify the starting data.
-    sql::Statement s_names(connection.GetUniqueStatement(
-        "SELECT guid, first_name, middle_name, last_name "
-        "FROM autofill_profile_names"));
+    sql::Statement s_names(
+        connection.GetUniqueStatement(
+            "SELECT guid, first_name, middle_name, last_name "
+            "FROM autofill_profile_names"));
     ASSERT_TRUE(s_names.Step());
     EXPECT_EQ("B41FE6E0-B13E-2A2A-BF0B-29FCE2C3ADBD", s_names.ColumnString(0));
     EXPECT_EQ(ASCIIToUTF16("Jon"), s_names.ColumnString16(1));
@@ -711,9 +719,10 @@
 
     // Data should have been preserved. Full name should have been set to the
     // empty string.
-    sql::Statement s_names(connection.GetUniqueStatement(
-        "SELECT guid, first_name, middle_name, last_name, full_name "
-        "FROM autofill_profile_names"));
+    sql::Statement s_names(
+        connection.GetUniqueStatement(
+            "SELECT guid, first_name, middle_name, last_name, full_name "
+            "FROM autofill_profile_names"));
 
     ASSERT_TRUE(s_names.Step());
     EXPECT_EQ("B41FE6E0-B13E-2A2A-BF0B-29FCE2C3ADBD", s_names.ColumnString(0));
@@ -769,8 +778,7 @@
 TEST_F(WebDatabaseMigrationTest, MigrateVersion58ToCurrent) {
   ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_58.sql")));
 
-  const char query_extensions[] =
-      "SELECT * FROM keywords "
+  const char query_extensions[] = "SELECT * FROM keywords "
       "WHERE url='chrome-extension://iphchnegaodmijmkdlbhbanjhfphhikp/"
       "?q={searchTerms}'";
   // Verify pre-conditions.
@@ -810,9 +818,8 @@
     }
     EXPECT_EQ(0, count);
 
-    s.Assign(
-        connection.GetUniqueStatement("SELECT * FROM keywords "
-                                      "WHERE short_name='Google'"));
+    s.Assign(connection.GetUniqueStatement("SELECT * FROM keywords "
+        "WHERE short_name='Google'"));
     ASSERT_TRUE(s.is_valid());
     count = 0;
     while (s.Step()) {
@@ -908,10 +915,10 @@
     sql::MetaTable meta_table;
     ASSERT_TRUE(meta_table.Init(&connection, 61, 61));
 
-    EXPECT_FALSE(
-        connection.DoesColumnExist("unmasked_credit_cards", "use_count"));
-    EXPECT_FALSE(
-        connection.DoesColumnExist("unmasked_credit_cards", "use_date"));
+    EXPECT_FALSE(connection.DoesColumnExist("unmasked_credit_cards",
+                                            "use_count"));
+    EXPECT_FALSE(connection.DoesColumnExist("unmasked_credit_cards",
+                                            "use_date"));
   }
 
   DoMigration();
@@ -925,10 +932,10 @@
     // Check version.
     EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
 
-    EXPECT_TRUE(
-        connection.DoesColumnExist("unmasked_credit_cards", "use_count"));
-    EXPECT_TRUE(
-        connection.DoesColumnExist("unmasked_credit_cards", "use_date"));
+    EXPECT_TRUE(connection.DoesColumnExist("unmasked_credit_cards",
+                                           "use_count"));
+    EXPECT_TRUE(connection.DoesColumnExist("unmasked_credit_cards",
+                                           "use_date"));
   }
 }
 
@@ -949,9 +956,10 @@
     EXPECT_FALSE(connection.DoesTableExist("server_address_metadata"));
 
     // Add a server address --- make sure it gets an ID.
-    sql::Statement insert_profiles(connection.GetUniqueStatement(
-        "INSERT INTO server_addresses(id, postal_code) "
-        "VALUES ('', 90210)"));
+    sql::Statement insert_profiles(
+        connection.GetUniqueStatement(
+            "INSERT INTO server_addresses(id, postal_code) "
+            "VALUES ('', 90210)"));
     insert_profiles.Run();
   }
 
@@ -969,8 +977,9 @@
     EXPECT_TRUE(connection.DoesTableExist("server_card_metadata"));
     EXPECT_TRUE(connection.DoesTableExist("server_address_metadata"));
 
-    sql::Statement read_profiles(connection.GetUniqueStatement(
-        "SELECT id, postal_code FROM server_addresses"));
+    sql::Statement read_profiles(
+        connection.GetUniqueStatement(
+            "SELECT id, postal_code FROM server_addresses"));
     ASSERT_TRUE(read_profiles.Step());
     EXPECT_FALSE(read_profiles.ColumnString(0).empty());
     EXPECT_EQ("90210", read_profiles.ColumnString(1));
@@ -990,8 +999,8 @@
     sql::MetaTable meta_table;
     ASSERT_TRUE(meta_table.Init(&connection, 65, 65));
 
-    EXPECT_FALSE(
-        connection.DoesColumnExist("credit_cards", "billing_address_id"));
+    EXPECT_FALSE(connection.DoesColumnExist("credit_cards",
+                                            "billing_address_id"));
 
     EXPECT_TRUE(connection.Execute(
         "INSERT INTO credit_cards(guid, name_on_card) VALUES ('', 'Alice')"));
@@ -1008,8 +1017,8 @@
     // Check version.
     EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
 
-    EXPECT_TRUE(
-        connection.DoesColumnExist("credit_cards", "billing_address_id"));
+    EXPECT_TRUE(connection.DoesColumnExist("credit_cards",
+                                           "billing_address_id"));
 
     sql::Statement read_credit_cards(connection.GetUniqueStatement(
         "SELECT name_on_card, billing_address_id FROM credit_cards"));
@@ -1036,9 +1045,9 @@
     EXPECT_FALSE(connection.DoesColumnExist("masked_credit_cards",
                                             "billing_address_id"));
 
-    EXPECT_TRUE(
-        connection.Execute("INSERT INTO masked_credit_cards(id, name_on_card) "
-                           "VALUES ('id', 'Alice')"));
+    EXPECT_TRUE(connection.Execute(
+        "INSERT INTO masked_credit_cards(id, name_on_card) "
+        "VALUES ('id', 'Alice')"));
   }
 
   DoMigration();
@@ -1119,7 +1128,8 @@
     // Check version.
     EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
 
-    EXPECT_TRUE(connection.DoesColumnExist("keywords", "last_visited"));
+    EXPECT_TRUE(
+        connection.DoesColumnExist("keywords", "last_visited"));
   }
 }
 
@@ -1267,8 +1277,7 @@
     // Check version.
     EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
 
-    // Don't check for absence of "type", because that's added in version 73
-    // with a different meaning.
+    EXPECT_FALSE(connection.DoesColumnExist("masked_credit_cards", "type"));
     EXPECT_TRUE(connection.DoesColumnExist("masked_credit_cards", "network"));
 
     sql::Statement s_cards_metadata(connection.GetUniqueStatement(
@@ -1278,45 +1287,3 @@
     EXPECT_EQ("VISA", s_cards_metadata.ColumnString(1));
   }
 }
-
-// Tests adding "type" column for the "masked_credit_cards" table.
-TEST_F(WebDatabaseMigrationTest, MigrateVersion72ToCurrent) {
-  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_72.sql")));
-
-  // Verify pre-conditions.
-  {
-    sql::Connection connection;
-    ASSERT_TRUE(connection.Open(GetDatabasePath()));
-    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
-
-    sql::MetaTable meta_table;
-    ASSERT_TRUE(meta_table.Init(&connection, 72, 72));
-
-    EXPECT_FALSE(connection.DoesColumnExist("masked_credit_cards", "type"));
-
-    EXPECT_TRUE(
-        connection.Execute("INSERT INTO masked_credit_cards(id, network) "
-                           "VALUES ('id', 'VISA')"));
-  }
-
-  DoMigration();
-
-  // Verify post-conditions.
-  {
-    sql::Connection connection;
-    ASSERT_TRUE(connection.Open(GetDatabasePath()));
-    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
-
-    // Check version.
-    EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
-
-    EXPECT_TRUE(connection.DoesColumnExist("masked_credit_cards", "type"));
-
-    sql::Statement cards(connection.GetUniqueStatement(
-        "SELECT id, network, type FROM masked_credit_cards"));
-    ASSERT_TRUE(cards.Step());
-    EXPECT_EQ("id", cards.ColumnString(0));
-    EXPECT_EQ("VISA", cards.ColumnString(1));
-    EXPECT_EQ(CreditCard::CARD_TYPE_UNKNOWN, cards.ColumnInt(2));
-  }
-}
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc
index a120339..4f2295d 100644
--- a/content/browser/cache_storage/cache_storage_cache.cc
+++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -1455,7 +1455,7 @@
   // size. If the sizes aren't equal then there is a bug in how the cache size
   // is saved in the store's index.
   if (cache_size_ != CacheStorage::kSizeUnknown) {
-    LOG_IF(ERROR, cache_size_ != cache_size)
+    DLOG_IF(ERROR, cache_size_ != cache_size)
         << "Cache size: " << cache_size
         << " does not match size from index: " << cache_size_;
     UMA_HISTOGRAM_COUNTS_10M("ServiceWorkerCache.IndexSizeDifference",
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc
index 2ff78d2..3a00577 100644
--- a/content/browser/devtools/devtools_http_handler.cc
+++ b/content/browser/devtools/devtools_http_handler.cc
@@ -801,6 +801,7 @@
                       static_cast<int>(port_string.length())) < 0) {
     LOG(ERROR) << "Error writing DevTools active port to file";
   }
+  LOG(ERROR) << "\nDevTools listening on " << endpoint.ToString() << "\n";
 }
 
 void DevToolsHttpHandler::SendJson(int connection_id,
diff --git a/content/browser/frame_host/interstitial_page_navigator_impl.cc b/content/browser/frame_host/interstitial_page_navigator_impl.cc
index a240942a..e9cba3a 100644
--- a/content/browser/frame_host/interstitial_page_navigator_impl.cc
+++ b/content/browser/frame_host/interstitial_page_navigator_impl.cc
@@ -42,7 +42,7 @@
   render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
       url, redirect_chain, render_frame_host->frame_tree_node(),
       false,                 /* is_renderer_initiated */
-      false,                 /* is_synchronous */
+      false,                 /* is_same_document */
       navigation_start,      /* navigation_state */
       0,                     /* pending_nav_entry_id */
       false,                 /* started_in_context_menu */
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index 0ca2425..2ad3b58d 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -64,16 +64,17 @@
     const std::vector<GURL>& redirect_chain,
     FrameTreeNode* frame_tree_node,
     bool is_renderer_initiated,
-    bool is_same_page,
+    bool is_same_document,
     const base::TimeTicks& navigation_start,
     int pending_nav_entry_id,
     bool started_from_context_menu,
     CSPDisposition should_check_main_world_csp,
     bool is_form_submission) {
   return std::unique_ptr<NavigationHandleImpl>(new NavigationHandleImpl(
-      url, redirect_chain, frame_tree_node, is_renderer_initiated, is_same_page,
-      navigation_start, pending_nav_entry_id, started_from_context_menu,
-      should_check_main_world_csp, is_form_submission));
+      url, redirect_chain, frame_tree_node, is_renderer_initiated,
+      is_same_document, navigation_start, pending_nav_entry_id,
+      started_from_context_menu, should_check_main_world_csp,
+      is_form_submission));
 }
 
 NavigationHandleImpl::NavigationHandleImpl(
@@ -81,7 +82,7 @@
     const std::vector<GURL>& redirect_chain,
     FrameTreeNode* frame_tree_node,
     bool is_renderer_initiated,
-    bool is_same_page,
+    bool is_same_document,
     const base::TimeTicks& navigation_start,
     int pending_nav_entry_id,
     bool started_from_context_menu,
@@ -94,7 +95,7 @@
       net_error_code_(net::OK),
       render_frame_host_(nullptr),
       is_renderer_initiated_(is_renderer_initiated),
-      is_same_page_(is_same_page),
+      is_same_document_(is_same_document),
       was_redirected_(false),
       did_replace_entry_(false),
       should_update_history_(false),
@@ -171,7 +172,7 @@
         navigation_start, "Initial URL", url_.spec());
   }
 
-  if (is_same_page_) {
+  if (is_same_document_) {
     TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this,
                                  "Same document");
   }
@@ -309,7 +310,7 @@
 }
 
 bool NavigationHandleImpl::IsSameDocument() {
-  return is_same_page_;
+  return is_same_document_;
 }
 
 const net::HttpResponseHeaders* NavigationHandleImpl::GetResponseHeaders() {
@@ -784,8 +785,9 @@
     // navigation having been blocked with BLOCK_REQUEST_AND_COLLAPSE.
     if (!frame_tree_node()->IsMainFrame()) {
       // The last committed load in collapsed frames will be an error page with
-      // |kUnreachableWebDataURL|. Same-page navigation should not be possible.
-      DCHECK(!is_same_page_ || !frame_tree_node()->is_collapsed());
+      // |kUnreachableWebDataURL|. Same-document navigation should not be
+      // possible.
+      DCHECK(!is_same_document_ || !frame_tree_node()->is_collapsed());
       frame_tree_node()->SetCollapsed(false);
     }
   }
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index eb533214..f98451b 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -88,7 +88,7 @@
       const std::vector<GURL>& redirect_chain,
       FrameTreeNode* frame_tree_node,
       bool is_renderer_initiated,
-      bool is_same_page,
+      bool is_same_document,
       const base::TimeTicks& navigation_start,
       int pending_nav_entry_id,
       bool started_from_context_menu,
@@ -389,7 +389,7 @@
                        const std::vector<GURL>& redirect_chain,
                        FrameTreeNode* frame_tree_node,
                        bool is_renderer_initiated,
-                       bool is_same_page,
+                       bool is_same_document,
                        const base::TimeTicks& navigation_start,
                        int pending_nav_entry_id,
                        bool started_from_context_menu,
@@ -444,7 +444,7 @@
   net::Error net_error_code_;
   RenderFrameHostImpl* render_frame_host_;
   const bool is_renderer_initiated_;
-  const bool is_same_page_;
+  const bool is_same_document_;
   bool was_redirected_;
   bool did_replace_entry_;
   bool should_update_history_;
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 55f3127..c51df45d 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -230,7 +230,7 @@
   render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
       validated_url, validated_redirect_chain,
       render_frame_host->frame_tree_node(), is_renderer_initiated,
-      false,  // is_same_page
+      false,  // is_same_document
       navigation_start, pending_nav_entry_id, started_from_context_menu,
       CSPDisposition::CHECK,  // should_check_main_world_csp
       false));                // is_form_submission
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index d3f875d..c1a3487 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2880,9 +2880,6 @@
 
   GetInterfaceRegistry()->AddInterface(base::Bind(
       &KeyboardLockServiceImpl::CreateMojoService));
-
-  GetContentClient()->browser()->ExposeInterfacesToFrame(GetInterfaceRegistry(),
-                                                         this);
 }
 
 void RenderFrameHostImpl::ResetWaitingState() {
@@ -3921,11 +3918,15 @@
 void RenderFrameHostImpl::GetInterface(
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle interface_pipe) {
-  if (interface_registry_.get()) {
-    service_manager::BindSourceInfo source_info(
-        GetProcess()->GetChildIdentity(), service_manager::CapabilitySet());
+  service_manager::BindSourceInfo source_info(GetProcess()->GetChildIdentity(),
+                                              service_manager::CapabilitySet());
+  if (interface_registry_.get() &&
+      interface_registry_->CanBindInterface(interface_name)) {
     interface_registry_->BindInterface(source_info, interface_name,
                                        std::move(interface_pipe));
+  } else {
+    GetContentClient()->browser()->BindInterfaceRequestFromFrame(
+        this, source_info, interface_name, std::move(interface_pipe));
   }
 }
 
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index e1e43dd..84b9b9d 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -403,7 +403,12 @@
     }
   }
 
-  enum class FinalizeType { EVERYTHING, POWER_ONLY, CONTROLS_ONLY };
+  enum class FinalizeType {
+    EVERYTHING,
+    POWER_ONLY,
+    CONTROLS_ONLY,
+    DISPLAY_ONLY
+  };
   void FinalizeWatchTime(bool has_video,
                          const GURL& url,
                          int* underflow_count,
@@ -440,6 +445,10 @@
         RecordWatchTimeWithFilter(url, watch_time_info,
                                   watch_time_controls_keys_);
         break;
+      case FinalizeType::DISPLAY_ONLY:
+        RecordWatchTimeWithFilter(url, watch_time_info,
+                                  watch_time_display_keys_);
+        break;
     }
   }
 
@@ -461,6 +470,9 @@
   // Set of only the controls related watch time keys.
   const base::flat_set<base::StringPiece> watch_time_controls_keys_;
 
+  // Set of only the display related watch time keys.
+  const base::flat_set<base::StringPiece> watch_time_display_keys_;
+
   // Mapping of WatchTime metric keys to MeanTimeBetweenRebuffers (MTBR) and
   // smooth rate (had zero rebuffers) keys.
   struct RebufferMapping {
@@ -480,6 +492,7 @@
     : watch_time_keys_(media::GetWatchTimeKeys()),
       watch_time_power_keys_(media::GetWatchTimePowerKeys()),
       watch_time_controls_keys_(media::GetWatchTimeControlsKeys()),
+      watch_time_display_keys_(media::GetWatchTimeDisplayKeys()),
       rebuffer_keys_(
           {{media::kWatchTimeAudioSrc, media::kMeanTimeBetweenRebuffersAudioSrc,
             media::kRebuffersCountAudioSrc},
@@ -628,6 +641,17 @@
                             &player_info.watch_time_info,
                             FinalizeType::CONTROLS_ONLY);
         }
+
+        if (event.params.HasKey(media::kWatchTimeFinalizeDisplay)) {
+          bool should_finalize;
+          DCHECK(event.params.GetBoolean(media::kWatchTimeFinalizeDisplay,
+                                         &should_finalize) &&
+                 should_finalize);
+          FinalizeWatchTime(player_info.has_video, player_info.origin_url,
+                            &player_info.underflow_count,
+                            &player_info.watch_time_info,
+                            FinalizeType::DISPLAY_ONLY);
+        }
       }
       break;
     }
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc
index 940da64..c63b998 100644
--- a/content/browser/media/media_internals_unittest.cc
+++ b/content/browser/media/media_internals_unittest.cc
@@ -510,6 +510,7 @@
       {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
        media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
        media::kWatchTimeAudioVideoNativeControlsOff,
+       media::kWatchTimeAudioVideoDisplayInline,
        media::kWatchTimeAudioVideoEmbeddedExperience},
       kWatchTimeLate);
   ExpectMtbrTime({media::kMeanTimeBetweenRebuffersAudioVideoSrc,
@@ -520,7 +521,7 @@
                   2);
 
   ASSERT_EQ(1U, test_recorder_->sources_count());
-  ExpectUkmWatchTime(0, 5, kWatchTimeLate);
+  ExpectUkmWatchTime(0, 6, kWatchTimeLate);
   EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
 }
 
@@ -556,9 +557,11 @@
   wtr_.reset();
 
   std::vector<base::StringPiece> normal_keys = {
-      media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
+      media::kWatchTimeAudioVideoAll,
+      media::kWatchTimeAudioVideoSrc,
       media::kWatchTimeAudioVideoEme,
       media::kWatchTimeAudioVideoNativeControlsOff,
+      media::kWatchTimeAudioVideoDisplayInline,
       media::kWatchTimeAudioVideoEmbeddedExperience};
 
   for (auto key : watch_time_keys_) {
@@ -592,7 +595,7 @@
   // Spot check one of the non-AC keys; this relies on the assumption that the
   // AC metric is not last.
   const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
-  ASSERT_EQ(5U, metrics_vector.size());
+  ASSERT_EQ(6U, metrics_vector.size());
 }
 
 TEST_F(MediaInternalsWatchTimeTest, BasicControls) {
@@ -628,8 +631,11 @@
   wtr_.reset();
 
   std::vector<base::StringPiece> normal_keys = {
-      media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
-      media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
+      media::kWatchTimeAudioVideoAll,
+      media::kWatchTimeAudioVideoSrc,
+      media::kWatchTimeAudioVideoEme,
+      media::kWatchTimeAudioVideoAc,
+      media::kWatchTimeAudioVideoDisplayInline,
       media::kWatchTimeAudioVideoEmbeddedExperience};
 
   for (auto key : watch_time_keys_) {
@@ -661,7 +667,80 @@
   // Spot check one of the non-AC keys; this relies on the assumption that the
   // AC metric is not last.
   const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
-  ASSERT_EQ(5U, metrics_vector.size());
+  ASSERT_EQ(6U, metrics_vector.size());
+  EXPECT_EQ(kWatchTime3.InMilliseconds(), metrics_vector.back()->value);
+}
+
+TEST_F(MediaInternalsWatchTimeTest, BasicDisplay) {
+  constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
+  constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
+  constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
+  EXPECT_CALL(*this, GetCurrentMediaTime())
+      .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(kWatchTime1))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillRepeatedly(testing::Return(kWatchTime3));
+
+  Initialize(true, true, false, true);
+  wtr_->OnDisplayTypeFullscreen();
+  wtr_->OnPlaying();
+
+  // No log should have been generated yet since the message loop has not had
+  // any chance to pump.
+  CycleWatchTimeReporter();
+  ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
+
+  CycleWatchTimeReporter();
+
+  // Transition back to display inline, this should generate controls watch time
+  // as well.
+  wtr_->OnDisplayTypeInline();
+  CycleWatchTimeReporter();
+
+  // This should finalize the power watch time on display type.
+  ExpectWatchTime({media::kWatchTimeAudioVideoDisplayFullscreen}, kWatchTime2);
+  ResetHistogramTester();
+  wtr_.reset();
+
+  std::vector<base::StringPiece> normal_keys = {
+      media::kWatchTimeAudioVideoAll,
+      media::kWatchTimeAudioVideoSrc,
+      media::kWatchTimeAudioVideoEme,
+      media::kWatchTimeAudioVideoAc,
+      media::kWatchTimeAudioVideoNativeControlsOff,
+      media::kWatchTimeAudioVideoEmbeddedExperience};
+
+  for (auto key : watch_time_keys_) {
+    if (key == media::kWatchTimeAudioVideoDisplayInline) {
+      histogram_tester_->ExpectUniqueSample(
+          key.as_string(), (kWatchTime3 - kWatchTime2).InMilliseconds(), 1);
+      continue;
+    }
+
+    auto it = std::find(normal_keys.begin(), normal_keys.end(), key);
+    if (it == normal_keys.end()) {
+      histogram_tester_->ExpectTotalCount(key.as_string(), 0);
+    } else {
+      histogram_tester_->ExpectUniqueSample(key.as_string(),
+                                            kWatchTime3.InMilliseconds(), 1);
+    }
+  }
+
+  // Each finalize creates a new source and entry. We don't check the URL here
+  // since the TestUkmService() helpers DCHECK() a unique URL per source.
+  ASSERT_EQ(2U, test_recorder_->sources_count());
+  ASSERT_EQ(2U, test_recorder_->entries_count());
+  ExpectUkmWatchTime(0, 1, kWatchTime2);
+
+  // Verify Media.WatchTime keys are properly stripped for UKM reporting.
+  EXPECT_TRUE(test_recorder_->FindMetric(test_recorder_->GetEntry(0),
+                                         "AudioVideo.DisplayFullscreen"));
+
+  // Spot check one of the non-AC keys; this relies on the assumption that the
+  // AC metric is not last.
+  const auto& metrics_vector = test_recorder_->GetEntry(1)->metrics;
+  ASSERT_EQ(6U, metrics_vector.size());
   EXPECT_EQ(kWatchTime3.InMilliseconds(), metrics_vector.back()->value);
 }
 
@@ -700,6 +779,79 @@
   wtr_.reset();
 }
 
+TEST_F(MediaInternalsWatchTimeTest, PowerDisplayFinalize) {
+  constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
+  constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
+  constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
+  EXPECT_CALL(*this, GetCurrentMediaTime())
+      .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(kWatchTime1))
+      .WillOnce(testing::Return(kWatchTime1))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillRepeatedly(testing::Return(kWatchTime3));
+
+  Initialize(true, true, false, true);
+  wtr_->OnPlaying();
+
+  // No log should have been generated yet since the message loop has not had
+  // any chance to pump.
+  CycleWatchTimeReporter();
+  ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
+
+  CycleWatchTimeReporter();
+
+  // Transition display and power.
+  wtr_->OnDisplayTypePictureInPicture();
+  wtr_->OnPowerStateChangeForTesting(true);
+  CycleWatchTimeReporter();
+
+  // This should finalize the power and controls watch times.
+  ExpectWatchTime(
+      {media::kWatchTimeAudioVideoDisplayInline, media::kWatchTimeAudioVideoAc},
+      kWatchTime2);
+  ResetHistogramTester();
+  wtr_.reset();
+}
+
+TEST_F(MediaInternalsWatchTimeTest, PowerDisplayControlsFinalize) {
+  constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
+  constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(10);
+  constexpr base::TimeDelta kWatchTime3 = base::TimeDelta::FromSeconds(30);
+  EXPECT_CALL(*this, GetCurrentMediaTime())
+      .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(kWatchTime1))
+      .WillOnce(testing::Return(kWatchTime1))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillOnce(testing::Return(kWatchTime2))
+      .WillRepeatedly(testing::Return(kWatchTime3));
+
+  Initialize(true, true, false, true);
+  wtr_->OnPlaying();
+
+  // No log should have been generated yet since the message loop has not had
+  // any chance to pump.
+  CycleWatchTimeReporter();
+  ExpectWatchTime(std::vector<base::StringPiece>(), base::TimeDelta());
+
+  CycleWatchTimeReporter();
+
+  // Transition display and power.
+  wtr_->OnNativeControlsEnabled();
+  wtr_->OnDisplayTypeFullscreen();
+  wtr_->OnPowerStateChangeForTesting(true);
+  CycleWatchTimeReporter();
+
+  // This should finalize the power and controls watch times.
+  ExpectWatchTime({media::kWatchTimeAudioVideoDisplayInline,
+                   media::kWatchTimeAudioVideoNativeControlsOff,
+                   media::kWatchTimeAudioVideoAc},
+                  kWatchTime2);
+  ResetHistogramTester();
+  wtr_.reset();
+}
+
 TEST_F(MediaInternalsWatchTimeTest, BasicHidden) {
   constexpr base::TimeDelta kWatchTimeEarly = base::TimeDelta::FromSeconds(5);
   constexpr base::TimeDelta kWatchTimeLate = base::TimeDelta::FromSeconds(10);
@@ -770,13 +922,14 @@
       {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoMse,
        media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
        media::kWatchTimeAudioVideoNativeControlsOff,
+       media::kWatchTimeAudioVideoDisplayInline,
        media::kWatchTimeAudioVideoEmbeddedExperience},
       kWatchTimeLate);
   ExpectZeroRebuffers({media::kRebuffersCountAudioVideoMse,
                        media::kRebuffersCountAudioVideoEme});
 
   ASSERT_EQ(1U, test_recorder_->sources_count());
-  ExpectUkmWatchTime(0, 5, kWatchTimeLate);
+  ExpectUkmWatchTime(0, 6, kWatchTimeLate);
   EXPECT_TRUE(test_recorder_->GetSourceForUrl(kTestOrigin));
 }
 
@@ -804,6 +957,7 @@
       {media::kWatchTimeAudioVideoAll, media::kWatchTimeAudioVideoSrc,
        media::kWatchTimeAudioVideoEme, media::kWatchTimeAudioVideoAc,
        media::kWatchTimeAudioVideoNativeControlsOff,
+       media::kWatchTimeAudioVideoDisplayInline,
        media::kWatchTimeAudioVideoEmbeddedExperience},
       kWatchTimeLate);
   ExpectZeroRebuffers({media::kRebuffersCountAudioVideoSrc,
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index f09402d..b68f88a3 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -494,12 +494,10 @@
   return availability_url_;
 }
 
-void PresentationServiceImpl::ScreenAvailabilityListenerImpl
-::OnScreenAvailabilityChanged(bool available) {
-  service_->client_->OnScreenAvailabilityUpdated(
-      availability_url_, available
-                             ? blink::mojom::ScreenAvailability::AVAILABLE
-                             : blink::mojom::ScreenAvailability::UNAVAILABLE);
+void PresentationServiceImpl::ScreenAvailabilityListenerImpl::
+    OnScreenAvailabilityChanged(blink::mojom::ScreenAvailability availability) {
+  service_->client_->OnScreenAvailabilityUpdated(availability_url_,
+                                                 availability);
 }
 
 void PresentationServiceImpl::ScreenAvailabilityListenerImpl
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h
index d23ad25..85f1f4bf 100644
--- a/content/browser/presentation/presentation_service_impl.h
+++ b/content/browser/presentation/presentation_service_impl.h
@@ -125,7 +125,8 @@
 
     // PresentationScreenAvailabilityListener implementation.
     GURL GetAvailabilityUrl() const override;
-    void OnScreenAvailabilityChanged(bool available) override;
+    void OnScreenAvailabilityChanged(
+        blink::mojom::ScreenAvailability availability) override;
     void OnScreenAvailabilityNotSupported() override;
 
    private:
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc
index fe47a55..659f2f6a 100644
--- a/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -25,6 +25,7 @@
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
+using blink::mojom::ScreenAvailability;
 using ::testing::_;
 using ::testing::Eq;
 using ::testing::Mock;
@@ -203,8 +204,7 @@
     : public blink::mojom::PresentationServiceClient {
  public:
   MOCK_METHOD2(OnScreenAvailabilityUpdated,
-               void(const GURL& url,
-                    blink::mojom::ScreenAvailability availability));
+               void(const GURL& url, ScreenAvailability availability));
   MOCK_METHOD2(OnConnectionStateChanged,
                void(const PresentationInfo& connection,
                     PresentationConnectionState new_state));
@@ -294,17 +294,14 @@
     EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_delegate_));
   }
 
-  void SimulateScreenAvailabilityChangeAndWait(const GURL& url,
-                                               bool available) {
+  void SimulateScreenAvailabilityChangeAndWait(
+      const GURL& url,
+      ScreenAvailability availability) {
     auto listener_it = service_impl_->screen_availability_listeners_.find(url);
     ASSERT_TRUE(listener_it->second);
 
-    blink::mojom::ScreenAvailability expected_availability =
-        available ? blink::mojom::ScreenAvailability::AVAILABLE
-                  : blink::mojom::ScreenAvailability::UNAVAILABLE;
-    EXPECT_CALL(mock_client_,
-                OnScreenAvailabilityUpdated(url, expected_availability));
-    listener_it->second->OnScreenAvailabilityChanged(available);
+    EXPECT_CALL(mock_client_, OnScreenAvailabilityUpdated(url, availability));
+    listener_it->second->OnScreenAvailabilityChanged(availability);
     base::RunLoop().RunUntilIdle();
   }
 
@@ -337,9 +334,12 @@
 TEST_F(PresentationServiceImplTest, ListenForScreenAvailability) {
   ListenForScreenAvailabilityAndWait(presentation_url1_, true);
 
-  SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
-  SimulateScreenAvailabilityChangeAndWait(presentation_url1_, false);
-  SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
+  SimulateScreenAvailabilityChangeAndWait(presentation_url1_,
+                                          ScreenAvailability::AVAILABLE);
+  SimulateScreenAvailabilityChangeAndWait(presentation_url1_,
+                                          ScreenAvailability::UNAVAILABLE);
+  SimulateScreenAvailabilityChangeAndWait(presentation_url1_,
+                                          ScreenAvailability::AVAILABLE);
 }
 
 TEST_F(PresentationServiceImplTest, ScreenAvailabilityNotSupported) {
@@ -373,7 +373,8 @@
 
   // Availability is reported and callback is invoked since it was not
   // removed.
-  SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
+  SimulateScreenAvailabilityChangeAndWait(presentation_url1_,
+                                          ScreenAvailability::AVAILABLE);
 }
 
 TEST_F(PresentationServiceImplTest, ThisRenderFrameDeleted) {
@@ -398,7 +399,8 @@
 
   // Availability is reported and callback should be invoked since listener
   // has not been deleted.
-  SimulateScreenAvailabilityChangeAndWait(presentation_url1_, true);
+  SimulateScreenAvailabilityChangeAndWait(presentation_url1_,
+                                          ScreenAvailability::AVAILABLE);
 }
 
 TEST_F(PresentationServiceImplTest, DelegateFails) {
diff --git a/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h b/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
index ef8fed9..268b4576 100644
--- a/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
+++ b/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/containers/flat_set.h"
+#include "base/threading/thread_checker.h"
 #include "content/common/content_export.h"
 #include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
index 0cd11af..598d7a5a 100644
--- a/content/browser/webrtc/webrtc_image_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -22,6 +22,10 @@
 
 #if defined(OS_WIN)
 // These tests are flaky on WebRTC Windows bots: https://crbug.com/633242.
+// As a mitigation for https://crbug.com/722038, access to the image capture
+// controls has been put behind a feature flag kImageCaptureControls, which is
+// disabled by default on Windows. In order to re-activate these tests on
+// Windows, this feature must be enabled.
 #define MAYBE_GetPhotoCapabilities DISABLED_GetPhotoCapabilities
 #define MAYBE_GetPhotoSettings DISABLED_GetPhotoSettings
 #define MAYBE_TakePhoto DISABLED_TakePhoto
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 6bf72098..6fddeb9 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -648,11 +648,13 @@
       service_manager::BinderRegistry* registry,
       RenderFrameHost* render_frame_host) {}
 
-  // Allows to register browser Mojo interfaces exposed through the
-  // RenderFrameHost.
-  virtual void ExposeInterfacesToFrame(
-      service_manager::BinderRegistry* registry,
-      RenderFrameHost* render_frame_host) {}
+  // Content was unable to bind a request for this interface, so the embedder
+  // should try.
+  virtual void BindInterfaceRequestFromFrame(
+      RenderFrameHost* render_frame_host,
+      const service_manager::BindSourceInfo& source_info,
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle interface_pipe) {}
 
   // (Currently called only from GPUProcessHost, move somewhere more central).
   // Called when a request to bind |interface_name| on |interface_pipe| is
diff --git a/content/public/browser/navigation_handle.cc b/content/public/browser/navigation_handle.cc
index 8f8d99d..8eea81f 100644
--- a/content/public/browser/navigation_handle.cc
+++ b/content/public/browser/navigation_handle.cc
@@ -27,14 +27,14 @@
     RenderFrameHost* render_frame_host,
     bool committed,
     net::Error error,
-    bool is_same_page) {
+    bool is_same_document) {
   RenderFrameHostImpl* rfhi =
       static_cast<RenderFrameHostImpl*>(render_frame_host);
   std::unique_ptr<NavigationHandleImpl> handle_impl =
       NavigationHandleImpl::Create(
           url, std::vector<GURL>(), rfhi->frame_tree_node(),
           true,  // is_renderer_initiated
-          is_same_page, base::TimeTicks::Now(), 0,
+          is_same_document, base::TimeTicks::Now(), 0,
           false,                  // started_from_context_menu
           CSPDisposition::CHECK,  // should_check_main_world_csp
           false);                 // is_form_submission
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h
index 32af5114..82efc45 100644
--- a/content/public/browser/navigation_handle.h
+++ b/content/public/browser/navigation_handle.h
@@ -260,7 +260,7 @@
       RenderFrameHost* render_frame_host,
       bool committed = false,
       net::Error error = net::OK,
-      bool is_same_page = false);
+      bool is_same_document = false);
 
   // Registers a NavigationThrottle for tests. The throttle can
   // modify the request, pause the request or cancel the request. This will
diff --git a/content/public/browser/presentation_screen_availability_listener.h b/content/public/browser/presentation_screen_availability_listener.h
index 4fa18df..e37ddef 100644
--- a/content/public/browser/presentation_screen_availability_listener.h
+++ b/content/public/browser/presentation_screen_availability_listener.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -25,12 +26,13 @@
   virtual GURL GetAvailabilityUrl() const = 0;
 
   // Called when screen availability for the associated Presentation URL has
-  // changed to |available|.
-  virtual void OnScreenAvailabilityChanged(bool available) = 0;
+  // changed to |availability|.
+  virtual void OnScreenAvailabilityChanged(
+      blink::mojom::ScreenAvailability availability) = 0;
 
-  // Callend when screen availability monitoring is not supported by the
-  // by the implementation because of system limitations like running low on
-  // battery or having resource constraints.
+  // Called when screen availability monitoring is not supported by the
+  // implementation because of system limitations like running low on battery or
+  // having resource constraints.
   virtual void OnScreenAvailabilityNotSupported() = 0;
 };
 
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index a5b67e1..2b67c29 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -59,6 +59,12 @@
 }
 
 // static
+bool RenderFrameHostTester::TestOnMessageReceived(RenderFrameHost* rfh,
+                                                  const IPC::Message& msg) {
+  return static_cast<RenderFrameHostImpl*>(rfh)->OnMessageReceived(msg);
+}
+
+// static
 void RenderFrameHostTester::CommitPendingLoad(
     NavigationController* controller) {
   // This function is currently used by BrowserWithTestWindowTest. It would be
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h
index 8292ece..edbee84 100644
--- a/content/public/test/test_renderer_host.h
+++ b/content/public/test/test_renderer_host.h
@@ -58,6 +58,11 @@
   // RenderViewHostTestEnabler instance (see below) to do this.
   static RenderFrameHostTester* For(RenderFrameHost* host);
 
+  // Calls the RenderFrameHost's private OnMessageReceived function with the
+  // given message.
+  static bool TestOnMessageReceived(RenderFrameHost* rfh,
+                                    const IPC::Message& msg);
+
   static void CommitPendingLoad(NavigationController* controller);
 
   virtual ~RenderFrameHostTester() {}
diff --git a/content/renderer/media/webmediaplayer_ms_unittest.cc b/content/renderer/media/webmediaplayer_ms_unittest.cc
index 2afbe16..ed6aa0fa 100644
--- a/content/renderer/media/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -473,6 +473,9 @@
     return blink::WebMediaPlayer::TrackId();
   }
   bool HasNativeControls() override { return false; }
+  blink::WebMediaPlayer::DisplayType DisplayType() const override {
+    return blink::WebMediaPlayer::DisplayType::kInline;
+  }
 
   // Implementation of cc::VideoFrameProvider::Client
   void StopUsingProvider() override;
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index 0c6a517d..c2b44125 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -249,6 +249,7 @@
 
 BlinkTestController::BlinkTestController()
     : main_window_(NULL),
+      secondary_window_(nullptr),
       devtools_window_(nullptr),
       test_phase_(BETWEEN_TESTS),
       is_leak_detection_enabled_(
@@ -296,10 +297,9 @@
   current_working_directory_ = current_working_directory;
   enable_pixel_dumping_ = enable_pixel_dumping;
   expected_pixel_hash_ = expected_pixel_hash;
-  if (test_url.spec().find("/inspector-unit/") == std::string::npos)
-    test_url_ = test_url;
-  else
-    test_url_ = LayoutTestDevToolsBindings::MapJSTestURL(test_url);
+  bool is_devtools_js_test = false;
+  test_url_ = LayoutTestDevToolsBindings::MapTestURLIfNeeded(
+      test_url, &is_devtools_js_test);
   did_send_initial_test_configuration_ = false;
   printer_->reset();
   frame_to_layout_dump_map_.clear();
@@ -326,7 +326,10 @@
     current_pid_ = base::kNullProcessId;
     default_prefs_ =
       main_window_->web_contents()->GetRenderViewHost()->GetWebkitPreferences();
-    main_window_->LoadURL(test_url_);
+    if (is_devtools_js_test)
+      LoadDevToolsJSTest();
+    else
+      main_window_->LoadURL(test_url_);
   } else {
 #if defined(OS_MACOSX)
     // Shell::SizeTo is not implemented on all platforms.
@@ -352,12 +355,16 @@
     render_view_host->UpdateWebkitPreferences(default_prefs_);
     HandleNewRenderFrameHost(render_view_host->GetMainFrame());
 
-    NavigationController::LoadURLParams params(test_url_);
-    params.transition_type = ui::PageTransitionFromInt(
-        ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
-    params.should_clear_history_list = true;
-    main_window_->web_contents()->GetController().LoadURLWithParams(params);
-    main_window_->web_contents()->Focus();
+    if (is_devtools_js_test) {
+      LoadDevToolsJSTest();
+    } else {
+      NavigationController::LoadURLParams params(test_url_);
+      params.transition_type = ui::PageTransitionFromInt(
+          ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+      params.should_clear_history_list = true;
+      main_window_->web_contents()->GetController().LoadURLWithParams(params);
+      main_window_->web_contents()->Focus();
+    }
   }
   main_window_->web_contents()->GetRenderViewHost()->GetWidget()->SetActive(
       true);
@@ -365,6 +372,25 @@
   return true;
 }
 
+Shell* BlinkTestController::SecondaryWindow() {
+  if (!secondary_window_) {
+    ShellBrowserContext* browser_context =
+        ShellContentBrowserClient::Get()->browser_context();
+    secondary_window_ = content::Shell::CreateNewWindow(browser_context, GURL(),
+                                                        nullptr, initial_size_);
+  }
+  return secondary_window_;
+}
+
+void BlinkTestController::LoadDevToolsJSTest() {
+  devtools_window_ = main_window_;
+  Shell* secondary = SecondaryWindow();
+  devtools_bindings_.reset(LayoutTestDevToolsBindings::LoadDevTools(
+      devtools_window_->web_contents(), secondary->web_contents(), "",
+      test_url_.spec()));
+  secondary->LoadURL(GURL(url::kAboutBlankURL));
+}
+
 bool BlinkTestController::ResetAfterLayoutTest() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   printer_->PrintTextFooter();
@@ -379,6 +405,7 @@
   prefs_ = WebPreferences();
   should_override_prefs_ = false;
   LayoutTestContentBrowserClient::Get()->SetPopupBlockingEnabled(false);
+  devtools_bindings_.reset();
 
 #if defined(OS_ANDROID)
   // Re-using the shell's main window on Android causes issues with networking
@@ -843,13 +870,7 @@
 
 void BlinkTestController::OnShowDevTools(const std::string& settings,
                                          const std::string& frontend_url) {
-  if (!devtools_window_) {
-    ShellBrowserContext* browser_context =
-        ShellContentBrowserClient::Get()->browser_context();
-    devtools_window_ = content::Shell::CreateNewWindow(browser_context, GURL(),
-                                                       nullptr, initial_size_);
-  }
-
+  devtools_window_ = SecondaryWindow();
   devtools_bindings_.reset(LayoutTestDevToolsBindings::LoadDevTools(
       devtools_window_->web_contents(), main_window_->web_contents(), settings,
       frontend_url));
@@ -926,7 +947,7 @@
   DevToolsAgentHost::DetachAllClients();
   std::vector<Shell*> open_windows(Shell::windows());
   for (size_t i = 0; i < open_windows.size(); ++i) {
-    if (open_windows[i] != main_window_ && open_windows[i] != devtools_window_)
+    if (open_windows[i] != main_window_ && open_windows[i] != secondary_window_)
       open_windows[i]->Close();
   }
   base::RunLoop().RunUntilIdle();
diff --git a/content/shell/browser/layout_test/blink_test_controller.h b/content/shell/browser/layout_test/blink_test_controller.h
index 270ce4d..657ab60 100644
--- a/content/shell/browser/layout_test/blink_test_controller.h
+++ b/content/shell/browser/layout_test/blink_test_controller.h
@@ -194,6 +194,8 @@
 
   static BlinkTestController* instance_;
 
+  Shell* SecondaryWindow();
+  void LoadDevToolsJSTest();
   void DiscardMainWindow();
 
   // Message handlers.
@@ -234,6 +236,7 @@
   base::FilePath temp_path_;
 
   Shell* main_window_;
+  Shell* secondary_window_;
   Shell* devtools_window_;
 
   std::unique_ptr<LayoutTestDevToolsBindings> devtools_bindings_;
diff --git a/content/shell/browser/layout_test/layout_test_devtools_bindings.cc b/content/shell/browser/layout_test/layout_test_devtools_bindings.cc
index 529e1f99..2ec94572f 100644
--- a/content/shell/browser/layout_test/layout_test_devtools_bindings.cc
+++ b/content/shell/browser/layout_test/layout_test_devtools_bindings.cc
@@ -58,12 +58,26 @@
 }
 
 // static.
-GURL LayoutTestDevToolsBindings::MapJSTestURL(const GURL& test_url) {
+GURL LayoutTestDevToolsBindings::MapTestURLIfNeeded(const GURL& test_url,
+                                                    bool* is_devtools_js_test) {
+  std::string spec = test_url.spec();
+  *is_devtools_js_test = spec.find("/devtools-js/") != std::string::npos;
+  bool is_unit_test = spec.find("/inspector-unit/") != std::string::npos;
+  if (!*is_devtools_js_test && !is_unit_test)
+    return test_url;
+  return MapJSTestURL(test_url, is_unit_test ? "unit_test_runner.html"
+                                             : "integration_test_runner.html");
+}
+
+// static.
+GURL LayoutTestDevToolsBindings::MapJSTestURL(
+    const GURL& test_url,
+    const std::string& entry_filename) {
   std::string url_string = GetDevToolsPathAsURL(std::string()).spec();
   std::string inspector_file_name = "inspector.html";
   size_t start_position = url_string.find(inspector_file_name);
   url_string.replace(start_position, inspector_file_name.length(),
-                     "unit_test_runner.html");
+                     entry_filename);
   url_string += "&test=" + test_url.spec();
   return GURL(url_string);
 }
@@ -84,7 +98,6 @@
       ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
   bindings->web_contents()->GetController().LoadURLWithParams(params);
   bindings->web_contents()->Focus();
-  bindings->CreateFrontendHost();
   return bindings;
 }
 
diff --git a/content/shell/browser/layout_test/layout_test_devtools_bindings.h b/content/shell/browser/layout_test/layout_test_devtools_bindings.h
index 1b443e1..bf9a34fa 100644
--- a/content/shell/browser/layout_test/layout_test_devtools_bindings.h
+++ b/content/shell/browser/layout_test/layout_test_devtools_bindings.h
@@ -17,7 +17,8 @@
  public:
   static GURL GetDevToolsPathAsURL(const std::string& frontend_url);
 
-  static GURL MapJSTestURL(const GURL& test_url);
+  static GURL MapTestURLIfNeeded(const GURL& test_url,
+                                 bool* is_devtools_js_test);
 
   static LayoutTestDevToolsBindings* LoadDevTools(
       WebContents* devtools_contents_,
@@ -29,6 +30,9 @@
   ~LayoutTestDevToolsBindings() override;
 
  private:
+  static GURL MapJSTestURL(const GURL& test_url,
+                           const std::string& entry_filename);
+
   LayoutTestDevToolsBindings(WebContents* devtools_contents,
                              WebContents* inspected_contents);
 
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index ed558d4..c1a2808 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -143,7 +143,8 @@
 };
 
 void BindLayoutTestHelper(const service_manager::BindSourceInfo& source_info,
-                          mojom::MojoLayoutTestHelperRequest request) {
+                          mojom::MojoLayoutTestHelperRequest request,
+                          RenderFrameHost* render_frame_host) {
   mojo::MakeStrongBinding(base::MakeUnique<MojoLayoutTestHelper>(),
                           std::move(request));
 }
@@ -162,6 +163,7 @@
     : shell_browser_main_parts_(NULL) {
   DCHECK(!g_browser_client);
   g_browser_client = this;
+  frame_interfaces_.AddInterface(base::Bind(&BindLayoutTestHelper));
 }
 
 ShellContentBrowserClient::~ShellContentBrowserClient() {
@@ -218,10 +220,16 @@
   return false;
 }
 
-void ShellContentBrowserClient::ExposeInterfacesToFrame(
-    service_manager::BinderRegistry* registry,
-    RenderFrameHost* frame_host) {
-  registry->AddInterface(base::Bind(&BindLayoutTestHelper));
+void ShellContentBrowserClient::BindInterfaceRequestFromFrame(
+    RenderFrameHost* render_frame_host,
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  if (frame_interfaces_.CanBindInterface(interface_name)) {
+    frame_interfaces_.BindInterface(source_info, interface_name,
+                                    std::move(interface_pipe),
+                                    render_frame_host);
+  }
 }
 
 void ShellContentBrowserClient::RegisterInProcessServices(
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h
index 9e10d08..5bee942 100644
--- a/content/shell/browser/shell_content_browser_client.h
+++ b/content/shell/browser/shell_content_browser_client.h
@@ -14,6 +14,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
 #include "content/shell/browser/shell_speech_recognition_manager_delegate.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
 
 namespace content {
 
@@ -36,8 +37,11 @@
   bool DoesSiteRequireDedicatedProcess(BrowserContext* browser_context,
                                        const GURL& effective_site_url) override;
   bool IsHandledURL(const GURL& url) override;
-  void ExposeInterfacesToFrame(service_manager::BinderRegistry* registry,
-                               RenderFrameHost* frame_host) override;
+  void BindInterfaceRequestFromFrame(
+      content::RenderFrameHost* render_frame_host,
+      const service_manager::BindSourceInfo& source_info,
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle interface_pipe) override;
   void RegisterInProcessServices(StaticServiceMap* services) override;
   void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override;
   std::unique_ptr<base::Value> GetServiceManifestOverlay(
@@ -111,6 +115,9 @@
 
   base::Closure select_client_certificate_callback_;
 
+  service_manager::BinderRegistryWithParams<content::RenderFrameHost*>
+      frame_interfaces_;
+
   ShellBrowserMainParts* shell_browser_main_parts_;
 };
 
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc
index 8c07122..3bedaad 100644
--- a/content/shell/browser/shell_devtools_bindings.cc
+++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -137,8 +137,13 @@
     NavigationHandle* navigation_handle) {
 #if !defined(OS_ANDROID)
   content::RenderFrameHost* frame = navigation_handle->GetRenderFrameHost();
-  if (!frame->GetParent())
+  if (navigation_handle->IsInMainFrame()) {
+    frontend_host_.reset(DevToolsFrontendHost::Create(
+        frame,
+        base::Bind(&ShellDevToolsBindings::HandleMessageFromDevToolsFrontend,
+                   base::Unretained(this))));
     return;
+  }
   std::string origin = navigation_handle->GetURL().GetOrigin().spec();
   auto it = extensions_api_.find(origin);
   if (it == extensions_api_.end())
@@ -149,26 +154,6 @@
 #endif
 }
 
-void ShellDevToolsBindings::RenderViewCreated(
-    RenderViewHost* render_view_host) {
-  CreateFrontendHost();
-}
-
-#if !defined(OS_ANDROID)
-void ShellDevToolsBindings::CreateFrontendHost() {
-  if (!frontend_host_) {
-    frontend_host_.reset(DevToolsFrontendHost::Create(
-        web_contents()->GetMainFrame(),
-        base::Bind(&ShellDevToolsBindings::HandleMessageFromDevToolsFrontend,
-                   base::Unretained(this))));
-  }
-}
-#endif
-
-#if defined(OS_ANDROID)
-void ShellDevToolsBindings::CreateFrontendHost() {}
-#endif
-
 void ShellDevToolsBindings::DocumentAvailableInMainFrame() {
   agent_host_ = DevToolsAgentHost::GetOrCreateFor(inspected_contents_);
   agent_host_->AttachClient(this);
diff --git a/content/shell/browser/shell_devtools_bindings.h b/content/shell/browser/shell_devtools_bindings.h
index 13bc74bf0..924ab60 100644
--- a/content/shell/browser/shell_devtools_bindings.h
+++ b/content/shell/browser/shell_devtools_bindings.h
@@ -61,12 +61,10 @@
 
   void SetPreferences(const std::string& json);
   virtual void HandleMessageFromDevToolsFrontend(const std::string& message);
-  void CreateFrontendHost();
 
  private:
   // WebContentsObserver overrides
   void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override;
-  void RenderViewCreated(RenderViewHost* render_view_host) override;
   void DocumentAvailableInMainFrame() override;
   void WebContentsDestroyed() override;
 
diff --git a/content/shell/test_runner/test_interfaces.cc b/content/shell/test_runner/test_interfaces.cc
index 0131fdb..05e35fa 100644
--- a/content/shell/test_runner/test_interfaces.cc
+++ b/content/shell/test_runner/test_interfaces.cc
@@ -108,6 +108,7 @@
     test_runner_->SetV8CacheDisabled(false);
   }
   if (spec.find("/inspector/") != std::string::npos &&
+      spec.find("integration_test_runner.html") == std::string::npos &&
       spec.find("unit_test_runner.html") == std::string::npos) {
     // Subfolder name determines default panel to open.
     std::string test_path = spec.substr(spec.find("/inspector/") + 11);
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index 92a3a2d..8b4c0c5 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -55,6 +55,10 @@
     # TODO(zakerinasab): check / generate reference images.
     self.Fail('Pixel_Canvas2DUntagged', bug=713632)
 
+    # TODO(fmalita): remove when new baselines are available.
+    self.Fail('Pixel_CSSFilterEffects', bug=731693)
+    self.Fail('Pixel_CSSFilterEffects_NoOverlays', bug=731693)
+
     # Failures on Haswell GPUs on macOS after upgrade to 10.12.4.
     self.Fail('Pixel_OffscreenCanvas2DResizeOnWorker',
               ['mac', ('intel', 0x0a2e)], bug=718183)
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index e1b2f70..a780493e 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -484,12 +484,12 @@
       'filter_effects.html',
       base_name + '_CSSFilterEffects',
       test_rect=[0, 0, 300, 300],
-      revision=4),
+      revision=5),
     PixelTestPage(
       'filter_effects.html',
       base_name + '_CSSFilterEffects_NoOverlays',
       test_rect=[0, 0, 300, 300],
-      revision=4,
+      revision=5,
       tolerance=10,
       browser_args=['--disable-mac-overlays']),
   ]
diff --git a/device/sensors/device_sensor_host.h b/device/sensors/device_sensor_host.h
index b6aad4e..d6d5493 100644
--- a/device/sensors/device_sensor_host.h
+++ b/device/sensors/device_sensor_host.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/shared_memory.h"
+#include "base/threading/thread_checker.h"
 #include "device/sensors/device_sensors_consts.h"
 #include "device/sensors/public/interfaces/motion.mojom.h"
 #include "device/sensors/public/interfaces/orientation.mojom.h"
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
index 46174f3..a579c9f 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -29,8 +29,10 @@
 
 const CGFloat kMaxSearchFieldFrameMargin = 200;
 const CGFloat kDoodleTopMarginIPad = 82;
-const CGFloat kDoodleTopMarginIPhone = 56;
-const CGFloat kSearchFieldTopMarginIPhone = 16;
+const CGFloat kDoodleTopMarginIPhonePortrait = 66;
+const CGFloat kDoodleTopMarginIPhoneLandscape = 56;
+const CGFloat kSearchFieldTopMarginIPhonePortrait = 32;
+const CGFloat kSearchFieldTopMarginIPhoneLandscape = 16;
 const CGFloat kNTPSearchFieldBottomPadding = 16;
 
 const CGFloat kTopSpacingMaterialPortrait = 56;
@@ -91,13 +93,19 @@
 CGFloat doodleTopMargin() {
   if (IsIPadIdiom())
     return kDoodleTopMarginIPad;
-  return kDoodleTopMarginIPhone;
+  if (IsPortrait())
+    return kDoodleTopMarginIPhonePortrait;
+  return kDoodleTopMarginIPhoneLandscape;
 }
 
 CGFloat searchFieldTopMargin() {
-  if (IsIPadIdiom())
+  if (IsIPadIdiom()) {
     return kDoodleTopMarginIPad;
-  return kSearchFieldTopMarginIPhone;
+  } else if (IsPortrait()) {
+    return kSearchFieldTopMarginIPhonePortrait;
+  } else {
+    return kSearchFieldTopMarginIPhoneLandscape;
+  }
 }
 
 CGFloat searchFieldWidth(CGFloat superviewWidth) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm
index a46a48d..f31738e4 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm
@@ -99,7 +99,7 @@
   // Test.
   EXPECT_EQ(120, heightLogo);
   EXPECT_EQ(60, heightNoLogo);
-  EXPECT_EQ(56, topMargin);
+  EXPECT_EQ(66, topMargin);
 }
 
 TEST_F(ContentSuggestionsCollectionUtilsTest, doodleFrameIPhoneLandscape) {
@@ -148,7 +148,7 @@
   CGFloat topMargin = searchFieldTopMargin();
 
   // Test.
-  EXPECT_EQ(16, topMargin);
+  EXPECT_EQ(32, topMargin);
   EXPECT_EQ(width - 2 * margin, resultWidth);
 }
 
@@ -182,8 +182,8 @@
   SetAsIPhone();
 
   // Action, tests.
-  EXPECT_EQ(258, heightForLogoHeader(YES, YES));
-  EXPECT_EQ(258, heightForLogoHeader(YES, NO));
+  EXPECT_EQ(284, heightForLogoHeader(YES, YES));
+  EXPECT_EQ(284, heightForLogoHeader(YES, NO));
 }
 
 TEST_F(ContentSuggestionsCollectionUtilsTest, SizeIPhone6) {
diff --git a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
index e1455f2..447643f 100644
--- a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
@@ -54,6 +54,44 @@
 
 }  // namespace
 
+@interface GoogleLandingViewController (UsedByGoogleLandingView)
+// Update frames for subviews depending on the interface orientation.
+- (void)updateSubviewFrames;
+// Resets the collection view's inset to 0.
+- (void)resetSectionInset;
+- (void)reloadData;
+@end
+
+// Subclassing the main UIScrollView allows calls for setFrame.
+@interface GoogleLandingView : UIView {
+  GoogleLandingViewController* _googleLanding;
+}
+
+- (void)setFrameDelegate:(GoogleLandingViewController*)delegate;
+
+@end
+
+@implementation GoogleLandingView
+
+- (void)setFrameDelegate:(GoogleLandingViewController*)delegate {
+  _googleLanding = delegate;
+}
+
+- (void)setFrame:(CGRect)frame {
+  // On iPad and in fullscreen, the collection view's inset is very large.
+  // When Chrome enters slide over mode, the previously set inset is larger than
+  // the newly set collection view's width, which makes the collection view
+  // throw an exception.
+  // To prevent this from happening, we reset the inset to 0 before changing the
+  // frame.
+  [_googleLanding resetSectionInset];
+  [super setFrame:frame];
+  [_googleLanding updateSubviewFrames];
+  [_googleLanding reloadData];
+}
+
+@end
+
 @interface GoogleLandingViewController ()<OverscrollActionsControllerDelegate,
                                           UICollectionViewDataSource,
                                           UICollectionViewDelegate,
@@ -115,6 +153,10 @@
   base::WeakNSProtocol<id<UrlLoader, OmniboxFocuser>> _dispatcher;
 }
 
+// Redeclare the |view| property to be the GoogleLandingView subclass instead of
+// a generic UIView.
+@property(nonatomic, readwrite, strong) GoogleLandingView* view;
+
 // Whether the Google logo or doodle is being shown.
 @property(nonatomic, assign) BOOL logoIsShowing;
 
@@ -151,9 +193,6 @@
 // pushed into the header view.
 @property(nonatomic, assign) BOOL canGoBack;
 
-// Left margin to center the items. Used for the inset.
-@property(nonatomic, assign) CGFloat leftMargin;
-
 // Returns the height to use for the What's New promo view.
 - (CGFloat)promoHeaderHeight;
 // Add fake search field and voice search microphone.
@@ -178,6 +217,8 @@
 // If Google is not the default search engine, hide the logo, doodle and
 // fakebox.
 - (void)updateLogoAndFakeboxDisplay;
+// Helper method to set UICollectionViewFlowLayout insets for most visited.
+- (void)setFlowLayoutInset:(UICollectionViewFlowLayout*)layout;
 // Instructs the UICollectionView and UIView to reload it's data and layout.
 - (void)reloadData;
 // Adds the constraints for the |logoView|, the |searchField| related to the
@@ -203,6 +244,7 @@
 
 @implementation GoogleLandingViewController
 
+@dynamic view;
 @synthesize logoVendor = _logoVendor;
 // Property declared in NewTabPagePanelProtocol.
 @synthesize delegate = _delegate;
@@ -216,12 +258,17 @@
 @synthesize canGoForward = _canGoForward;
 @synthesize canGoBack = _canGoBack;
 @synthesize voiceSearchIsEnabled = _voiceSearchIsEnabled;
-@synthesize leftMargin = _leftMargin;
+
+- (void)loadView {
+  self.view = [[[GoogleLandingView alloc]
+      initWithFrame:[UIScreen mainScreen].bounds] autorelease];
+}
 
 - (void)viewDidLoad {
   [super viewDidLoad];
   [self.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
                                  UIViewAutoresizingFlexibleWidth];
+  [self.view setFrameDelegate:self];
 
   // Initialise |shiftTilesDownStartTime| to a sentinel value to indicate that
   // the animation has not yet started.
@@ -240,15 +287,14 @@
               action:@selector(blurOmnibox)]);
   [_swipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionDown];
 
-  self.leftMargin =
-      content_suggestions::centeredTilesMarginForWidth([self viewWidth]);
-
   [self addSearchField];
   [self addMostVisited];
   [self addOverscrollActions];
   [self reload];
-  _viewLoaded = YES;
-  [self.logoVendor fetchDoodle];
+}
+
+- (void)viewDidLayoutSubviews {
+  [self updateSubviewFrames];
 }
 
 - (void)viewWillTransitionToSize:(CGSize)size
@@ -256,13 +302,6 @@
            (id<UIViewControllerTransitionCoordinator>)coordinator {
   [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
 
-  self.leftMargin =
-      content_suggestions::centeredTilesMarginForWidth(size.width);
-
-  // Invalidate the layout so that the collection view's header size is reset
-  // for the new orientation.
-  [[_mostVisitedView collectionViewLayout] invalidateLayout];
-
   void (^alongsideBlock)(id<UIViewControllerTransitionCoordinatorContext>) = ^(
       id<UIViewControllerTransitionCoordinatorContext> context) {
     if (IsIPadIdiom() && _scrolledToTop) {
@@ -271,33 +310,23 @@
       return;
     };
 
+    // Invalidate the layout so that the collection view's header size is reset
+    // for the new orientation.
+    if (!_scrolledToTop) {
+      [[_mostVisitedView collectionViewLayout] invalidateLayout];
+    }
+
     // Call -scrollViewDidScroll: so that the omnibox's frame is adjusted for
     // the scroll view's offset.
     [self scrollViewDidScroll:_mostVisitedView];
 
     // Updates the constraints.
-    [_promoHeaderView
-        setSideMargin:content_suggestions::centeredTilesMarginForWidth(
-                          size.width)
-             forWidth:size.width];
-    [_doodleTopMarginConstraint
-        setConstant:content_suggestions::doodleTopMargin()];
     [_searchFieldWidthConstraint
         setConstant:content_suggestions::searchFieldWidth(size.width)];
     [_searchFieldTopMarginConstraint
         setConstant:content_suggestions::searchFieldTopMargin()];
-    BOOL isScrollableNTP = !IsIPadIdiom() || IsCompactTablet();
-    if (isScrollableNTP && _scrolledToTop) {
-      // Set the scroll view's offset to the pinned offset to keep the omnibox
-      // at the top of the screen if it isn't already.
-      CGFloat pinnedOffsetY = [self pinnedOffsetY];
-      if ([_mostVisitedView contentOffset].y < pinnedOffsetY) {
-        [_mostVisitedView setContentOffset:CGPointMake(0, pinnedOffsetY)];
-      } else {
-        [self updateSearchField];
-      }
-    }
-
+    [_doodleTopMarginConstraint
+        setConstant:content_suggestions::doodleTopMargin()];
   };
   [coordinator animateAlongsideTransition:alongsideBlock completion:nil];
 }
@@ -375,6 +404,7 @@
   if (self.logoVendor.showingLogo != self.logoIsShowing) {
     self.logoVendor.showingLogo = self.logoIsShowing;
     if (_viewLoaded) {
+      [self updateSubviewFrames];
       [_doodleHeightConstraint
           setConstant:content_suggestions::doodleHeight(self.logoIsShowing)];
 
@@ -473,6 +503,64 @@
   [sender chromeExecuteCommand:command];
 }
 
+- (void)setFlowLayoutInset:(UICollectionViewFlowLayout*)layout {
+  CGFloat leftMargin =
+      content_suggestions::centeredTilesMarginForWidth([self viewWidth]);
+  [layout setSectionInset:UIEdgeInsetsMake(0, leftMargin, 0, leftMargin)];
+}
+
+- (void)resetSectionInset {
+  UICollectionViewFlowLayout* flowLayout =
+      (UICollectionViewFlowLayout*)[_mostVisitedView collectionViewLayout];
+  [flowLayout setSectionInset:UIEdgeInsetsZero];
+}
+
+- (void)updateSubviewFrames {
+  _mostVisitedCellSize = [self mostVisitedCellSize];
+  UICollectionViewFlowLayout* flowLayout =
+      base::mac::ObjCCastStrict<UICollectionViewFlowLayout>(
+          [_mostVisitedView collectionViewLayout]);
+  [flowLayout setItemSize:_mostVisitedCellSize];
+
+  [self setFlowLayoutInset:flowLayout];
+  [flowLayout invalidateLayout];
+  [_promoHeaderView
+      setSideMargin:content_suggestions::centeredTilesMarginForWidth(
+                        [self viewWidth])];
+
+  // On the iPhone 6 Plus, if the app is started in landscape after a fresh
+  // install, the UICollectionViewLayout incorrectly sizes the widths of the
+  // supplementary views to the portrait width.  Correct that here to ensure
+  // that the header is property laid out to the UICollectionView's width.
+  // crbug.com/491131
+  CGFloat collectionViewWidth = CGRectGetWidth([_mostVisitedView bounds]);
+  CGFloat collectionViewMinX = CGRectGetMinX([_mostVisitedView bounds]);
+  for (UIView* supplementaryView in _supplementaryViews.get()) {
+    CGRect supplementaryViewFrame = supplementaryView.frame;
+    supplementaryViewFrame.origin.x = collectionViewMinX;
+    supplementaryViewFrame.size.width = collectionViewWidth;
+    supplementaryView.frame = supplementaryViewFrame;
+  }
+
+  BOOL isScrollableNTP = !IsIPadIdiom() || IsCompactTablet();
+  if (isScrollableNTP && _scrolledToTop) {
+    // Set the scroll view's offset to the pinned offset to keep the omnibox
+    // at the top of the screen if it isn't already.
+    CGFloat pinnedOffsetY = [self pinnedOffsetY];
+    if ([_mostVisitedView contentOffset].y < pinnedOffsetY) {
+      [_mostVisitedView setContentOffset:CGPointMake(0, pinnedOffsetY)];
+    } else {
+      [self updateSearchField];
+    }
+  }
+
+  if (!_viewLoaded) {
+    _viewLoaded = YES;
+    [self.logoVendor fetchDoodle];
+  }
+  [self.delegate updateNtpBarShadowForPanelController:self];
+}
+
 // Initialize and add a panel with most visited sites.
 - (void)addMostVisited {
   CGRect mostVisitedFrame = [self.view bounds];
@@ -720,12 +808,6 @@
 
 #pragma mark - UICollectionView Methods.
 
-- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView
-                        layout:(UICollectionViewLayout*)collectionViewLayout
-        insetForSectionAtIndex:(NSInteger)section {
-  return UIEdgeInsetsMake(0, self.leftMargin, 0, self.leftMargin);
-}
-
 - (CGSize)collectionView:(UICollectionView*)collectionView
                              layout:
                                  (UICollectionViewLayout*)collectionViewLayout
@@ -832,8 +914,7 @@
                                     forIndexPath:indexPath] retain]);
       [_promoHeaderView
           setSideMargin:content_suggestions::centeredTilesMarginForWidth(
-                            [self viewWidth])
-               forWidth:[self viewWidth]];
+                            [self viewWidth])];
       [_promoHeaderView setDelegate:self];
       if (self.promoCanShow) {
         [_promoHeaderView setText:self.promoText];
@@ -1039,8 +1120,7 @@
 // Returns the Y value to use for the scroll view's contentOffset when scrolling
 // the omnibox to the top of the screen.
 - (CGFloat)pinnedOffsetY {
-  CGFloat headerHeight = content_suggestions::heightForLogoHeader(
-      self.logoIsShowing, self.promoCanShow);
+  CGFloat headerHeight = [_headerView frame].size.height;
   CGFloat offsetY =
       headerHeight - ntp_header::kScrolledToTopOmniboxBottomMargin;
   if (!IsIPadIdiom())
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
index 945cc38..a81ec0d06 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
@@ -80,6 +80,7 @@
   toolbarView.frame = toolbarFrame;
   [toolbarView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
 
+  [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
   [self addSubview:[_toolbarController view]];
 }
 
diff --git a/ios/chrome/browser/ui/ntp/whats_new_header_view.h b/ios/chrome/browser/ui/ntp/whats_new_header_view.h
index b87a138..ac306164 100644
--- a/ios/chrome/browser/ui/ntp/whats_new_header_view.h
+++ b/ios/chrome/browser/ui/ntp/whats_new_header_view.h
@@ -27,7 +27,7 @@
 - (void)setIcon:(WhatsNewIcon)icon;
 
 // Sets the value to use for the left and right margin.
-- (void)setSideMargin:(CGFloat)sideMargin forWidth:(CGFloat)width;
+- (void)setSideMargin:(CGFloat)sideMargin;
 
 // Returns the minimum height required for WhatsNewHeaderView to fit in |width|,
 // for a given |text|.
diff --git a/ios/chrome/browser/ui/ntp/whats_new_header_view.mm b/ios/chrome/browser/ui/ntp/whats_new_header_view.mm
index 43c43f9..c4a7aef6 100644
--- a/ios/chrome/browser/ui/ntp/whats_new_header_view.mm
+++ b/ios/chrome/browser/ui/ntp/whats_new_header_view.mm
@@ -131,11 +131,11 @@
   [_infoIconImageView setImage:image];
 }
 
-- (void)setSideMargin:(CGFloat)sideMargin forWidth:(CGFloat)width {
+- (void)setSideMargin:(CGFloat)sideMargin {
   _sideMargin = sideMargin;
   [self setNeedsUpdateConstraints];
   CGFloat maxLabelWidth =
-      width - 2 * sideMargin - kInfoIconSize - kLabelLeftMargin;
+      self.frame.size.width - 2 * sideMargin - kInfoIconSize - kLabelLeftMargin;
   [_promoLabel.get() setPreferredMaxLayoutWidth:maxLabelWidth];
 }
 
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index 6b50104..56c2a48f 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -163,6 +163,8 @@
     "src/components/Typography/src/MDCTypography.h",
     "src/components/Typography/src/MDCTypography.m",
     "src/components/Typography/src/MaterialTypography.h",
+    "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h",
+    "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m",
     "src/components/private/Application/src/MaterialApplication.h",
     "src/components/private/Application/src/UIApplication+AppExtensions.h",
     "src/components/private/Application/src/UIApplication+AppExtensions.m",
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index 34f53ef4..0abd728 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: b452b1e7fb85cc9aeef2df2b6a44cbe0e8594560
+Revision: f2fbf2501a825c023f2d846aeba4a292f1053c03
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 70ece28..df77c1c 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -288,6 +288,15 @@
 const base::Feature kDelayCopyNV12Textures{"DelayCopyNV12Textures",
                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables code paths accessing controls exposed by video capture devices in the
+// context of capturing still images. Note that several webcam drivers have
+// shown issues when accessing these controls, resulting in symptoms such as
+// video capture outputting blank images or images with incorrect settings for
+// things like zoom, white balance, contrast, focus, etc, see
+// https://crbug.com/722038.
+const base::Feature kImageCaptureControls{"ImageCaptureControls",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables H264 HW encode acceleration using Media Foundation for Windows.
 const base::Feature kMediaFoundationH264Encoding{
     "MediaFoundationH264Encoding", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 89e2e61..772b5b3 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -129,6 +129,7 @@
 #if defined(OS_WIN)
 MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoding;
 MEDIA_EXPORT extern const base::Feature kDelayCopyNV12Textures;
+MEDIA_EXPORT extern const base::Feature kImageCaptureControls;
 MEDIA_EXPORT extern const base::Feature kMediaFoundationH264Encoding;
 #endif  // defined(OS_WIN)
 
diff --git a/media/base/watch_time_keys.cc b/media/base/watch_time_keys.cc
index 243d580..49065ac 100644
--- a/media/base/watch_time_keys.cc
+++ b/media/base/watch_time_keys.cc
@@ -13,6 +13,12 @@
 const char kWatchTimeAudioVideoSrc[] = "Media.WatchTime.AudioVideo.SRC";
 const char kWatchTimeAudioVideoBattery[] = "Media.WatchTime.AudioVideo.Battery";
 const char kWatchTimeAudioVideoAc[] = "Media.WatchTime.AudioVideo.AC";
+const char kWatchTimeAudioVideoDisplayFullscreen[] =
+    "Media.WatchTime.AudioVideo.DisplayFullscreen";
+const char kWatchTimeAudioVideoDisplayInline[] =
+    "Media.WatchTime.AudioVideo.DisplayInline";
+const char kWatchTimeAudioVideoDisplayPictureInPicture[] =
+    "Media.WatchTime.AudioVideo.DisplayPictureInPicture";
 const char kWatchTimeAudioVideoEmbeddedExperience[] =
     "Media.WatchTime.AudioVideo.EmbeddedExperience";
 const char kWatchTimeAudioVideoNativeControlsOn[] =
@@ -27,6 +33,12 @@
 const char kWatchTimeAudioSrc[] = "Media.WatchTime.Audio.SRC";
 const char kWatchTimeAudioBattery[] = "Media.WatchTime.Audio.Battery";
 const char kWatchTimeAudioAc[] = "Media.WatchTime.Audio.AC";
+const char kWatchTimeAudioDisplayFullscreen[] =
+    "Media.WatchTime.Audio.DisplayFullscreen";
+const char kWatchTimeAudioDisplayInline[] =
+    "Media.WatchTime.Audio.DisplayInline";
+const char kWatchTimeAudioDisplayPictureInPicture[] =
+    "Media.WatchTime.Audio.DisplayPictureInPicture";
 const char kWatchTimeAudioEmbeddedExperience[] =
     "Media.WatchTime.Audio.EmbeddedExperience";
 const char kWatchTimeAudioNativeControlsOn[] =
@@ -53,6 +65,7 @@
 const char kWatchTimeFinalize[] = "FinalizeWatchTime";
 const char kWatchTimeFinalizePower[] = "FinalizePowerWatchTime";
 const char kWatchTimeFinalizeControls[] = "FinalizeControlsWatchTime";
+const char kWatchTimeFinalizeDisplay[] = "FinalizeDisplayWatchTime";
 
 const char kWatchTimeUnderflowCount[] = "UnderflowCount";
 
@@ -89,6 +102,9 @@
           kWatchTimeAudioBattery,
           kWatchTimeAudioAc,
           kWatchTimeAudioEmbeddedExperience,
+          kWatchTimeAudioDisplayFullscreen,
+          kWatchTimeAudioDisplayInline,
+          kWatchTimeAudioDisplayPictureInPicture,
           kWatchTimeAudioNativeControlsOn,
           kWatchTimeAudioNativeControlsOff,
           kWatchTimeAudioVideoAll,
@@ -97,6 +113,9 @@
           kWatchTimeAudioVideoSrc,
           kWatchTimeAudioVideoBattery,
           kWatchTimeAudioVideoAc,
+          kWatchTimeAudioVideoDisplayFullscreen,
+          kWatchTimeAudioVideoDisplayInline,
+          kWatchTimeAudioVideoDisplayPictureInPicture,
           kWatchTimeAudioVideoEmbeddedExperience,
           kWatchTimeAudioVideoNativeControlsOn,
           kWatchTimeAudioVideoNativeControlsOff,
@@ -127,4 +146,13 @@
       base::KEEP_FIRST_OF_DUPES);
 }
 
+base::flat_set<base::StringPiece> GetWatchTimeDisplayKeys() {
+  return base::flat_set<base::StringPiece>(
+      {kWatchTimeAudioDisplayFullscreen, kWatchTimeAudioDisplayInline,
+       kWatchTimeAudioDisplayPictureInPicture,
+       kWatchTimeAudioVideoDisplayFullscreen, kWatchTimeAudioVideoDisplayInline,
+       kWatchTimeAudioVideoDisplayPictureInPicture},
+      base::KEEP_FIRST_OF_DUPES);
+}
+
 }  // namespace media
diff --git a/media/base/watch_time_keys.h b/media/base/watch_time_keys.h
index e7dcdfa5..148ffe0 100644
--- a/media/base/watch_time_keys.h
+++ b/media/base/watch_time_keys.h
@@ -14,12 +14,18 @@
 // Histogram names used for reporting; also double as MediaLog key names.
 // NOTE: If you add to this list you must update GetWatchTimeKeys() and if
 // necessary, GetWatchTimePowerKeys().
+// TODO(mlamouri): the kWatchTimeAudioDisplay* constants are here for
+// convenience because a few macros expect them. They should be removed after
+// a refactor.
 MEDIA_EXPORT extern const char kWatchTimeAudioAll[];
 MEDIA_EXPORT extern const char kWatchTimeAudioMse[];
 MEDIA_EXPORT extern const char kWatchTimeAudioEme[];
 MEDIA_EXPORT extern const char kWatchTimeAudioSrc[];
 MEDIA_EXPORT extern const char kWatchTimeAudioBattery[];
 MEDIA_EXPORT extern const char kWatchTimeAudioAc[];
+MEDIA_EXPORT extern const char kWatchTimeAudioDisplayFullscreen[];
+MEDIA_EXPORT extern const char kWatchTimeAudioDisplayInline[];
+MEDIA_EXPORT extern const char kWatchTimeAudioDisplayPictureInPicture[];
 MEDIA_EXPORT extern const char kWatchTimeAudioEmbeddedExperience[];
 MEDIA_EXPORT extern const char kWatchTimeAudioNativeControlsOn[];
 MEDIA_EXPORT extern const char kWatchTimeAudioNativeControlsOff[];
@@ -29,6 +35,9 @@
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoSrc[];
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoBattery[];
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoAc[];
+MEDIA_EXPORT extern const char kWatchTimeAudioVideoDisplayFullscreen[];
+MEDIA_EXPORT extern const char kWatchTimeAudioVideoDisplayInline[];
+MEDIA_EXPORT extern const char kWatchTimeAudioVideoDisplayPictureInPicture[];
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoEmbeddedExperience[];
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoNativeControlsOn[];
 MEDIA_EXPORT extern const char kWatchTimeAudioVideoNativeControlsOff[];
@@ -46,6 +55,7 @@
 MEDIA_EXPORT extern const char kWatchTimeFinalize[];
 MEDIA_EXPORT extern const char kWatchTimeFinalizePower[];
 MEDIA_EXPORT extern const char kWatchTimeFinalizeControls[];
+MEDIA_EXPORT extern const char kWatchTimeFinalizeDisplay[];
 
 // Count of the number of underflow events during a media session.
 MEDIA_EXPORT extern const char kWatchTimeUnderflowCount[];
@@ -69,6 +79,7 @@
 MEDIA_EXPORT base::flat_set<base::StringPiece> GetWatchTimeKeys();
 MEDIA_EXPORT base::flat_set<base::StringPiece> GetWatchTimePowerKeys();
 MEDIA_EXPORT base::flat_set<base::StringPiece> GetWatchTimeControlsKeys();
+MEDIA_EXPORT base::flat_set<base::StringPiece> GetWatchTimeDisplayKeys();
 
 }  // namespace media
 
diff --git a/media/blink/watch_time_reporter.cc b/media/blink/watch_time_reporter.cc
index 8d249327..28bc7ce6 100644
--- a/media/blink/watch_time_reporter.cc
+++ b/media/blink/watch_time_reporter.cc
@@ -210,6 +210,18 @@
                          &WatchTimeReporter::UpdateWatchTime);
 }
 
+void WatchTimeReporter::OnDisplayTypeInline() {
+  OnDisplayTypeChanged(blink::WebMediaPlayer::DisplayType::kInline);
+}
+
+void WatchTimeReporter::OnDisplayTypeFullscreen() {
+  OnDisplayTypeChanged(blink::WebMediaPlayer::DisplayType::kFullscreen);
+}
+
+void WatchTimeReporter::OnDisplayTypePictureInPicture() {
+  OnDisplayTypeChanged(blink::WebMediaPlayer::DisplayType::kPictureInPicture);
+}
+
 void WatchTimeReporter::OnPowerStateChange(bool on_battery_power) {
   if (!reporting_timer_.IsRunning())
     return;
@@ -261,10 +273,14 @@
 
   underflow_count_ = 0;
   last_media_timestamp_ = last_media_power_timestamp_ =
-      last_media_controls_timestamp_ = end_timestamp_for_power_ = kNoTimestamp;
+      last_media_controls_timestamp_ = end_timestamp_for_power_ =
+          last_media_display_type_timestamp_ = end_timestamp_for_display_type_ =
+              kNoTimestamp;
   is_on_battery_power_ = IsOnBatteryPower();
+  display_type_for_recording_ = display_type_;
   start_timestamp_ = start_timestamp_for_power_ =
-      start_timestamp_for_controls_ = start_timestamp;
+      start_timestamp_for_controls_ = start_timestamp_for_display_type_ =
+          start_timestamp;
   reporting_timer_.Start(FROM_HERE, reporting_interval_, this,
                          &WatchTimeReporter::UpdateWatchTime);
 }
@@ -297,6 +313,8 @@
   const bool is_power_change_pending = end_timestamp_for_power_ != kNoTimestamp;
   const bool is_controls_change_pending =
       end_timestamp_for_controls_ != kNoTimestamp;
+  const bool is_display_type_change_pending =
+      end_timestamp_for_display_type_ != kNoTimestamp;
 
   // If we're finalizing the log, use the media time value at the time of
   // finalization.
@@ -316,10 +334,10 @@
         value.InSecondsF());                                               \
   } while (0)
 
-#define RECORD_CONTROLS_WATCH_TIME(key, value)                         \
+// Similar to RECORD_WATCH_TIME but ignores background watch time.
+#define RECORD_FOREGROUND_WATCH_TIME(key, value)                       \
   do {                                                                 \
-    if (is_background_)                                                \
-      break;                                                           \
+    DCHECK(!is_background_);                                           \
     log_event->params.SetDoubleWithoutPathExpansion(                   \
         has_video_ ? kWatchTimeAudioVideo##key : kWatchTimeAudio##key, \
         value.InSecondsF());                                           \
@@ -370,7 +388,7 @@
   }
 
   // Similar to the block above for controls.
-  if (last_media_controls_timestamp_ != current_timestamp) {
+  if (!is_background_ && last_media_controls_timestamp_ != current_timestamp) {
     last_media_controls_timestamp_ = is_controls_change_pending
                                          ? end_timestamp_for_controls_
                                          : current_timestamp;
@@ -380,13 +398,40 @@
 
     if (elapsed_controls >= kMinimumElapsedWatchTime) {
       if (has_native_controls_)
-        RECORD_CONTROLS_WATCH_TIME(NativeControlsOn, elapsed_controls);
+        RECORD_FOREGROUND_WATCH_TIME(NativeControlsOn, elapsed_controls);
       else
-        RECORD_CONTROLS_WATCH_TIME(NativeControlsOff, elapsed_controls);
+        RECORD_FOREGROUND_WATCH_TIME(NativeControlsOff, elapsed_controls);
     }
   }
+
+  // Similar to the block above for display type.
+  if (!is_background_ && has_video_ &&
+      last_media_display_type_timestamp_ != current_timestamp) {
+    last_media_display_type_timestamp_ = is_display_type_change_pending
+                                             ? end_timestamp_for_display_type_
+                                             : current_timestamp;
+
+    const base::TimeDelta elapsed_display_type =
+        last_media_display_type_timestamp_ - start_timestamp_for_display_type_;
+
+    if (elapsed_display_type >= kMinimumElapsedWatchTime) {
+      switch (display_type_for_recording_) {
+        case blink::WebMediaPlayer::DisplayType::kInline:
+          RECORD_FOREGROUND_WATCH_TIME(DisplayInline, elapsed_display_type);
+          break;
+        case blink::WebMediaPlayer::DisplayType::kFullscreen:
+          RECORD_FOREGROUND_WATCH_TIME(DisplayFullscreen, elapsed_display_type);
+          break;
+        case blink::WebMediaPlayer::DisplayType::kPictureInPicture:
+          RECORD_FOREGROUND_WATCH_TIME(DisplayPictureInPicture,
+                                       elapsed_display_type);
+          break;
+      }
+    }
+  }
+
 #undef RECORD_WATCH_TIME
-#undef RECORD_CONTROLS_WATCH_TIME
+#undef RECORD_FOREGROUND_WATCH_TIME
 
   // Pass along any underflow events which have occurred since the last report.
   if (!pending_underflow_events_.empty()) {
@@ -414,6 +459,8 @@
       log_event->params.SetBoolean(kWatchTimeFinalizePower, true);
     if (is_controls_change_pending)
       log_event->params.SetBoolean(kWatchTimeFinalizeControls, true);
+    if (is_display_type_change_pending)
+      log_event->params.SetBoolean(kWatchTimeFinalizeDisplay, true);
   }
 
   if (!log_event->params.empty())
@@ -435,6 +482,13 @@
     end_timestamp_for_controls_ = kNoTimestamp;
   }
 
+  if (is_display_type_change_pending) {
+    display_type_for_recording_ = display_type_;
+
+    start_timestamp_for_display_type_ = end_timestamp_for_display_type_;
+    end_timestamp_for_display_type_ = kNoTimestamp;
+  }
+
   // Stop the timer if this is supposed to be our last tick.
   if (is_finalizing) {
     end_timestamp_ = kNoTimestamp;
@@ -443,4 +497,21 @@
   }
 }
 
+void WatchTimeReporter::OnDisplayTypeChanged(
+    blink::WebMediaPlayer::DisplayType display_type) {
+  display_type_ = display_type;
+
+  if (!reporting_timer_.IsRunning())
+    return;
+
+  if (display_type_for_recording_ == display_type_) {
+    end_timestamp_for_display_type_ = kNoTimestamp;
+    return;
+  }
+
+  end_timestamp_for_display_type_ = get_media_time_cb_.Run();
+  reporting_timer_.Start(FROM_HERE, reporting_interval_, this,
+                         &WatchTimeReporter::UpdateWatchTime);
+}
+
 }  // namespace media
diff --git a/media/blink/watch_time_reporter.h b/media/blink/watch_time_reporter.h
index 51cfa78d..656ae211 100644
--- a/media/blink/watch_time_reporter.h
+++ b/media/blink/watch_time_reporter.h
@@ -14,6 +14,7 @@
 #include "media/base/media_log.h"
 #include "media/base/timestamp_constants.h"
 #include "media/blink/media_blink_export.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -119,6 +120,12 @@
   void OnNativeControlsEnabled();
   void OnNativeControlsDisabled();
 
+  // These methods are used to ensure that the watch time is reported relative
+  // to the display type of the media.
+  void OnDisplayTypeInline();
+  void OnDisplayTypeFullscreen();
+  void OnDisplayTypePictureInPicture();
+
   // Setup the reporting interval to be immediate to avoid spinning real time
   // within the unit test.
   void set_reporting_interval_for_testing() {
@@ -159,6 +166,7 @@
   enum class FinalizeTime { IMMEDIATELY, ON_NEXT_UPDATE };
   void MaybeFinalizeWatchTime(FinalizeTime finalize_time);
   void UpdateWatchTime();
+  void OnDisplayTypeChanged(blink::WebMediaPlayer::DisplayType display_type);
 
   // Initialized during construction.
   const bool has_audio_;
@@ -186,11 +194,16 @@
   double volume_ = 1.0;
   int underflow_count_ = 0;
   std::vector<base::TimeDelta> pending_underflow_events_;
+  blink::WebMediaPlayer::DisplayType display_type_ =
+      blink::WebMediaPlayer::DisplayType::kInline;
+  blink::WebMediaPlayer::DisplayType display_type_for_recording_ =
+      blink::WebMediaPlayer::DisplayType::kInline;
 
   // The last media timestamp seen by UpdateWatchTime().
   base::TimeDelta last_media_timestamp_ = kNoTimestamp;
   base::TimeDelta last_media_power_timestamp_ = kNoTimestamp;
   base::TimeDelta last_media_controls_timestamp_ = kNoTimestamp;
+  base::TimeDelta last_media_display_type_timestamp_ = kNoTimestamp;
 
   // The starting and ending timestamps used for reporting watch time.
   base::TimeDelta start_timestamp_;
@@ -206,6 +219,11 @@
   base::TimeDelta start_timestamp_for_controls_;
   base::TimeDelta end_timestamp_for_controls_ = kNoTimestamp;
 
+  // Similar to the above but tracks watch time relative to whether the display
+  // type is inline, fullscreen or picture-in-picture.
+  base::TimeDelta start_timestamp_for_display_type_;
+  base::TimeDelta end_timestamp_for_display_type_ = kNoTimestamp;
+
   // Special case reporter for handling background video watch time. Configured
   // as an audio only WatchTimeReporter with |is_background_| set to true.
   std::unique_ptr<WatchTimeReporter> background_reporter_;
diff --git a/media/blink/watch_time_reporter_unittest.cc b/media/blink/watch_time_reporter_unittest.cc
index 18ddf020..fb64ae8 100644
--- a/media/blink/watch_time_reporter_unittest.cc
+++ b/media/blink/watch_time_reporter_unittest.cc
@@ -18,6 +18,8 @@
 
 constexpr gfx::Size kSizeJustRight = gfx::Size(201, 201);
 
+using blink::WebMediaPlayer;
+
 #define EXPECT_WATCH_TIME(key, value)                                    \
   do {                                                                   \
     EXPECT_CALL(media_log_,                                              \
@@ -27,6 +29,13 @@
         .RetiresOnSaturation();                                          \
   } while (0)
 
+#define EXPECT_WATCH_TIME_IF_VIDEO(key, value) \
+  do {                                         \
+    if (!has_video_)                           \
+      break;                                   \
+    EXPECT_WATCH_TIME(key, value);             \
+  } while (0)
+
 #define EXPECT_BACKGROUND_WATCH_TIME(key, value)                               \
   do {                                                                         \
     DCHECK(has_video_);                                                        \
@@ -44,6 +53,9 @@
 #define EXPECT_CONTROLS_WATCH_TIME_FINALIZED() \
   EXPECT_CALL(media_log_, OnControlsWatchTimeFinalized()).RetiresOnSaturation();
 
+#define EXPECT_DISPLAY_WATCH_TIME_FINALIZED() \
+  EXPECT_CALL(media_log_, OnDisplayWatchTimeFinalized()).RetiresOnSaturation();
+
 class WatchTimeReporterTest : public testing::TestWithParam<bool> {
  public:
   WatchTimeReporterTest() : has_video_(GetParam()) {}
@@ -67,6 +79,8 @@
             OnPowerWatchTimeFinalized();
           else if (it.key() == kWatchTimeFinalizeControls)
             OnControlsWatchTimeFinalized();
+          else if (it.key() == kWatchTimeFinalizeDisplay)
+            OnDisplayWatchTimeFinalized();
           else
             NOTREACHED();
           continue;
@@ -87,6 +101,7 @@
     MOCK_METHOD0(OnWatchTimeFinalized, void(void));
     MOCK_METHOD0(OnPowerWatchTimeFinalized, void(void));
     MOCK_METHOD0(OnControlsWatchTimeFinalized, void(void));
+    MOCK_METHOD0(OnDisplayWatchTimeFinalized, void(void));
     MOCK_METHOD2(OnWatchTimeUpdate, void(const std::string&, base::TimeDelta));
     MOCK_METHOD1(OnUnderflowUpdate, void(int));
 
@@ -147,6 +162,10 @@
             : wtr_->OnNativeControlsDisabled();
   }
 
+  void OnDisplayTypeChanged(WebMediaPlayer::DisplayType display_type) {
+    wtr_->OnDisplayTypeChanged(display_type);
+  }
+
   enum {
     // After |test_callback_func| is executed, should watch time continue to
     // accumulate?
@@ -186,6 +205,21 @@
     // Indicates that controls watch time should be reported to the native
     // controls metric.
     kStartWithNativeControls = 256,
+
+    // During finalize the watch time should not continue on the starting
+    // display metric. By default this means the DisplayInline metric will be
+    // finalized, but if used with |kStartWithDisplayFullscreen| it will be the
+    // DisplayFullscreen metric.
+    kFinalizeDisplayWatchTime = 1024,
+
+    // During finalize the display watch time should continue on the metric
+    // opposite the starting metric (by default it's inline, it's fullscreen if
+    // |kStartWithDisplayFullscreen| is specified.
+    kTransitionDisplayWatchTime = 2048,
+
+    // Indicates that the watch time should be reporter to the fullscreen
+    // display metric.
+    kStartWithDisplayFullscreen = 4096,
   };
 
   template <int TestFlags = 0, typename HysteresisTestCallback>
@@ -197,6 +231,8 @@
 
     if (TestFlags & kStartWithNativeControls)
       OnNativeControlsEnabled(true);
+    if (TestFlags & kStartWithDisplayFullscreen)
+      OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
 
     // Setup all current time expectations first since they need to use the
     // InSequence macro for ease of use, but we don't want the watch time
@@ -220,7 +256,8 @@
         EXPECT_CALL(*this, GetCurrentMediaTime())
             .Times(TestFlags & (kFinalizeExitDoesNotRequireCurrentTime |
                                 kFinalizePowerWatchTime |
-                                kFinalizeControlsWatchTime)
+                                kFinalizeControlsWatchTime |
+                                kFinalizeDisplayWatchTime)
                        ? 1
                        : 2)
             .WillRepeatedly(testing::Return(kWatchTime2));
@@ -242,6 +279,11 @@
         EXPECT_CALL(*this, GetCurrentMediaTime())
             .WillOnce(testing::Return(kWatchTime4));
       }
+
+      if (TestFlags & kTransitionDisplayWatchTime) {
+        EXPECT_CALL(*this, GetCurrentMediaTime())
+            .WillOnce(testing::Return(kWatchTime4));
+      }
     }
 
     wtr_->OnPlaying();
@@ -261,6 +303,10 @@
       EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime1);
     else
       EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+    if (TestFlags & kStartWithDisplayFullscreen)
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime1);
+    else
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
 
     CycleReportingTimer();
 
@@ -277,6 +323,9 @@
     const base::TimeDelta kExpectedContolsWatchTime =
         TestFlags & kFinalizeControlsWatchTime ? kWatchTime2
                                                : kExpectedWatchTime;
+    const base::TimeDelta kExpectedDisplayWatchTime =
+        TestFlags & kFinalizeDisplayWatchTime ? kWatchTime2
+                                              : kExpectedWatchTime;
 
     if (TestFlags & kStartOnBattery)
       EXPECT_WATCH_TIME(Battery, kExpectedPowerWatchTime);
@@ -288,6 +337,11 @@
     else
       EXPECT_WATCH_TIME(NativeControlsOff, kExpectedContolsWatchTime);
 
+    if (TestFlags & kStartWithDisplayFullscreen)
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kExpectedDisplayWatchTime);
+    else
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedDisplayWatchTime);
+
     // Special case when testing battery watch time.
     if (TestFlags & kTransitionPowerWatchTime) {
       ASSERT_TRUE(TestFlags & kAccumulationContinuesAfterTest)
@@ -302,6 +356,7 @@
       // started on battery we'll now record one for ac and vice versa.
       EXPECT_WATCH_TIME(All, kWatchTime4);
       EXPECT_WATCH_TIME(Src, kWatchTime4);
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4);
       EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4);
       if (TestFlags & kStartOnBattery)
         EXPECT_WATCH_TIME(Ac, kWatchTime4 - kWatchTime2);
@@ -321,10 +376,31 @@
       EXPECT_WATCH_TIME(All, kWatchTime4);
       EXPECT_WATCH_TIME(Src, kWatchTime4);
       EXPECT_WATCH_TIME(Ac, kWatchTime4);
+      EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4);
       if (TestFlags & kStartWithNativeControls)
         EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4 - kWatchTime2);
       else
         EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime4 - kWatchTime2);
+    } else if (TestFlags & kTransitionDisplayWatchTime) {
+      ASSERT_TRUE(TestFlags & kAccumulationContinuesAfterTest)
+          << "kTransitionDisplayWatchTime tests must be done with "
+             "kAccumulationContinuesAfterTest";
+
+      EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+      CycleReportingTimer();
+
+      // Run one last cycle that is long enough to trigger a new watch time
+      // entry on the opposite of the current power watch time graph; i.e. if we
+      // started on battery we'll now record one for ac and vice versa.
+      EXPECT_WATCH_TIME(All, kWatchTime4);
+      EXPECT_WATCH_TIME(Src, kWatchTime4);
+      EXPECT_WATCH_TIME(Ac, kWatchTime4);
+      EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime4);
+      if (TestFlags & kStartWithDisplayFullscreen)
+        EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime4 - kWatchTime2);
+      else
+        EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen,
+                                   kWatchTime4 - kWatchTime2);
     }
 
     EXPECT_WATCH_TIME_FINALIZED();
@@ -420,6 +496,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTimeLate);
   EXPECT_WATCH_TIME(Mse, kWatchTimeLate);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeLate);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeLate);
   EXPECT_CALL(media_log_, OnUnderflowUpdate(2));
   CycleReportingTimer();
 
@@ -458,6 +535,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTimeEarly);
   EXPECT_WATCH_TIME(Mse, kWatchTimeEarly);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTimeEarly);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTimeEarly);
   EXPECT_CALL(media_log_, OnUnderflowUpdate(1));
   EXPECT_WATCH_TIME_FINALIZED();
   CycleReportingTimer();
@@ -498,6 +576,7 @@
   EXPECT_WATCH_TIME(Eme, kExpectedWatchTime);
   EXPECT_WATCH_TIME(Mse, kExpectedWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kExpectedWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kExpectedWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 }
@@ -717,7 +796,7 @@
   wtr_.reset();
 }
 
-TEST_P(WatchTimeReporterTest, WatchTimeReporterControlsPowerFinalize) {
+TEST_P(WatchTimeReporterTest, WatchTimeReporterHiddenDisplayTypeBackground) {
   // Only run these background tests when video is present.
   if (!has_video_)
     return;
@@ -726,39 +805,166 @@
   constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
   EXPECT_CALL(*this, GetCurrentMediaTime())
       .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(base::TimeDelta()))
       .WillOnce(testing::Return(kWatchTime1))
-      .WillOnce(testing::Return(kWatchTime1))
-      .WillOnce(testing::Return(kWatchTime1))
-      .WillRepeatedly(testing::Return(kWatchTime2));
+      .WillOnce(testing::Return(kWatchTime2));
   Initialize(true, true, true, kSizeJustRight);
+  wtr_->OnHidden();
   wtr_->OnPlaying();
-  EXPECT_TRUE(IsMonitoring());
+  EXPECT_TRUE(IsBackgroundMonitoring());
+  EXPECT_FALSE(IsMonitoring());
 
-  OnNativeControlsEnabled(true);
-  OnPowerStateChange(true);
+  OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
 
-  EXPECT_WATCH_TIME(Ac, kWatchTime1);
-  EXPECT_WATCH_TIME(All, kWatchTime1);
-  EXPECT_WATCH_TIME(Eme, kWatchTime1);
-  EXPECT_WATCH_TIME(Mse, kWatchTime1);
-  EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
-  EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
-  EXPECT_POWER_WATCH_TIME_FINALIZED();
+  EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime1);
+  EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime1);
+  EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime1);
+  EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime1);
   CycleReportingTimer();
 
   wtr_->OnPaused();
-  EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime2 - kWatchTime1);
-  EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
-  EXPECT_WATCH_TIME(All, kWatchTime2);
-  EXPECT_WATCH_TIME(Eme, kWatchTime2);
-  EXPECT_WATCH_TIME(Mse, kWatchTime2);
+  EXPECT_BACKGROUND_WATCH_TIME(Ac, kWatchTime2);
+  EXPECT_BACKGROUND_WATCH_TIME(All, kWatchTime2);
+  EXPECT_BACKGROUND_WATCH_TIME(Eme, kWatchTime2);
+  EXPECT_BACKGROUND_WATCH_TIME(Mse, kWatchTime2);
   EXPECT_WATCH_TIME_FINALIZED();
   CycleReportingTimer();
 
+  EXPECT_FALSE(IsBackgroundMonitoring());
   EXPECT_FALSE(IsMonitoring());
   wtr_.reset();
 }
 
+TEST_P(WatchTimeReporterTest, WatchTimeReporterMultiplePartialFinalize) {
+  // Only run these background tests when video is present.
+  if (!has_video_)
+    return;
+
+  constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(8);
+  constexpr base::TimeDelta kWatchTime2 = base::TimeDelta::FromSeconds(16);
+
+  // Transition controls and battery.
+  {
+    EXPECT_CALL(*this, GetCurrentMediaTime())
+        .WillOnce(testing::Return(base::TimeDelta()))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime2));
+    Initialize(true, true, true, kSizeJustRight);
+    wtr_->OnPlaying();
+    EXPECT_TRUE(IsMonitoring());
+
+    OnNativeControlsEnabled(true);
+    OnPowerStateChange(true);
+
+    EXPECT_WATCH_TIME(Ac, kWatchTime1);
+    EXPECT_WATCH_TIME(All, kWatchTime1);
+    EXPECT_WATCH_TIME(Eme, kWatchTime1);
+    EXPECT_WATCH_TIME(Mse, kWatchTime1);
+    EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+    EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+    EXPECT_POWER_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    wtr_->OnPaused();
+    EXPECT_WATCH_TIME(All, kWatchTime2);
+    EXPECT_WATCH_TIME(Eme, kWatchTime2);
+    EXPECT_WATCH_TIME(Mse, kWatchTime2);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime2);
+    EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    EXPECT_FALSE(IsMonitoring());
+    wtr_.reset();
+  }
+
+  // Transition display type and battery.
+  {
+    EXPECT_CALL(*this, GetCurrentMediaTime())
+        .WillOnce(testing::Return(base::TimeDelta()))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime2));
+    Initialize(true, true, true, kSizeJustRight);
+    wtr_->OnPlaying();
+    EXPECT_TRUE(IsMonitoring());
+
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+    OnPowerStateChange(true);
+
+    EXPECT_WATCH_TIME(Ac, kWatchTime1);
+    EXPECT_WATCH_TIME(All, kWatchTime1);
+    EXPECT_WATCH_TIME(Eme, kWatchTime1);
+    EXPECT_WATCH_TIME(Mse, kWatchTime1);
+    EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+    EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+    EXPECT_POWER_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    wtr_->OnPaused();
+    EXPECT_WATCH_TIME(All, kWatchTime2);
+    EXPECT_WATCH_TIME(Eme, kWatchTime2);
+    EXPECT_WATCH_TIME(Mse, kWatchTime2);
+    EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime2);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    EXPECT_FALSE(IsMonitoring());
+    wtr_.reset();
+  }
+
+  // Transition controls, battery and display type.
+  {
+    EXPECT_CALL(*this, GetCurrentMediaTime())
+        .WillOnce(testing::Return(base::TimeDelta()))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime1))
+        .WillOnce(testing::Return(kWatchTime2));
+    Initialize(true, true, true, kSizeJustRight);
+    wtr_->OnPlaying();
+    EXPECT_TRUE(IsMonitoring());
+
+    OnNativeControlsEnabled(true);
+    OnPowerStateChange(true);
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kPictureInPicture);
+
+    EXPECT_WATCH_TIME(Ac, kWatchTime1);
+    EXPECT_WATCH_TIME(All, kWatchTime1);
+    EXPECT_WATCH_TIME(Eme, kWatchTime1);
+    EXPECT_WATCH_TIME(Mse, kWatchTime1);
+    EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime1);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime1);
+    EXPECT_CONTROLS_WATCH_TIME_FINALIZED();
+    EXPECT_POWER_WATCH_TIME_FINALIZED();
+    EXPECT_DISPLAY_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    wtr_->OnPaused();
+    EXPECT_WATCH_TIME(All, kWatchTime2);
+    EXPECT_WATCH_TIME(Eme, kWatchTime2);
+    EXPECT_WATCH_TIME(Mse, kWatchTime2);
+    EXPECT_WATCH_TIME_IF_VIDEO(DisplayPictureInPicture,
+                               kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME(Battery, kWatchTime2 - kWatchTime1);
+    EXPECT_WATCH_TIME_FINALIZED();
+    CycleReportingTimer();
+
+    EXPECT_FALSE(IsMonitoring());
+    wtr_.reset();
+  }
+}
+
 // Tests that starting from a non-zero base works.
 TEST_P(WatchTimeReporterTest, WatchTimeReporterNonZeroStart) {
   constexpr base::TimeDelta kWatchTime1 = base::TimeDelta::FromSeconds(5);
@@ -776,6 +982,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTime);
   EXPECT_WATCH_TIME(Mse, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   CycleReportingTimer();
 
   EXPECT_WATCH_TIME_FINALIZED();
@@ -797,6 +1004,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTime);
   EXPECT_WATCH_TIME(Mse, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_->OnSeeking();
 }
@@ -817,6 +1025,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTime);
   EXPECT_WATCH_TIME(Mse, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_->OnPaused();
   wtr_->OnSeeking();
@@ -838,6 +1047,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTime);
   EXPECT_WATCH_TIME(Mse, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 }
@@ -857,6 +1067,7 @@
   EXPECT_WATCH_TIME(All, kWatchTime);
   EXPECT_WATCH_TIME(Src, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 
@@ -871,6 +1082,7 @@
   EXPECT_WATCH_TIME(All, kWatchTime);
   EXPECT_WATCH_TIME(Mse, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 
@@ -886,6 +1098,7 @@
   EXPECT_WATCH_TIME(Eme, kWatchTime);
   EXPECT_WATCH_TIME(Src, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 
@@ -901,6 +1114,7 @@
   EXPECT_WATCH_TIME(Battery, kWatchTime);
   EXPECT_WATCH_TIME(Src, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 
@@ -916,6 +1130,41 @@
   EXPECT_WATCH_TIME(All, kWatchTime);
   EXPECT_WATCH_TIME(Src, kWatchTime);
   EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayInline, kWatchTime);
+  EXPECT_WATCH_TIME_FINALIZED();
+  wtr_.reset();
+
+  // Verify all, battery, src, non-native controls, display fullscreen
+  EXPECT_CALL(*this, GetCurrentMediaTime())
+      .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(kWatchTime));
+  Initialize(true, false, false, kSizeJustRight);
+  OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+  wtr_->OnPlaying();
+  SetOnBatteryPower(true);
+  EXPECT_TRUE(IsMonitoring());
+  EXPECT_WATCH_TIME(All, kWatchTime);
+  EXPECT_WATCH_TIME(Battery, kWatchTime);
+  EXPECT_WATCH_TIME(Src, kWatchTime);
+  EXPECT_WATCH_TIME(NativeControlsOff, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayFullscreen, kWatchTime);
+  EXPECT_WATCH_TIME_FINALIZED();
+  wtr_.reset();
+
+  // Verify ac, all, src, native controls, display picture-in-picture
+  EXPECT_CALL(*this, GetCurrentMediaTime())
+      .WillOnce(testing::Return(base::TimeDelta()))
+      .WillOnce(testing::Return(kWatchTime));
+  Initialize(true, false, false, kSizeJustRight);
+  OnNativeControlsEnabled(true);
+  OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kPictureInPicture);
+  wtr_->OnPlaying();
+  EXPECT_TRUE(IsMonitoring());
+  EXPECT_WATCH_TIME(Ac, kWatchTime);
+  EXPECT_WATCH_TIME(All, kWatchTime);
+  EXPECT_WATCH_TIME(Src, kWatchTime);
+  EXPECT_WATCH_TIME(NativeControlsOn, kWatchTime);
+  EXPECT_WATCH_TIME_IF_VIDEO(DisplayPictureInPicture, kWatchTime);
   EXPECT_WATCH_TIME_FINALIZED();
   wtr_.reset();
 }
@@ -1038,6 +1287,52 @@
       [this]() { OnNativeControlsEnabled(true); });
 }
 
+TEST_P(WatchTimeReporterTest,
+       OnDisplayTypeChangeHysteresisFullscreenContinuation) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeExitDoesNotRequireCurrentTime |
+                    kStartWithDisplayFullscreen>([this]() {
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kInline);
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+  });
+}
+
+TEST_P(WatchTimeReporterTest, OnDisplayTypeChangeHysteresisNativeFinalized) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeDisplayWatchTime | kStartWithDisplayFullscreen>(
+      [this]() { OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kInline); });
+}
+
+TEST_P(WatchTimeReporterTest, OnDisplayTypeChangeHysteresisInlineContinuation) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeExitDoesNotRequireCurrentTime>([this]() {
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kInline);
+  });
+}
+
+TEST_P(WatchTimeReporterTest, OnDisplayTypeChangeHysteresisNativeOffFinalized) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeDisplayWatchTime>([this]() {
+    OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+  });
+}
+
+TEST_P(WatchTimeReporterTest, OnDisplayTypeChangeInlineToFullscreen) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeDisplayWatchTime | kStartWithDisplayFullscreen |
+                    kTransitionDisplayWatchTime>(
+      [this]() { OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kInline); });
+}
+
+TEST_P(WatchTimeReporterTest, OnDisplayTypeChangeFullscreenToInline) {
+  RunHysteresisTest<kAccumulationContinuesAfterTest |
+                    kFinalizeDisplayWatchTime | kTransitionDisplayWatchTime>(
+      [this]() {
+        OnDisplayTypeChanged(WebMediaPlayer::DisplayType::kFullscreen);
+      });
+}
+
 // Tests that the first finalize is the only one that matters.
 TEST_P(WatchTimeReporterTest, HysteresisFinalizedWithEarliest) {
   RunHysteresisTest([this]() {
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index f37e0f1..0ef078f 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -456,6 +456,24 @@
     watch_time_reporter_->OnNativeControlsDisabled();
 }
 
+void WebMediaPlayerImpl::OnDisplayTypeChanged(
+    WebMediaPlayer::DisplayType display_type) {
+  if (!watch_time_reporter_)
+    return;
+
+  switch (display_type) {
+    case WebMediaPlayer::DisplayType::kInline:
+      watch_time_reporter_->OnDisplayTypeInline();
+      break;
+    case WebMediaPlayer::DisplayType::kFullscreen:
+      watch_time_reporter_->OnDisplayTypeFullscreen();
+      break;
+    case WebMediaPlayer::DisplayType::kPictureInPicture:
+      watch_time_reporter_->OnDisplayTypePictureInPicture();
+      break;
+  }
+}
+
 void WebMediaPlayerImpl::DoLoad(LoadType load_type,
                                 const blink::WebURL& url,
                                 CORSMode cors_mode) {
@@ -2311,14 +2329,28 @@
                             media_log_.get(), pipeline_metadata_.natural_size,
                             base::Bind(&GetCurrentTimeInternal, this)));
   watch_time_reporter_->OnVolumeChange(volume_);
+
   if (delegate_->IsFrameHidden())
     watch_time_reporter_->OnHidden();
   else
     watch_time_reporter_->OnShown();
+
   if (client_->HasNativeControls())
     watch_time_reporter_->OnNativeControlsEnabled();
   else
     watch_time_reporter_->OnNativeControlsDisabled();
+
+  switch (client_->DisplayType()) {
+    case WebMediaPlayer::DisplayType::kInline:
+      watch_time_reporter_->OnDisplayTypeInline();
+      break;
+    case WebMediaPlayer::DisplayType::kFullscreen:
+      watch_time_reporter_->OnDisplayTypeFullscreen();
+      break;
+    case WebMediaPlayer::DisplayType::kPictureInPicture:
+      watch_time_reporter_->OnDisplayTypePictureInPicture();
+      break;
+  }
 }
 
 bool WebMediaPlayerImpl::IsHidden() const {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 5bdf19e..da0d8b6 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -194,6 +194,7 @@
   void BecameDominantVisibleContent(bool isDominant) override;
   void SetIsEffectivelyFullscreen(bool isEffectivelyFullscreen) override;
   void OnHasNativeControlsChanged(bool) override;
+  void OnDisplayTypeChanged(WebMediaPlayer::DisplayType) override;
 
   // WebMediaPlayerDelegate::Observer implementation.
   void OnFrameHidden() override;
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index 4915476..49ee8b9 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -103,6 +103,9 @@
     return blink::WebMediaPlayer::TrackId();
   }
   bool HasNativeControls() override { return false; }
+  blink::WebMediaPlayer::DisplayType DisplayType() const override {
+    return blink::WebMediaPlayer::DisplayType::kInline;
+  }
 
   void set_is_autoplaying_muted(bool value) { is_autoplaying_muted_ = value; }
 
diff --git a/media/capture/video/fake_video_capture_device.h b/media/capture/video/fake_video_capture_device.h
index ffc0e8d..33cab32e 100644
--- a/media/capture/video/fake_video_capture_device.h
+++ b/media/capture/video/fake_video_capture_device.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <string>
 
+#include "base/threading/thread_checker.h"
 #include "media/capture/video/video_capture_device.h"
 
 namespace media {
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc
index c044c52..c9172b6 100644
--- a/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -426,7 +426,9 @@
       device.reset();
   } else if (device_descriptor.capture_api ==
              VideoCaptureApi::WIN_DIRECT_SHOW) {
-    device.reset(new VideoCaptureDeviceWin(device_descriptor));
+    device.reset(new VideoCaptureDeviceWin(
+        device_descriptor,
+        base::FeatureList::IsEnabled(kImageCaptureControls)));
     DVLOG(1) << " DirectShow Device: " << device_descriptor.display_name;
     if (!static_cast<VideoCaptureDeviceWin*>(device.get())->Init())
       device.reset();
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc
index ce27a07c..532722a 100644
--- a/media/capture/video/win/video_capture_device_win.cc
+++ b/media/capture/video/win/video_capture_device_win.cc
@@ -264,8 +264,10 @@
 }
 
 VideoCaptureDeviceWin::VideoCaptureDeviceWin(
-    const VideoCaptureDeviceDescriptor& device_descriptor)
+    const VideoCaptureDeviceDescriptor& device_descriptor,
+    bool allow_image_capture_controls)
     : device_descriptor_(device_descriptor),
+      allow_image_capture_controls_(allow_image_capture_controls),
       state_(kIdle),
       white_balance_mode_manual_(false),
       exposure_mode_manual_(false) {
@@ -466,8 +468,13 @@
   client_->OnStarted();
   state_ = kCapturing;
 
+  if (allow_image_capture_controls_)
+    InitializeVideoAndCameraControls();
+}
+
+void VideoCaptureDeviceWin::InitializeVideoAndCameraControls() {
   base::win::ScopedComPtr<IKsTopologyInfo> info;
-  hr = capture_filter_.CopyTo(info.GetAddressOf());
+  HRESULT hr = capture_filter_.CopyTo(info.GetAddressOf());
   if (FAILED(hr)) {
     SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr);
     return;
@@ -525,6 +532,10 @@
 
 void VideoCaptureDeviceWin::TakePhoto(TakePhotoCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (!allow_image_capture_controls_)
+    return;
+
   // DirectShow has other means of capturing still pictures, e.g. connecting a
   // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This
   // way, however, is not widespread and proves too cumbersome, so we just grab
@@ -535,7 +546,7 @@
 void VideoCaptureDeviceWin::GetPhotoState(GetPhotoStateCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (!camera_control_ || !video_control_)
+  if (!camera_control_ || !video_control_ || !allow_image_capture_controls_)
     return;
 
   auto photo_capabilities = mojom::PhotoState::New();
@@ -627,7 +638,7 @@
     VideoCaptureDevice::SetPhotoOptionsCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (!camera_control_ || !video_control_)
+  if (!camera_control_ || !video_control_ || !allow_image_capture_controls_)
     return;
 
   HRESULT hr;
diff --git a/media/capture/video/win/video_capture_device_win.h b/media/capture/video/win/video_capture_device_win.h
index 8a2ed6cc..f6d28d7 100644
--- a/media/capture/video/win/video_capture_device_win.h
+++ b/media/capture/video/win/video_capture_device_win.h
@@ -65,8 +65,8 @@
   static VideoPixelFormat TranslateMediaSubtypeToPixelFormat(
       const GUID& sub_type);
 
-  explicit VideoCaptureDeviceWin(
-      const VideoCaptureDeviceDescriptor& device_descriptor);
+  VideoCaptureDeviceWin(const VideoCaptureDeviceDescriptor& device_descriptor,
+                        bool allow_image_capture_controls);
   ~VideoCaptureDeviceWin() override;
   // Opens the device driver for this device.
   bool Init();
@@ -89,6 +89,8 @@
                  // User needs to recover by destroying the object.
   };
 
+  void InitializeVideoAndCameraControls();
+
   // Implements SinkFilterObserver.
   void FrameReceived(const uint8_t* buffer,
                      int length,
@@ -102,6 +104,7 @@
                      HRESULT hr);
 
   const VideoCaptureDeviceDescriptor device_descriptor_;
+  const bool allow_image_capture_controls_;
   InternalState state_;
   std::unique_ptr<VideoCaptureDevice::Client> client_;
 
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md
index c43a132..a98708e 100644
--- a/mojo/public/cpp/bindings/README.md
+++ b/mojo/public/cpp/bindings/README.md
@@ -366,10 +366,18 @@
 
 ### Connection Errors
 
-If there are no remaining messages available on a pipe and the remote end has
-been closed, a connection error will be triggered on the local end. Connection
-errors may also be triggered by automatic forced local pipe closure due to
-*e.g.* a validation error when processing a received message.
+If a pipe is disconnected, both endpoints will be able to observe the connection
+error (unless the disconnection is caused by closing/destroying an endpoint, in
+which case that endpoint won't get such a notification). If there are remaining
+incoming messages for an endpoint on disconnection, the connection error won't
+be triggered until the messages are drained.
+
+Pipe disconnecition may be caused by:
+* Mojo system-level causes: process terminated, resource exhausted, etc.
+* The bindings close the pipe due to a validation error when processing a
+  received message.
+* The peer endpoint is closed. For example, the remote side is a bound
+  `mojo::InterfacePtr<T>` and it is destroyed.
 
 Regardless of the underlying cause, when a connection error is encountered on
 a binding endpoint, that endpoint's **connection error handler** (if set) is
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
index a80be35d..68236ca 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -32,12 +32,6 @@
 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
-// TODO(sammc): Remove these includes. Various files are not including what they
-// use, but are instead depending on mojo headers including what they use.
-// To avoid unrelated changes, these includes are left for now.
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
-
 namespace base {
 class SequencedTaskRunner;
 }
diff --git a/mojo/public/js/README.md b/mojo/public/js/README.md
index 862be29..b978c2ee 100644
--- a/mojo/public/js/README.md
+++ b/mojo/public/js/README.md
@@ -141,10 +141,18 @@
 disconnected.
 
 ### Connection Errors
-If there are no remaining messages available on a pipe and the remote end has
-been closed, a connection error will be triggered on the local end. Connection
-errors may also be triggered by automatic forced local pipe closure due to
-*e.g.* a validation error when processing a received message.
+If a pipe is disconnected, both endpoints will be able to observe the connection
+error (unless the disconnection is caused by closing/destroying an endpoint, in
+which case that endpoint won't get such a notification). If there are remaining
+incoming messages for an endpoint on disconnection, the connection error won't
+be triggered until the messages are drained.
+
+Pipe disconnecition may be caused by:
+* Mojo system-level causes: process terminated, resource exhausted, etc.
+* The bindings close the pipe due to a validation error when processing a
+  received message.
+* The peer endpoint is closed. For example, the remote side is a bound interface
+  pointer and it is destroyed.
 
 Regardless of the underlying cause, when a connection error is encountered on
 a binding endpoint, that endpoint's **connection error handler** (if set) is
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index ef08e7c..7ccf452 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -765,7 +765,7 @@
 
   bool result = true;
   if (positive_diff.size() > 0)
-    result = this->cookie_monster()->SetCanonicalCookies(list_);
+    result = this->cookie_monster()->SetAllCookies(list_);
 
   if (!callback_.is_null())
     callback_.Run(result);
@@ -1085,10 +1085,6 @@
     return false;
   }
 
-  // Validate passed arguments against URL.
-  if (secure && !url.SchemeIsCryptographic())
-    return false;
-
   std::string cookie_domain;
   if (!cookie_util::GetCookieDomainWithString(url, domain, &cookie_domain))
     return false;
@@ -1111,11 +1107,7 @@
       expiration_time, last_access_time, secure, http_only, same_site,
       priority));
 
-  CookieOptions options;
-  options.set_include_httponly();
-  options.set_same_site_cookie_mode(
-      CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
-  return SetCanonicalCookie(std::move(cc), url, options);
+  return SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(), true);
 }
 
 CookieList CookieMonster::GetAllCookies() {
@@ -1434,7 +1426,7 @@
     if (creation_times_.insert(cookie_creation_time).second) {
       CanonicalCookie* cookie_ptr = cookie.get();
       CookieMap::iterator inserted = InternalInsertCookie(
-          GetKey(cookie_ptr->Domain()), std::move(cookie), GURL(), false);
+          GetKey(cookie_ptr->Domain()), std::move(cookie), false);
       const Time cookie_access_time(cookie_ptr->LastAccessDate());
       if (earliest_access_time_.is_null() ||
           cookie_access_time < earliest_access_time_)
@@ -1648,7 +1640,7 @@
 
 bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
                                               const CanonicalCookie& ecc,
-                                              const GURL& source_url,
+                                              bool source_secure,
                                               bool skip_httponly,
                                               bool already_expired) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -1671,7 +1663,7 @@
     // attribute.
     //
     // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone
-    if (cc->IsSecure() && !source_url.SchemeIsCryptographic() &&
+    if (cc->IsSecure() && !source_secure &&
         ecc.IsEquivalentForSecureCookieMatching(*cc)) {
       skipped_secure_cookie = true;
       histogram_cookie_delete_equivalent_->Add(
@@ -1712,7 +1704,6 @@
 CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
     const std::string& key,
     std::unique_ptr<CanonicalCookie> cc,
-    const GURL& source_url,
     bool sync_to_store) {
   DCHECK(thread_checker_.CalledOnValidThread());
   CanonicalCookie* cc_ptr = cc.get();
@@ -1735,27 +1726,6 @@
   type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
   histogram_cookie_type_->Add(type_sample);
 
-  // Histogram the type of scheme used on URLs that set cookies. This
-  // intentionally includes cookies that are set or overwritten by
-  // http:// URLs, but not cookies that are cleared by http:// URLs, to
-  // understand if the former behavior can be deprecated for Secure
-  // cookies.
-  if (!source_url.is_empty()) {
-    CookieSource cookie_source_sample;
-    if (source_url.SchemeIsCryptographic()) {
-      cookie_source_sample =
-          cc_ptr->IsSecure()
-              ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
-              : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME;
-    } else {
-      cookie_source_sample =
-          cc_ptr->IsSecure()
-              ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
-              : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME;
-    }
-    histogram_cookie_source_scheme_->Add(cookie_source_sample);
-  }
-
   RunCookieChangedCallbacks(*cc_ptr, CookieStore::ChangeCause::INSERTED);
 
   return inserted;
@@ -1783,20 +1753,24 @@
     VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
     return false;
   }
-  return SetCanonicalCookie(std::move(cc), url, options);
+  return SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(),
+                            !options.exclude_httponly());
 }
 
 bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
-                                       const GURL& source_url,
-                                       const CookieOptions& options) {
+                                       bool secure_source,
+                                       bool modify_http_only) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  if (cc->IsSecure() && !secure_source)
+    return false;
+
   Time creation_time = cc->CreationDate();
   const std::string key(GetKey(cc->Domain()));
   bool already_expired = cc->IsExpired(creation_time);
 
-  if (DeleteAnyEquivalentCookie(key, *cc, source_url,
-                                options.exclude_httponly(), already_expired)) {
+  if (DeleteAnyEquivalentCookie(key, *cc, secure_source, !modify_http_only,
+                                already_expired)) {
     std::string error;
     error =
         "SetCookie() not clobbering httponly cookie or secure cookie for "
@@ -1818,7 +1792,22 @@
           (cc->ExpiryDate() - creation_time).InMinutes());
     }
 
-    InternalInsertCookie(key, std::move(cc), source_url, true);
+    // Histogram the type of scheme used on URLs that set cookies. This
+    // intentionally includes cookies that are set or overwritten by
+    // http:// URLs, but not cookies that are cleared by http:// URLs, to
+    // understand if the former behavior can be deprecated for Secure
+    // cookies.
+    CookieSource cookie_source_sample =
+        (secure_source
+             ? (cc->IsSecure()
+                    ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
+                    : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME)
+             : (cc->IsSecure()
+                    ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
+                    : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME));
+    histogram_cookie_source_scheme_->Add(cookie_source_sample);
+
+    InternalInsertCookie(key, std::move(cc), true);
   } else {
     VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
   }
@@ -1833,20 +1822,33 @@
   return true;
 }
 
-bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
+bool CookieMonster::SetAllCookies(const CookieList& list) {
   DCHECK(thread_checker_.CalledOnValidThread());
-
-  CookieOptions options;
-  options.set_include_httponly();
-
   for (const auto& cookie : list) {
-    // Use an empty GURL.  This method does not support setting secure cookies.
-    if (!SetCanonicalCookie(base::MakeUnique<CanonicalCookie>(cookie), GURL(),
-                            options)) {
-      return false;
+    const std::string key(GetKey(cookie.Domain()));
+    Time creation_time = cookie.CreationDate();
+    bool already_expired = cookie.IsExpired(creation_time);
+
+    bool result =
+        DeleteAnyEquivalentCookie(key, cookie, true, false, already_expired);
+    DCHECK(!result);
+
+    if (already_expired)
+      continue;
+
+    if (cookie.IsPersistent()) {
+      histogram_expiration_duration_minutes_->Add(
+          (cookie.ExpiryDate() - creation_time).InMinutes());
     }
+
+    InternalInsertCookie(key, base::MakeUnique<CanonicalCookie>(cookie), true);
+    GarbageCollect(creation_time, key);
   }
 
+  // TODO(rdsmith): If this function always returns the same value, it
+  // shouldn't have a return value.  But it should also be deleted (see
+  // https://codereview.chromium.org/2882063002/#msg64), which would
+  // solve the return value problem.
   return true;
 }
 
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 219b5b0..42afd9a 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -149,10 +149,12 @@
 
   ~CookieMonster() override;
 
-  // Replaces all the cookies by |list|. This method does not flush the backend.
-  // This method does not support setting secure cookies, which need source
-  // URLs.
-  // TODO(mmenke): This method is only used on iOS. Consider removing it.
+  // Writes all the cookies in |list| into the store, replacing existing
+  // cookies that collide.  Does not affect cookies not listed in |list|.
+  // This method does not flush the backend.
+  // TODO(rdsmith, mmenke): Do not use this function; it is deprecated
+  // and should be removed.
+  // See https://codereview.chromium.org/2882063002/#msg64.
   void SetAllCookiesAsync(const CookieList& list,
                           const SetCookiesCallback& callback);
 
@@ -515,7 +517,8 @@
                          std::vector<CanonicalCookie*>* cookies);
 
   // Delete any cookies that are equivalent to |ecc| (same path, domain, etc).
-  // |source_url| is the URL that is attempting to set the cookie.
+  // |source_secure| indicates if the source may override existing secure
+  // cookies.
   // If |skip_httponly| is true, httponly cookies will not be deleted.  The
   // return value will be true if |skip_httponly| skipped an httponly cookie or
   // the cookie to delete was Secure and the scheme of |ecc| is insecure.  |key|
@@ -524,7 +527,7 @@
   // NOTE: There should never be more than a single matching equivalent cookie.
   bool DeleteAnyEquivalentCookie(const std::string& key,
                                  const CanonicalCookie& ecc,
-                                 const GURL& source_url,
+                                 bool source_secure,
                                  bool skip_httponly,
                                  bool already_expired);
 
@@ -532,7 +535,6 @@
   // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid.
   CookieMap::iterator InternalInsertCookie(const std::string& key,
                                            std::unique_ptr<CanonicalCookie> cc,
-                                           const GURL& source_url,
                                            bool sync_to_store);
 
   // Helper function that sets cookies with more control.
@@ -543,15 +545,19 @@
                                            const base::Time& creation_time,
                                            const CookieOptions& options);
 
-  // Helper function that sets a canonical cookie, deleting equivalents and
-  // performing garbage collection.
-  // |source_url| is the URL that's attempting to set the cookie.
-  bool SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
-                          const GURL& source_url,
-                          const CookieOptions& options);
+  // Sets a canonical cookie, deletes equivalents and performs garbage
+  // collection.  |source_secure| indicates if the cookie is being set
+  // from a secure source (e.g. a cryptographic scheme).
+  // |modify_http_only| indicates if this setting operation is allowed
+  // to affect http_only cookies.
+  bool SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cookie,
+                          bool secure_source,
+                          bool can_modify_httponly);
 
-  // Helper function calling SetCanonicalCookie() for all cookies in |list|.
-  bool SetCanonicalCookies(const CookieList& list);
+  // Sets all cookies from |list| after deleting any equivalent cookie.
+  // For data gathering purposes, this routine is treated as if it is
+  // restoring saved cookies; some statistics are not gathered in this case.
+  bool SetAllCookies(const CookieList& list);
 
   void InternalUpdateCookieAccessTime(CanonicalCookie* cc,
                                       const base::Time& current_time);
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc
index 999d3f6..19a2192 100644
--- a/net/dns/host_cache.cc
+++ b/net/dns/host_cache.cc
@@ -145,7 +145,7 @@
 }
 
 HostCache::HostCache(size_t max_entries)
-    : max_entries_(max_entries), network_changes_(0) {}
+    : max_entries_(max_entries), network_changes_(0), delegate_(nullptr) {}
 
 HostCache::~HostCache() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -210,21 +210,31 @@
   if (caching_is_disabled())
     return;
 
+  bool result_changed = false;
   auto it = entries_.find(key);
   if (it != entries_.end()) {
     bool is_stale = it->second.IsStale(now, network_changes_);
+    AddressListDeltaType delta =
+        FindAddressListDeltaType(it->second.addresses(), entry.addresses());
     RecordSet(is_stale ? SET_UPDATE_STALE : SET_UPDATE_VALID, now, &it->second,
-              entry);
+              entry, delta);
     // TODO(juliatuttle): Remember some old metadata (hit count or frequency or
     // something like that) if it's useful for better eviction algorithms?
+    result_changed =
+        entry.error() == OK &&
+        (it->second.error() != entry.error() || delta != DELTA_IDENTICAL);
     entries_.erase(it);
   } else {
+    result_changed = true;
     if (size() == max_entries_)
       EvictOneEntry(now);
-    RecordSet(SET_INSERT, now, nullptr, entry);
+    RecordSet(SET_INSERT, now, nullptr, entry, DELTA_DISJOINT);
   }
 
   AddEntry(Key(key), Entry(entry, now, ttl, network_changes_));
+
+  if (delegate_ && result_changed)
+    delegate_->ScheduleWrite();
 }
 
 void HostCache::AddEntry(const Key& key, const Entry& entry) {
@@ -241,7 +251,14 @@
 void HostCache::clear() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   RecordEraseAll(ERASE_CLEAR, base::TimeTicks::Now());
+
+  // Don't bother scheduling a write if there's nothing to clear.
+  if (size() == 0)
+    return;
+
   entries_.clear();
+  if (delegate_)
+    delegate_->ScheduleWrite();
 }
 
 void HostCache::ClearForHosts(
@@ -253,6 +270,7 @@
     return;
   }
 
+  bool changed = false;
   base::TimeTicks now = base::TimeTicks::Now();
   for (EntryMap::iterator it = entries_.begin(); it != entries_.end();) {
     EntryMap::iterator next_it = std::next(it);
@@ -260,10 +278,14 @@
     if (host_filter.Run(it->first.hostname)) {
       RecordErase(ERASE_CLEAR, now, it->second);
       entries_.erase(it);
+      changed = true;
     }
 
     it = next_it;
   }
+
+  if (delegate_ && changed)
+    delegate_->ScheduleWrite();
 }
 
 std::unique_ptr<base::ListValue> HostCache::GetAsListValue(
@@ -417,7 +439,8 @@
 void HostCache::RecordSet(SetOutcome outcome,
                           base::TimeTicks now,
                           const Entry* old_entry,
-                          const Entry& new_entry) {
+                          const Entry& new_entry,
+                          AddressListDeltaType delta) {
   CACHE_HISTOGRAM_ENUM("Set", outcome, MAX_SET_OUTCOME);
   switch (outcome) {
     case SET_INSERT:
@@ -432,8 +455,6 @@
                             stale.network_changes);
       CACHE_HISTOGRAM_COUNT("UpdateStale.StaleHits", stale.stale_hits);
       if (old_entry->error() == OK && new_entry.error() == OK) {
-        AddressListDeltaType delta = FindAddressListDeltaType(
-            old_entry->addresses(), new_entry.addresses());
         RecordUpdateStale(delta, stale);
       }
       break;
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h
index 39c95e4..13042e3 100644
--- a/net/dns/host_cache.h
+++ b/net/dns/host_cache.h
@@ -124,6 +124,15 @@
     int stale_hits_;
   };
 
+  // Interface for interacting with persistent storage, to be provided by the
+  // embedder. Does not include support for writes that must happen immediately.
+  class PersistenceDelegate {
+   public:
+    // Calling ScheduleWrite() signals that data has changed and should be
+    // written to persistent storage. The write might be delayed.
+    virtual void ScheduleWrite() = 0;
+  };
+
   using EntryMap = std::map<Key, Entry>;
   using EvictionCallback = base::Callback<void(const Key&, const Entry&)>;
 
@@ -158,6 +167,10 @@
     eviction_callback_ = callback;
   }
 
+  void set_persistence_delegate(PersistenceDelegate* delegate) {
+    delegate_ = delegate;
+  }
+
   // Empties the cache.
   void clear();
 
@@ -196,7 +209,8 @@
   void RecordSet(SetOutcome outcome,
                  base::TimeTicks now,
                  const Entry* old_entry,
-                 const Entry& new_entry);
+                 const Entry& new_entry,
+                 AddressListDeltaType delta);
   void RecordUpdateStale(AddressListDeltaType delta,
                          const EntryStaleness& stale);
   void RecordLookup(LookupOutcome outcome,
@@ -219,6 +233,8 @@
   int network_changes_;
   EvictionCallback eviction_callback_;
 
+  PersistenceDelegate* delegate_;
+
   THREAD_CHECKER(thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(HostCache);
diff --git a/net/dns/host_cache_unittest.cc b/net/dns/host_cache_unittest.cc
index 15a43e3c..66c0faa 100644
--- a/net/dns/host_cache_unittest.cc
+++ b/net/dns/host_cache_unittest.cc
@@ -5,6 +5,7 @@
 #include "net/dns/host_cache.h"
 
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/callback.h"
@@ -31,6 +32,16 @@
   return (foobarx_com[6] - '0') % 2 == 1;
 }
 
+class MockPersistenceDelegate : public HostCache::PersistenceDelegate {
+ public:
+  void ScheduleWrite() override { ++num_changes_; }
+
+  int num_changes() const { return num_changes_; }
+
+ private:
+  int num_changes_ = 0;
+};
+
 }  // namespace
 
 TEST(HostCacheTest, Basic) {
@@ -274,7 +285,7 @@
   HostCache::Entry entry = HostCache::Entry(OK, AddressList());
 
   // Lookup and Set should have no effect.
-  EXPECT_FALSE(cache.Lookup(Key("foobar.com"),now));
+  EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now));
   cache.Set(Key("foobar.com"), entry, now, kTTL);
   EXPECT_FALSE(cache.Lookup(Key("foobar.com"), now));
 
@@ -752,4 +763,77 @@
   EXPECT_EQ(address_ipv4, result4->addresses().front().address());
 }
 
+TEST(HostCacheTest, PersistenceDelegate) {
+  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+  HostCache cache(kMaxCacheEntries);
+  MockPersistenceDelegate delegate;
+  cache.set_persistence_delegate(&delegate);
+
+  HostCache::Key key1 = Key("foobar.com");
+  HostCache::Key key2 = Key("foobar2.com");
+
+  IPAddress address_ipv4(1, 2, 3, 4);
+  IPAddress address_ipv6(0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+  IPEndPoint endpoint_ipv4(address_ipv4, 0);
+  IPEndPoint endpoint_ipv6(address_ipv6, 0);
+
+  HostCache::Entry entry1 = HostCache::Entry(OK, AddressList(endpoint_ipv4));
+  AddressList addresses2 = AddressList(endpoint_ipv6);
+  addresses2.push_back(endpoint_ipv4);
+  HostCache::Entry entry2 = HostCache::Entry(OK, addresses2);
+  HostCache::Entry entry3 =
+      HostCache::Entry(ERR_NAME_NOT_RESOLVED, AddressList());
+  HostCache::Entry entry4 = HostCache::Entry(OK, AddressList());
+
+  // Start at t=0.
+  base::TimeTicks now;
+  EXPECT_EQ(0u, cache.size());
+
+  // Add two entries at t=0.
+  EXPECT_FALSE(cache.Lookup(key1, now));
+  cache.Set(key1, entry1, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_EQ(1u, cache.size());
+  EXPECT_EQ(1, delegate.num_changes());
+
+  EXPECT_FALSE(cache.Lookup(key2, now));
+  cache.Set(key2, entry3, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key2, now));
+  EXPECT_EQ(2u, cache.size());
+  EXPECT_EQ(2, delegate.num_changes());
+
+  // Advance to t=5.
+  now += base::TimeDelta::FromSeconds(5);
+
+  // Changes that shouldn't trigger a write:
+  // Add an entry for "foobar.com" with different expiration time.
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  cache.Set(key1, entry1, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_EQ(2u, cache.size());
+  EXPECT_EQ(2, delegate.num_changes());
+
+  // Add an entry for "foobar.com" with different TTL.
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  cache.Set(key1, entry1, now, kTTL - base::TimeDelta::FromSeconds(5));
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_EQ(2u, cache.size());
+  EXPECT_EQ(2, delegate.num_changes());
+
+  // Changes that should trigger a write:
+  // Add an entry for "foobar.com" with different address list.
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  cache.Set(key1, entry2, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_EQ(2u, cache.size());
+  EXPECT_EQ(3, delegate.num_changes());
+
+  // Add an entry for "foobar2.com" with different error.
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  cache.Set(key2, entry4, now, kTTL);
+  EXPECT_TRUE(cache.Lookup(key1, now));
+  EXPECT_EQ(2u, cache.size());
+  EXPECT_EQ(4, delegate.num_changes());
+}
+
 }  // namespace net
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index f0167a3..9d93a6452 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -832,7 +832,8 @@
             static_cast<DBCookiePriority>(smt.ColumnInt(13)))));  // priority
     DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
         << L"CreationDate too recent";
-    cookies->push_back(std::move(cc));
+    if (cc->IsCanonical())
+      cookies->push_back(std::move(cc));
     ++num_cookies_read_;
   }
 }
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index d8be57e..54c520c 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
+#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
@@ -480,7 +481,7 @@
   cookies.clear();
 }
 
-// Test loading old session cookies from the disk.
+// Test refusing to load old session cookies from the disk.
 // TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
 TEST_F(SQLitePersistentCookieStoreTest,
        DISABLED_TestDontLoadOldSessionCookies) {
@@ -511,6 +512,58 @@
   ASSERT_EQ(0U, cookies.size());
 }
 
+// Confirm bad cookies on disk don't get looaded
+TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookies) {
+  // Create an on-disk store.
+  InitializeStore(false, true);
+  DestroyStore();
+
+  // Add some cookies in by hand.
+  base::FilePath store_name(temp_dir_.GetPath().Append(kCookieFilename));
+  std::unique_ptr<sql::Connection> db(base::MakeUnique<sql::Connection>());
+  ASSERT_TRUE(db->Open(store_name));
+  sql::Statement stmt(db->GetUniqueStatement(
+      "INSERT INTO cookies (creation_utc, host_key, name, value, "
+      "encrypted_value, path, expires_utc, secure, httponly, "
+      "firstpartyonly, last_access_utc, has_expires, persistent, priority) "
+      "VALUES (?,'google.izzle',?,?,'',?,0,0,0,0,0,1,1,0)"));
+  ASSERT_TRUE(stmt.is_valid());
+
+  struct CookieInfo {
+    const char* name;
+    const char* value;
+    const char* path;
+  } cookies_info[] = {// A couple non-canonical cookies.
+                      {"A=", "B", "/path"},
+                      {"C ", "D", "/path"},
+
+                      // A canonical cookie.
+                      {"E", "F", "/path"}};
+
+  int64_t creation_time = 1;
+  for (auto& cookie_info : cookies_info) {
+    stmt.Reset(true);
+
+    stmt.BindInt64(0, creation_time++);
+    stmt.BindString(1, cookie_info.name);
+    stmt.BindString(2, cookie_info.value);
+    stmt.BindString(3, cookie_info.path);
+    ASSERT_TRUE(stmt.Run());
+  }
+  stmt.Clear();
+  db.reset();
+
+  // Reopen the store and confirm that the only cookie loaded is the
+  // canonical one.
+  CanonicalCookieVector cookies;
+  CreateAndLoad(false, false, &cookies);
+  ASSERT_EQ(1U, cookies.size());
+  EXPECT_STREQ("E", cookies[0]->Name().c_str());
+  EXPECT_STREQ("F", cookies[0]->Value().c_str());
+  EXPECT_STREQ("/path", cookies[0]->Path().c_str());
+  DestroyStore();
+}
+
 // TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
 TEST_F(SQLitePersistentCookieStoreTest, DISABLED_PersistIsPersistent) {
   InitializeStore(false, true);
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index 73626e04..e5202c0 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -891,9 +891,10 @@
       GetDynamicExpectCTState(hostname, &state)) {
     if (expect_ct_reporter_ && !state.report_uri.is_empty() &&
         report_status == ENABLE_EXPECT_CT_REPORTS) {
-      MaybeNotifyExpectCTFailed(
-          host_port_pair, state.report_uri, validated_certificate_chain,
-          served_certificate_chain, signed_certificate_timestamps);
+      MaybeNotifyExpectCTFailed(host_port_pair, state.report_uri, state.expiry,
+                                validated_certificate_chain,
+                                served_certificate_chain,
+                                signed_certificate_timestamps);
     }
     if (state.enforce)
       return CT_REQUIREMENTS_NOT_MET;
@@ -1208,6 +1209,7 @@
 void TransportSecurityState::MaybeNotifyExpectCTFailed(
     const HostPortPair& host_port_pair,
     const GURL& report_uri,
+    base::Time expiration,
     const X509Certificate* validated_certificate_chain,
     const X509Certificate* served_certificate_chain,
     const SignedCertificateTimestampAndStatusList&
@@ -1228,7 +1230,7 @@
           base::TimeDelta::FromMinutes(kTimeToRememberReportsMins));
 
   expect_ct_reporter_->OnExpectCTFailed(
-      host_port_pair, report_uri, validated_certificate_chain,
+      host_port_pair, report_uri, expiration, validated_certificate_chain,
       served_certificate_chain, signed_certificate_timestamps);
 }
 
@@ -1476,7 +1478,7 @@
       return;
     ExpectCTState state;
     if (GetStaticExpectCTState(host_port_pair.host(), &state)) {
-      MaybeNotifyExpectCTFailed(host_port_pair, state.report_uri,
+      MaybeNotifyExpectCTFailed(host_port_pair, state.report_uri, base::Time(),
                                 ssl_info.cert.get(),
                                 ssl_info.unverified_cert.get(),
                                 ssl_info.signed_certificate_timestamps);
@@ -1512,7 +1514,8 @@
     // processing the header.
     if (expect_ct_reporter_ && !report_uri.is_empty() &&
         !GetDynamicExpectCTState(host_port_pair.host(), &state)) {
-      MaybeNotifyExpectCTFailed(host_port_pair, report_uri, ssl_info.cert.get(),
+      MaybeNotifyExpectCTFailed(host_port_pair, report_uri, base::Time(),
+                                ssl_info.cert.get(),
                                 ssl_info.unverified_cert.get(),
                                 ssl_info.signed_certificate_timestamps);
     }
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h
index e81aad5..5e75551 100644
--- a/net/http/transport_security_state.h
+++ b/net/http/transport_security_state.h
@@ -317,6 +317,7 @@
     virtual void OnExpectCTFailed(
         const net::HostPortPair& host_port_pair,
         const GURL& report_uri,
+        base::Time expiration,
         const X509Certificate* validated_certificate_chain,
         const X509Certificate* served_certificate_chain,
         const SignedCertificateTimestampAndStatusList&
@@ -671,6 +672,7 @@
   void MaybeNotifyExpectCTFailed(
       const HostPortPair& host_port_pair,
       const GURL& report_uri,
+      base::Time expiration,
       const X509Certificate* validated_certificate_chain,
       const X509Certificate* served_certificate_chain,
       const SignedCertificateTimestampAndStatusList&
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index f7a79c7..bfc8bee3 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -181,6 +181,7 @@
 
   void OnExpectCTFailed(const HostPortPair& host_port_pair,
                         const GURL& report_uri,
+                        base::Time expiration,
                         const X509Certificate* validated_certificate_chain,
                         const X509Certificate* served_certificate_chain,
                         const SignedCertificateTimestampAndStatusList&
@@ -188,6 +189,7 @@
     num_failures_++;
     host_port_pair_ = host_port_pair;
     report_uri_ = report_uri;
+    expiration_ = expiration;
     served_certificate_chain_ = served_certificate_chain;
     validated_certificate_chain_ = validated_certificate_chain;
     signed_certificate_timestamps_ = signed_certificate_timestamps;
@@ -195,6 +197,7 @@
 
   const HostPortPair& host_port_pair() { return host_port_pair_; }
   const GURL& report_uri() { return report_uri_; }
+  const base::Time& expiration() { return expiration_; }
   uint32_t num_failures() { return num_failures_; }
   const X509Certificate* served_certificate_chain() {
     return served_certificate_chain_;
@@ -210,6 +213,7 @@
  private:
   HostPortPair host_port_pair_;
   GURL report_uri_;
+  base::Time expiration_;
   uint32_t num_failures_;
   const X509Certificate* served_certificate_chain_;
   const X509Certificate* validated_certificate_chain_;
@@ -2125,6 +2129,7 @@
   EXPECT_EQ(1u, reporter.num_failures());
   EXPECT_EQ(host_port.host(), reporter.host_port_pair().host());
   EXPECT_EQ(host_port.port(), reporter.host_port_pair().port());
+  EXPECT_TRUE(reporter.expiration().is_null());
   EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
   EXPECT_EQ(cert1.get(), reporter.served_certificate_chain());
   EXPECT_EQ(cert2.get(), reporter.validated_certificate_chain());
@@ -3182,6 +3187,7 @@
   EXPECT_FALSE(state.GetDynamicExpectCTState("example.test", &expect_ct_state));
   EXPECT_EQ(1u, reporter.num_failures());
   EXPECT_EQ("example.test", reporter.host_port_pair().host());
+  EXPECT_TRUE(reporter.expiration().is_null());
   EXPECT_EQ(cert1.get(), reporter.served_certificate_chain());
   EXPECT_EQ(cert2.get(), reporter.validated_certificate_chain());
   EXPECT_EQ(ssl.signed_certificate_timestamps.size(),
@@ -3247,6 +3253,7 @@
   EXPECT_EQ(1u, reporter.num_failures());
   EXPECT_EQ("example.test", reporter.host_port_pair().host());
   EXPECT_EQ(443, reporter.host_port_pair().port());
+  EXPECT_EQ(expiry, reporter.expiration());
   EXPECT_EQ(cert1.get(), reporter.validated_certificate_chain());
   EXPECT_EQ(cert2.get(), reporter.served_certificate_chain());
   EXPECT_EQ(sct_list.size(), reporter.signed_certificate_timestamps().size());
@@ -3362,6 +3369,7 @@
   EXPECT_EQ(1u, reporter.num_failures());
   EXPECT_EQ("example.test", reporter.host_port_pair().host());
   EXPECT_EQ(443, reporter.host_port_pair().port());
+  EXPECT_EQ(expiry, reporter.expiration());
   EXPECT_EQ(cert1.get(), reporter.validated_certificate_chain());
   EXPECT_EQ(cert2.get(), reporter.served_certificate_chain());
   EXPECT_EQ(sct_list.size(), reporter.signed_certificate_timestamps().size());
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 50269d79..afa26c39 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -814,6 +814,7 @@
 
   void OnExpectCTFailed(const HostPortPair& host_port_pair,
                         const GURL& report_uri,
+                        base::Time expiration,
                         const X509Certificate* validated_certificate_chain,
                         const X509Certificate* served_certificate_chain,
                         const SignedCertificateTimestampAndStatusList&
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 449d59d7f..055f081 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -6704,6 +6704,7 @@
 
   void OnExpectCTFailed(const HostPortPair& host_port_pair,
                         const GURL& report_uri,
+                        base::Time expiration,
                         const X509Certificate* validated_certificate_chain,
                         const X509Certificate* served_certificate_chain,
                         const SignedCertificateTimestampAndStatusList&
diff --git a/remoting/ios/app/BUILD.gn b/remoting/ios/app/BUILD.gn
index 551ea38..59f2ccf 100644
--- a/remoting/ios/app/BUILD.gn
+++ b/remoting/ios/app/BUILD.gn
@@ -17,6 +17,7 @@
   sources = [
     "app_delegate.h",
     "app_delegate.mm",
+    "app_view_controller.h",
     "client_connection_view_controller.h",
     "client_connection_view_controller.mm",
     "host_collection_header_view.h",
@@ -27,10 +28,9 @@
     "host_collection_view_controller.mm",
     "host_view_controller.h",
     "host_view_controller.mm",
+    "main.mm",
     "pin_entry_view.h",
     "pin_entry_view.mm",
-    "remoting_menu_view_controller.h",
-    "remoting_menu_view_controller.mm",
     "remoting_theme.h",
     "remoting_theme.mm",
     "remoting_view_controller.h",
@@ -61,7 +61,9 @@
 
 source_set("main") {
   sources = [
-    "main.mm",
+    "app_view_controller_chromium.mm",
+    "remoting_menu_view_controller.h",
+    "remoting_menu_view_controller.mm",
   ]
   deps = [
     ":common_source_set",
diff --git a/remoting/ios/app/app_delegate.h b/remoting/ios/app/app_delegate.h
index 2e5bfff3..9235202 100644
--- a/remoting/ios/app/app_delegate.h
+++ b/remoting/ios/app/app_delegate.h
@@ -10,7 +10,12 @@
 // Default created delegate class for the entire application.
 @interface AppDelegate : UIResponder<UIApplicationDelegate>
 
+- (void)showMenuAnimated:(BOOL)animated;
+- (void)hideMenuAnimated:(BOOL)animated;
+- (void)presentSignInFlow;
+
 @property(strong, nonatomic) UIWindow* window;
+@property(class, strong, nonatomic, readonly) AppDelegate* instance;
 
 @end
 
diff --git a/remoting/ios/app/app_delegate.mm b/remoting/ios/app/app_delegate.mm
index d6c87e0..50a7597 100644
--- a/remoting/ios/app/app_delegate.mm
+++ b/remoting/ios/app/app_delegate.mm
@@ -12,10 +12,16 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
+#import "remoting/ios/app/app_view_controller.h"
 #import "remoting/ios/app/remoting_view_controller.h"
 #import "remoting/ios/facade/remoting_authentication.h"
 #import "remoting/ios/facade/remoting_service.h"
 
+@interface AppDelegate () {
+  AppViewController* _appViewController;
+}
+@end
+
 @implementation AppDelegate
 
 @synthesize window = _window;
@@ -53,12 +59,39 @@
   return YES;
 }
 
+#pragma mark - Public
+- (void)showMenuAnimated:(BOOL)animated {
+  DCHECK(_appViewController != nil);
+  [_appViewController showMenuAnimated:animated];
+}
+
+- (void)hideMenuAnimated:(BOOL)animated {
+  DCHECK(_appViewController != nil);
+  [_appViewController hideMenuAnimated:animated];
+}
+
+- (void)presentSignInFlow {
+  DCHECK(_appViewController != nil);
+  [_appViewController presentSignInFlow];
+}
+
+#pragma mark - Properties
+
++ (AppDelegate*)instance {
+  return (AppDelegate*)UIApplication.sharedApplication.delegate;
+}
+
+#pragma mark - Private
+
 - (void)launchRemotingViewController {
   RemotingViewController* vc = [[RemotingViewController alloc] init];
   UINavigationController* navController =
       [[UINavigationController alloc] initWithRootViewController:vc];
   navController.navigationBarHidden = true;
-  self.window.rootViewController = navController;
+
+  _appViewController =
+      [[AppViewController alloc] initWithMainViewController:navController];
+  self.window.rootViewController = _appViewController;
   [self.window makeKeyAndVisible];
 }
 
diff --git a/remoting/ios/app/app_view_controller.h b/remoting/ios/app/app_view_controller.h
new file mode 100644
index 0000000..efc5edc
--- /dev/null
+++ b/remoting/ios/app/app_view_controller.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_IOS_APP_APP_VIEW_CONTROLLER_H_
+#define REMOTING_IOS_APP_APP_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+@protocol AppController<NSObject>
+
+// For adding new methods, please mark them as optional until they are
+// implemented in both Chromium and ios_internal. For deletion, just reverse the
+// procedure. This is to prevent build break in internal buildbot.
+
+- (void)showMenuAnimated:(BOOL)animated;
+- (void)hideMenuAnimated:(BOOL)animated;
+- (void)presentSignInFlow;
+
+@end
+
+// The root view controller of the app. It acts as a container controller for
+// |mainViewController|, which will be shown as the primary content of the view.
+// Implementation can add drawer or modal for things like the side menu or help
+// and feedback.
+@interface AppViewController : UIViewController<AppController>
+
+- (instancetype)initWithMainViewController:
+    (UIViewController*)mainViewController;
+
+@end
+
+#endif  // REMOTING_IOS_APP_APP_VIEW_CONTROLLER_H_
diff --git a/remoting/ios/app/app_view_controller_chromium.mm b/remoting/ios/app/app_view_controller_chromium.mm
new file mode 100644
index 0000000..fb91461
--- /dev/null
+++ b/remoting/ios/app/app_view_controller_chromium.mm
@@ -0,0 +1,69 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#import "remoting/ios/app/app_view_controller.h"
+
+#include "base/logging.h"
+
+#import "remoting/ios/app/remoting_menu_view_controller.h"
+
+// The Chromium implementation for the AppViewController. It simply shows the
+// menu modally.
+@interface AppViewController () {
+  UIViewController* _mainViewController;
+
+  RemotingMenuViewController* _menuController;  // nullable
+}
+@end
+
+@implementation AppViewController
+
+- (instancetype)initWithMainViewController:
+    (UIViewController*)mainViewController {
+  if (self = [super init]) {
+    _mainViewController = mainViewController;
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [self addChildViewController:_mainViewController];
+  [self.view addSubview:_mainViewController.view];
+  [_mainViewController didMoveToParentViewController:self];
+}
+
+#pragma mark - AppController
+- (void)showMenuAnimated:(BOOL)animated {
+  if (_menuController != nil && [_menuController isBeingPresented]) {
+    return;
+  }
+  _menuController = [[RemotingMenuViewController alloc] init];
+  [self presentViewController:_menuController animated:animated completion:nil];
+}
+
+- (void)hideMenuAnimated:(BOOL)animated {
+  if (_menuController == nil || ![_menuController isBeingPresented]) {
+    return;
+  }
+  [_menuController dismissViewControllerAnimated:animated completion:nil];
+  _menuController = nil;
+}
+
+- (void)presentSignInFlow {
+  [self showMenuAnimated:YES];
+}
+
+- (UIViewController*)childViewControllerForStatusBarStyle {
+  return _mainViewController;
+}
+
+- (UIViewController*)childViewControllerForStatusBarHidden {
+  return _mainViewController;
+}
+
+@end
diff --git a/remoting/ios/app/remoting_view_controller.mm b/remoting/ios/app/remoting_view_controller.mm
index 99d91663..aea6122 100644
--- a/remoting/ios/app/remoting_view_controller.mm
+++ b/remoting/ios/app/remoting_view_controller.mm
@@ -13,6 +13,7 @@
 #import "ios/third_party/material_components_ios/src/components/AppBar/src/MaterialAppBar.h"
 #import "ios/third_party/material_components_ios/src/components/Dialogs/src/MaterialDialogs.h"
 #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
+#import "remoting/ios/app/app_delegate.h"
 #import "remoting/ios/app/client_connection_view_controller.h"
 #import "remoting/ios/app/host_collection_view_controller.h"
 #import "remoting/ios/app/host_view_controller.h"
@@ -135,10 +136,7 @@
 - (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   if (!_isAuthenticated) {
-    // TODO(nicholss): This is used as a demo of the app functionality for the
-    // moment but the real app will force the login flow if unauthenticated.
-    [self didSelectMenu];
-    // [self didSelectRefresh];
+    [AppDelegate.instance presentSignInFlow];
     MDCSnackbarMessage* message = [[MDCSnackbarMessage alloc] init];
     message.text = @"Please login.";
     [MDCSnackbarManager showMessage:message];
@@ -251,9 +249,7 @@
 }
 
 - (void)didSelectMenu {
-  RemotingMenuViewController* menuViewController =
-      [[RemotingMenuViewController alloc] init];
-  [self presentViewController:menuViewController animated:YES completion:nil];
+  [AppDelegate.instance showMenuAnimated:YES];
 }
 
 - (void)presentStatus {
diff --git a/services/service_manager/public/cpp/interface_binder.h b/services/service_manager/public/cpp/interface_binder.h
index 5420efe..b14efbe 100644
--- a/services/service_manager/public/cpp/interface_binder.h
+++ b/services/service_manager/public/cpp/interface_binder.h
@@ -44,7 +44,8 @@
 class CallbackBinder : public InterfaceBinder<BinderArgs...> {
  public:
   using BindCallback = base::Callback<void(const BindSourceInfo&,
-                                           mojo::InterfaceRequest<Interface>)>;
+                                           mojo::InterfaceRequest<Interface>,
+                                           BinderArgs...)>;
 
   CallbackBinder(const BindCallback& callback,
                  const scoped_refptr<base::SequencedTaskRunner>& task_runner)
diff --git a/services/video_capture/device_media_to_mojo_adapter.h b/services/video_capture/device_media_to_mojo_adapter.h
index f0b7591e..3557ab21 100644
--- a/services/video_capture/device_media_to_mojo_adapter.h
+++ b/services/video_capture/device_media_to_mojo_adapter.h
@@ -5,6 +5,7 @@
 #ifndef SERVICES_VIDEO_CAPTURE_DEVICE_MEDIA_TO_MOJO_ADAPTER_H_
 #define SERVICES_VIDEO_CAPTURE_DEVICE_MEDIA_TO_MOJO_ADAPTER_H_
 
+#include "base/threading/thread_checker.h"
 #include "media/capture/video/video_capture_device.h"
 #include "media/capture/video/video_capture_device_client.h"
 #include "media/capture/video_capture_types.h"
diff --git a/services/video_capture/service_impl.h b/services/video_capture/service_impl.h
index 34d7079..73a9c929 100644
--- a/services/video_capture/service_impl.h
+++ b/services/video_capture/service_impl.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index f96aaa4..4e6840c 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -198,10 +198,6 @@
 #   define SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE
 #endif
 
-#ifndef    SK_IGNORE_GPU_DITHER
-#   define SK_IGNORE_GPU_DITHER
-#endif
-
 // Remove this after we fixed all the issues related to the new SDF algorithm
 // (https://codereview.chromium.org/1643143002)
 #ifndef    SK_USE_LEGACY_DISTANCE_FIELDS
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index a647919..4d2660a 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -3966,7 +3966,7 @@
           ],
           "dimension_sets": [
             {
-              "android_devices": "6",
+              "android_devices": "1",
               "device_os": "LMY48I",
               "device_type": "hammerhead"
             }
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter
index 8115bfe9..914a6ff 100644
--- a/testing/buildbot/filters/fuchsia.base_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -66,33 +66,17 @@
 -FileProxyTest.SetTimes
 -FileTest.Append
 -FileUtilProxyTest.Touch
--FileUtilTest.AppendToFile
 -FileUtilTest.ChangeDirectoryPermissionsAndEnumerate
 -FileUtilTest.ChangeFilePermissionsAndRead
 -FileUtilTest.ChangeFilePermissionsAndWrite
 -FileUtilTest.CopyDirectoryACL
--FileUtilTest.CopyDirectoryExists
--FileUtilTest.CopyDirectoryNew
--FileUtilTest.CopyDirectoryRecursivelyExists
--FileUtilTest.CopyDirectoryRecursivelyNew
--FileUtilTest.CopyDirectoryWithTrailingSeparators
 -FileUtilTest.CopyFileACL
 -FileUtilTest.CreateAndReadSymlinks
--FileUtilTest.CreateDirectoryTest
--FileUtilTest.DeleteDirRecursive
 -FileUtilTest.DeleteSymlinkToExistentFile
 -FileUtilTest.DeleteSymlinkToNonExistentFile
--FileUtilTest.DetectDirectoryTest
 -FileUtilTest.ExecutableExistsInPath
--FileUtilTest.FileAndDirectorySize
--FileUtilTest.FileEnumeratorTest
 -FileUtilTest.FileToFILE
--FileUtilTest.IsDirectoryEmpty
 -FileUtilTest.NormalizeFilePathSymlinks
--FileUtilTest.ReadFile
--FileUtilTest.ReadFileToString
--FileUtilTest.SetCloseOnExec
--FileUtilTest.SetNonBlocking
 -FileUtilTest.TouchFile
 -HeapDumpWriterTest.BacktraceIndex
 -HeapDumpWriterTest.TypeId
diff --git a/testing/test_env.py b/testing/test_env.py
index 2e446e7..284185d5 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -52,7 +52,7 @@
   return out
 
 
-def get_sanitizer_env(cmd, asan, lsan, msan, tsan):
+def get_sanitizer_env(cmd, asan, lsan, msan, tsan, cfi_diag):
   """Returns the envirnoment flags needed for sanitizer tools."""
 
   extra_env = {}
@@ -73,7 +73,7 @@
     # fact, it needs symbolization to be able to apply suppressions.
     symbolization_options = ['symbolize=1',
                              'external_symbolizer_path=%s' % symbolizer_path]
-  elif (asan or msan) and sys.platform not in ['win32', 'cygwin']:
+  elif (asan or msan or cfi_diag) and sys.platform not in ['win32', 'cygwin']:
     # ASan uses a script for offline symbolization, except on Windows.
     # Important note: when running ASan with leak detection enabled, we must use
     # the LSan symbolization options above.
@@ -120,6 +120,11 @@
     tsan_options = symbolization_options[:]
     extra_env['TSAN_OPTIONS'] = ' '.join(tsan_options)
 
+  # CFI uses the UBSan runtime to provide diagnostics.
+  if cfi_diag:
+    ubsan_options = symbolization_options[:] + ['print_stacktrace=1']
+    extra_env['UBSAN_OPTIONS'] = ' '.join(ubsan_options)
+
   return extra_env
 
 
@@ -185,16 +190,17 @@
   lsan = '--lsan=1' in cmd
   msan = '--msan=1' in cmd
   tsan = '--tsan=1' in cmd
+  cfi_diag = '--cfi-diag=1' in cmd
   if sys.platform in ['win32', 'cygwin']:
     # Symbolization works in-process on Windows even when sandboxed.
     use_symbolization_script = False
   else:
     # LSan doesn't support sandboxing yet, so we use the in-process symbolizer.
     # Note that ASan and MSan can work together with LSan.
-    use_symbolization_script = (asan or msan) and not lsan
+    use_symbolization_script = (asan or msan or cfi_diag) and not lsan
 
-  if asan or lsan or msan or tsan:
-    extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
+  if asan or lsan or msan or tsan or cfi_diag:
+    extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan, cfi_diag))
 
   if lsan or tsan:
     # LSan and TSan are not sandbox-friendly.
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 30ead869..218c6b3 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -14828,7 +14828,6 @@
 crbug.com/591099 fast/writing-mode/flipped-blocks-hit-test-overflow.html [ Failure ]
 crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Crash Failure ]
 crbug.com/591099 fast/writing-mode/flipped-blocks-text-map-local-to-container.html [ Failure ]
-crbug.com/591099 fast/writing-mode/floats-in-block-layout.html [ Failure ]
 crbug.com/591099 fast/writing-mode/html-and-body-direction-propagation.html [ Failure Pass ]
 crbug.com/591099 fast/writing-mode/html-and-body-writing-mode-propagation.html [ Crash Failure Pass ]
 crbug.com/591099 fast/writing-mode/html-direction-propagation.html [ Crash Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/OWNERS b/third_party/WebKit/LayoutTests/OWNERS
index 0c995f7b..92d7595 100644
--- a/third_party/WebKit/LayoutTests/OWNERS
+++ b/third_party/WebKit/LayoutTests/OWNERS
@@ -1,10 +1,4 @@
 *
 
-# Changes to the SmokeTests file must be actually approved so it doesn't grow willy-nilly.
-per-file SmokeTests=set noparent
-per-file SmokeTests=dpranke@chromium.org
-per-file SmokeTests=peter@chromium.org
-per-file SmokeTests=ojan@chromium.org
-
 per-file ImageFirstTests=set noparent
 per-file ImageFirstTests=file://third_party/WebKit/Source/core/layout/OWNERS
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 1a37f56..88b935d6 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2777,3 +2777,6 @@
 crbug.com/733448 virtual/mojo-loading/http/tests/inspector/extensions/extensions-network.html [ Failure Pass ]
 crbug.com/733448 http/tests/inspector/extensions/extensions-network.html [ Failure Pass ]
 crbug.com/733524 [ Mac ] virtual/mojo-loading/http/tests/security/contentSecurityPolicy/report-cross-origin-no-cookies.php [ Timeout Pass ]
+
+# Rebaselining a newly-passing test fixed by v8
+crbug.com/v8/6504 fast/js/mozilla/strict/B.1.2.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-payment.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-payment.html
new file mode 100644
index 0000000..401a86e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-payment.html
@@ -0,0 +1,16 @@
+<script>
+'use strict';
+
+window.onload = function() {
+  var supportedInstruments = [ { supportedMethods: [ 'visa' ] } ];
+  var details = {
+      total: { label: 'Test', amount: { currency: 'USD', value: '5.00' } }
+  };
+  try {
+    new PaymentRequest(supportedInstruments, details);
+    parent.postMessage({ enabled: true }, '*');
+  } catch (e) {
+    parent.postMessage({ enabled: false }, '*');
+  }
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-usb.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-usb.html
new file mode 100644
index 0000000..99d47c6f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-usb.html
@@ -0,0 +1,9 @@
+<script>
+'use strict';
+
+Promise.resolve().then(() => navigator.usb.getDevices()).then(devices => {
+  window.parent.postMessage({ enabled: true }, '*');
+}, error => {
+  window.parent.postMessage({ enabled: false }, '*');
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
new file mode 100644
index 0000000..658b254
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
@@ -0,0 +1,56 @@
+// Tests whether a feature that is enabled/disabled by feature policy works
+// as expected.
+// Arguments:
+//    feature_description: a short string describing what feature is being
+//        tested. Examples: "usb.GetDevices()", "PaymentRequest()".
+//    test: test created by testharness. Examples: async_test, promise_test.
+//    src: URL where a feature's availability is checked. Examples:
+//        "/feature-policy/resources/feature-policy-payment.html",
+//        "/feature-policy/resources/feature-policy-usb.html".
+//    expect_feature_available: a callback(data, feature_description) to
+//        verify if a feature is avaiable or unavailable as expected.
+//        The file under the path "src" defines what "data" is sent back as a
+//        pistMessage. Inside the callback, some tests (e.g., EXPECT_EQ,
+//        EXPECT_TRUE, etc) are run accordingly to test a feature's
+//        availability.
+//        Example: expect_feature_available_default(data, feature_description).
+//    feature_name: Optional argument, only provided when testing iframe allow
+//      attribute. "feature_name" is the feature name of a policy controlled
+//      feature (https://wicg.github.io/feature-policy/#features).
+//      See examples at:
+//      https://github.com/WICG/feature-policy/blob/gh-pages/features.md
+//    allow_attribute: Optional argument, only used for testing fullscreen or
+//      payment: either "allowfullscreen" or "allowpaymentrequest" is passed.
+function test_feature_availability(
+    feature_description, test, src, expect_feature_available, feature_name,
+    allow_attribute) {
+  let frame = document.createElement('iframe');
+  frame.src = src;
+
+  if (typeof feature_name !== 'undefined') {
+    frame.allow.add(feature_name);
+  }
+
+  if (typeof allow_attribute !== 'undefined') {
+    frame.setAttribute(allow_attribute, true);
+  }
+
+  window.addEventListener('message', test.step_func(evt => {
+    if (evt.source === frame.contentWindow) {
+      expect_feature_available(evt.data, feature_description);
+      document.body.removeChild(frame);
+      test.done();
+    }
+  }));
+
+  document.body.appendChild(frame);
+}
+
+// Default helper functions to test a feature's availability:
+function expect_feature_available_default(data, feature_description) {
+  assert_true(data.enabled, feature_description);
+}
+
+function expect_feature_unavailable_default(data, feature_description) {
+  assert_false(data.enabled, feature_description);
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/redirect-on-load.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/redirect-on-load.html
new file mode 100644
index 0000000..1711655b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/redirect-on-load.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<body>
+<script>
+// Automatically redirects the page to a new URL on load.
+// Load this document with a URL like:
+//     "feature-policy/resources/redirect-on-load.html#https://www.example.com/"
+window.onload = function () {
+  document.location = document.location.hash.substring(1);
+}
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000..9a792173
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  'use strict';
+  var relative_path = '/feature-policy/resources/feature-policy-payment.html';
+  var base_src = '/feature-policy/resources/redirect-on-load.html#';
+  var same_origin_src = base_src + relative_path;
+  var cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+    relative_path;
+  var header = 'Feature-Policy allow="payment"';
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default, 'payment');
+  }, header + ' allows same-origin relocation.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_unavailable_default, 'payment');
+  }, header + ' disallows cross-origin relocation.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default, 'payment', 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true allows same-origin relocation.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_unavailable_default, 'payment', 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true disallows cross-origin relocation.');
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute.https.sub.html
new file mode 100644
index 0000000..eeebe399
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy-attribute.https.sub.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  'use strict';
+  var same_origin_src = '/feature-policy/resources/feature-policy-payment.html';
+  var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+    same_origin_src;
+  var feature_name = 'Feature policy "payment"';
+  var header = 'allow="payment" attribute';
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default, 'payment');
+  }, feature_name + ' can be enabled in same-origin iframe using ' + header);
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_available_default, 'payment');
+  }, feature_name + ' can be enabled in cross-origin iframe using ' + header);
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..b64cda813
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  'use strict';
+  var same_origin_src = '/feature-policy/resources/feature-policy-payment.html';
+  var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+    same_origin_src;
+  var header = 'Feature-Policy header {"payment" : ["*"]}';
+
+  test(() => {
+    var supportedInstruments = [ { supportedMethods: [ 'visa' ] } ];
+    var details = {
+      total: { label: 'Test', amount: { currency: 'USD', value: '5.00' } }
+    };
+    try {
+      new PaymentRequest(supportedInstruments, details);
+    } catch (e) {
+      assert_unreached();
+    }
+  }, header + ' allows the top-level document.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default);
+  }, header + ' allows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, cross_origin_src,
+        expect_feature_available_default);
+  }, header + ' allows cross-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true allows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_available_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true allows cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..5517dd3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: {"payment": ["*"]}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-default-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-default-feature-policy.https.sub.html
new file mode 100644
index 0000000..ab9c8ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-default-feature-policy.https.sub.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  'use strict';
+  var same_origin_src = '/feature-policy/resources/feature-policy-payment.html';
+  var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+    same_origin_src;
+  var header = 'Default "payment" feature policy ["self"]';
+
+  test(() => {
+    var supportedInstruments = [ { supportedMethods: [ 'visa' ] } ];
+    var details = {
+      total: { label: 'Test', amount: { currency: 'USD', value: '5.00' } }
+    };
+    try {
+      new PaymentRequest(supportedInstruments, details);
+    } catch (e) {
+      assert_unreached();
+    }
+  }, header + ' allows the top-level document.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default);
+  }, header + ' allows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, cross_origin_src,
+        expect_feature_unavailable_default);
+  }, header + ' disallows cross-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_available_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true allows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_available_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true allows cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..7379a5cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  'use strict';
+  var same_origin_src = '/feature-policy/resources/feature-policy-payment.html';
+  var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+    same_origin_src;
+  var header = 'Feature-Policy header {"payment" : []}';
+
+  test(() => {
+    var supportedInstruments = [ { supportedMethods: [ 'visa' ] } ];
+    var details = {
+      total: { label: 'Test', amount: { currency: 'USD', value: '5.00' } }
+    };
+    assert_throws('SecurityError', () => {
+      new PaymentRequest(supportedInstruments, details);
+    });
+  }, header + ' disallows the top-level document.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, same_origin_src,
+        expect_feature_unavailable_default);
+  }, header + ' disallows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability('PaymentRequest()', t, cross_origin_src,
+        expect_feature_unavailable_default,);
+  }, header + ' disallows cross-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, same_origin_src,
+        expect_feature_unavailable_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true disallows same-origin iframes.');
+
+  async_test(t => {
+    test_feature_availability(
+        'PaymentRequest()', t, cross_origin_src,
+        expect_feature_unavailable_default, undefined, 'allowpaymentrequest');
+  }, header + ' allowpaymentrequest=true disallows cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..8f8b4824
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: {"payment": []}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html
deleted file mode 100644
index f1e3bb5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/check-availability.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<script>
-'use strict';
-
-Promise.resolve().then(() => navigator.usb.getDevices()).then(devices => {
-  window.parent.postMessage('#OK', '*');
-}, error => {
-  window.parent.postMessage('#' + error.name, '*');
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js b/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js
deleted file mode 100644
index 243242ee..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/resources/featurepolicytest.js
+++ /dev/null
@@ -1,14 +0,0 @@
-function assert_usb_available_in_iframe(test, origin, expected) {
-  let frame = document.createElement('iframe');
-  frame.src = origin + '/webusb/resources/check-availability.html';
-
-  window.addEventListener('message', test.step_func(evt => {
-    if (evt.source == frame.contentWindow) {
-      assert_equals(evt.data, expected);
-      document.body.removeChild(frame);
-      test.done();
-    }
-  }));
-
-  document.body.appendChild(frame);
-}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000..0b53f09f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/feature-policy/resources/featurepolicy.js></script>
+<script>
+'use strict';
+var relative_path = '/feature-policy/resources/feature-policy-usb.html';
+var base_src = '/feature-policy/resources/redirect-on-load.html#';
+var same_origin_src = base_src + relative_path;
+var cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+  relative_path;
+var header = 'Feature-Policy allow="usb"';
+
+async_test(t => {
+  test_feature_availability(
+      'usb.getDevices()', t, same_origin_src,
+      expect_feature_available_default, 'usb');
+}, header + ' allows same-origin relocation.');
+
+async_test(t => {
+  test_feature_availability(
+      'usb.getDevices()', t, cross_origin_src,
+      expect_feature_unavailable_default, 'usb');
+}, header + ' disallows cross-origin relocation.');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html
index 302e7f4..f62135c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html
@@ -2,23 +2,25 @@
 <body>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
+<script src=/feature-policy/resources/featurepolicy.js></script>
 <script>
 'use strict';
+var same_origin_src = '/feature-policy/resources/feature-policy-usb.html';
+var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+  same_origin_src;
+var feature_name = 'Feature policy "usb"';
+var header = 'allow="usb" attribute';
 
 async_test(t => {
-  let frame = document.createElement('iframe');
-  frame.src = 'https://{{domains[www]}}:{{ports[https][0]}}/webusb/resources/check-availability.html';
-  frame.allow = 'usb';
+  test_feature_availability(
+      'usb.getDevices()', t, same_origin_src,
+      expect_feature_available_default, 'usb');
+}, feature_name + ' can be enabled in same-origin iframe using ' + header);
 
-  window.addEventListener('message', t.step_func(evt => {
-    if (evt.source == frame.contentWindow) {
-      assert_equals(evt.data, '#OK');
-      document.body.removeChild(frame);
-      t.done();
-    }
-  }));
-
-  document.body.appendChild(frame);
-}, 'Feature policy "usb" can be enabled in cross-origin iframes using "allowed" attribute.');
+async_test(t => {
+  test_feature_availability(
+      'usb.getDevices()', t, cross_origin_src,
+      expect_feature_available_default, 'usb');
+}, feature_name + ' can be enabled in cross-origin iframe using ' + header);
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html
index 288a3ac..f9af550 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html
@@ -2,20 +2,26 @@
 <body>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=resources/featurepolicytest.js></script>
+<script src=/feature-policy/resources/featurepolicy.js></script>
 <script>
 'use strict';
+var same_origin_src = '/feature-policy/resources/feature-policy-usb.html';
+var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+  same_origin_src;
+var header = 'Feature-Policy header {"usb" : ["*"]}';
 
 promise_test(
     () => navigator.usb.getDevices(),
-    'Feature-Policy header {"usb": ["*"]} allows the top-level document.');
+    header + ' allows the top-level document.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, '', '#OK');
-}, 'Feature-Policy header {"usb": ["*"]} allows same-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, same_origin_src,
+      expect_feature_available_default);
+}, header + ' allows same-origin iframes.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#OK');
-}, 'Feature-Policy header {"usb": ["*"]} allows cross-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, cross_origin_src,
+      expect_feature_available_default);
+}, header + ' allows cross-origin iframes.');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html
index 1579815..34dda528 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-default-feature-policy.https.sub.html
@@ -2,20 +2,26 @@
 <body>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=resources/featurepolicytest.js></script>
+<script src=/feature-policy/resources/featurepolicy.js></script>
 <script>
 'use strict';
+var same_origin_src = '/feature-policy/resources/feature-policy-usb.html';
+var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+  same_origin_src;
+var header = 'Default "usb" feature policy ["self"]';
 
 promise_test(
     () => navigator.usb.getDevices(),
-    'Default "usb" feature policy ["self"] allows the top-level document.');
+    header + ' allows the top-level document.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, '', '#OK');
-}, 'Default "usb" feature policy ["self"] allows same-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, same_origin_src,
+      expect_feature_available_default);
+}, header + ' allows same-origin iframes.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#SecurityError');
-}, 'Default "usb" feature policy ["self"] disallows cross-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, cross_origin_src,
+      expect_feature_unavailable_default);
+}, header + ' disallows cross-origin iframes.');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html
index b1e555c..f090fff 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/usb-disabled-by-feature-policy.https.sub.html
@@ -2,9 +2,13 @@
 <body>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=resources/featurepolicytest.js></script>
+<script src=/feature-policy/resources/featurepolicy.js></script>
 <script>
 'use strict';
+var same_origin_src = '/feature-policy/resources/feature-policy-usb.html';
+var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+  same_origin_src;
+var header = 'Feature-Policy header {"usb" : []}';
 
 promise_test(() => {
   return navigator.usb.getDevices().then(() => {
@@ -12,14 +16,16 @@
   }, error => {
     assert_equals(error.name, 'SecurityError');
   });
-}, 'Feature-Policy header {"usb": []} disallows the top-level document.');
+}, header + ' disallows the top-level document.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, '', '#SecurityError');
-}, 'Feature-Policy header {"usb": []} disallows same-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, same_origin_src,
+      expect_feature_unavailable_default);
+}, header + ' disallows same-origin iframes.');
 
 async_test(t => {
-  assert_usb_available_in_iframe(t, 'https://{{domains[www]}}:{{ports[https][0]}}', '#SecurityError');
-}, 'Feature-Policy header {"usb": []} disallows cross-origin iframes.');
+  test_feature_availability('usb.getDevices()', t, cross_origin_src,
+      expect_feature_unavailable_default);
+}, header + ' disallows cross-origin iframes.');
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillPath-gradient-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillPath-gradient-shadow.html
index 842509f..2b9c881 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillPath-gradient-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillPath-gradient-shadow.html
@@ -45,42 +45,37 @@
 ctx.restore();
 ctx.fillStyle = 'black';
 
-function testPixelShadow(pixel, reference, alphaApprox) {
-    var testPassed = true;
+function testPixelShadow(pixel, reference, rgbApprox, alphaApprox) {
     for(i = 0; i < 3; i++)
-        if(pixel[i] != reference[i]) {
-            testPassed = false;
-            break;
-        }
-    assert_true(testPassed);
+        assert_approx_equals(pixel[i], reference[i], rgbApprox);
     assert_approx_equals(pixel[3], reference[3], alphaApprox);
 }
 
 testScenarios =
         [
-            ['TestAlphaShadow 1', ctx.getImageData(400, 150, 1, 1).data, [ 0, 0, 0, 0, 0], 0],
-            ['TestAlphaShadow 2', ctx.getImageData(400, 75, 1, 1).data, [ 255,  0, 0, 64], 15],
-            ['TestAlphaShadow 3', ctx.getImageData(400, 225, 1, 1).data, [ 255, 0, 0, 64], 15],
-            ['TestAlphaShadow 4', ctx.getImageData(325, 150, 1, 1).data, [ 255, 0, 0, 64], 15],
-            ['TestAlphaShadow 5', ctx.getImageData(475, 150, 1, 1).data, [ 255, 0, 0, 64], 15],
+            ['TestAlphaShadow 1', ctx.getImageData(400, 150, 1, 1).data, [ 0, 0, 0, 0, 0], 0, 0],
+            ['TestAlphaShadow 2', ctx.getImageData(400, 75, 1, 1).data, [ 255,  0, 0, 64], 4, 15],
+            ['TestAlphaShadow 3', ctx.getImageData(400, 225, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
+            ['TestAlphaShadow 4', ctx.getImageData(325, 150, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
+            ['TestAlphaShadow 5', ctx.getImageData(475, 150, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
 
-            ['TestBlurryShadow 1', ctx.getImageData(400, 400, 1, 1).data, [ 0, 0, 0, 0, 0], 0],
-            ['TestBlurryShadow 2', ctx.getImageData(400, 300, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestBlurryShadow 3', ctx.getImageData(400, 500, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestBlurryShadow 4', ctx.getImageData(300, 400, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestBlurryShadow 5', ctx.getImageData(500, 400, 1, 1).data, [ 255, 0, 0, 31], 15],
+            ['TestBlurryShadow 1', ctx.getImageData(400, 400, 1, 1).data, [ 0, 0, 0, 0, 0], 0, 0],
+            ['TestBlurryShadow 2', ctx.getImageData(400, 300, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestBlurryShadow 3', ctx.getImageData(400, 500, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestBlurryShadow 4', ctx.getImageData(300, 400, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestBlurryShadow 5', ctx.getImageData(500, 400, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
 
-            ['TestRotatedAlphaShadow 1', ctx.getImageData(400, 650, 1, 1).data, [ 0, 0, 0, 0, 0], 0],
-            ['TestRotatedAlphaShadow 2', ctx.getImageData(400, 575, 1, 1).data, [ 255, 0, 0, 64], 15],
-            ['TestRotatedAlphaShadow 3', ctx.getImageData(400, 725, 1, 1).data, [ 255, 0, 0, 64], 15],
-            ['TestRotatedAlphaShadow 4', ctx.getImageData(325, 650, 1, 1).data, [ 255, 0, 0, 64], 15],
-            ['TestRotatedAlphaShadow 5', ctx.getImageData(475, 650, 1, 1).data, [ 255, 0, 0, 64], 15],
+            ['TestRotatedAlphaShadow 1', ctx.getImageData(400, 650, 1, 1).data, [ 0, 0, 0, 0, 0], 0, 0],
+            ['TestRotatedAlphaShadow 2', ctx.getImageData(400, 575, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
+            ['TestRotatedAlphaShadow 3', ctx.getImageData(400, 725, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
+            ['TestRotatedAlphaShadow 4', ctx.getImageData(325, 650, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
+            ['TestRotatedAlphaShadow 5', ctx.getImageData(475, 650, 1, 1).data, [ 255, 0, 0, 64], 4, 15],
 
-            ['TestRotatedBlurryShadow 1', ctx.getImageData(400, 900, 1, 1).data, [ 0, 0, 0, 0, 0], 0],
-            ['TestRotatedBlurryShadow 2', ctx.getImageData(400, 800, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestRotatedBlurryShadow 3', ctx.getImageData(400, 1000, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestRotatedBlurryShadow 4', ctx.getImageData(300, 900, 1, 1).data, [ 255, 0, 0, 31], 15],
-            ['TestRotatedBlurryShadow 5', ctx.getImageData(500, 900, 1, 1).data, [ 255, 0, 0, 31], 15],    
+            ['TestRotatedBlurryShadow 1', ctx.getImageData(400, 900, 1, 1).data, [ 0, 0, 0, 0, 0], 0, 0],
+            ['TestRotatedBlurryShadow 2', ctx.getImageData(400, 800, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestRotatedBlurryShadow 3', ctx.getImageData(400, 1000, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestRotatedBlurryShadow 4', ctx.getImageData(300, 900, 1, 1).data, [ 255, 0, 0, 31], 4, 15],
+            ['TestRotatedBlurryShadow 5', ctx.getImageData(500, 900, 1, 1).data, [ 255, 0, 0, 31], 4, 15],    
         ];
 
 generate_tests(testPixelShadow, testScenarios);
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow-expected.txt
deleted file mode 100644
index 98142587..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = 4 duplicate test names: "testBlurryShadow 1", "testBlurryShadow 2", "testBlurryShadow 3", "testBlurryShadow 4"
-PASS testSolidShadow 1 
-PASS testSolidShadow 2 
-PASS testSolidShadow 3 
-PASS testSolidShadow 4 
-PASS testSolidAlphaShadow 1 
-PASS testSolidAlphaShadow 2 
-PASS testSolidAlphaShadow 3 
-PASS testSolidAlphaShadow 4 
-PASS testBlurryShadow 1 
-PASS testBlurryShadow 2 
-PASS testBlurryShadow 3 
-PASS testBlurryShadow 4 
-PASS testBlurryShadow 1 
-PASS testBlurryShadow 2 
-PASS testBlurryShadow 3 
-PASS testBlurryShadow 4 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow.html
index c29d13d..abbe201 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-fillRect-gradient-shadow.html
@@ -3,15 +3,10 @@
 <body>
 <script>
 
-var alphaApprox = 0, alphaMax = 0;
+var rgbApprox = 0, alphaApprox = 0, alphaMax = 0;
 function testPixelShadow(pixel, reference) {
-  var testPassed = true;
   for(i = 0; i < 3; i++)
-    if(pixel[i] != reference[i]) {
-        testPassed = false;
-        break;
-    }
-  assert_true(testPassed);
+    assert_approx_equals(pixel[i], reference[i], rgbApprox);
   if(alphaMax != 0)
     assert_true(pixel[3] < alphaMax);
   else
@@ -44,6 +39,7 @@
 ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
 ctx.fillRect(50, 500, 100, 100);
 
+// rgbApprox = 1
 testSolidShadow = 
     [
         ['testSolidShadow 1', ctx.getImageData(250, 50, 1, 1).data, [255, 0, 0, 255]],
@@ -52,7 +48,7 @@
         ['testSolidShadow 4', ctx.getImageData(349, 149, 1, 1).data, [255, 0, 0, 255]],
     ];
 
-// alphaApprox = 5
+// rgbApprox = 3, alphaApprox = 5
 testSolidAlphaShadow = 
     [
         ['testSolidAlphaShadow 1', ctx.getImageData(250, 200, 1, 1).data, [255, 0, 0, 76]],
@@ -73,17 +69,23 @@
 // alpha < 10
 testBlurryAlphaShadow = 
     [
-        ['testBlurryShadow 1', ctx.getImageData(248, 498, 1, 1).data, [255, 0, 0, 0]],
-        ['testBlurryShadow 2', ctx.getImageData(248, 601, 1, 1).data, [255, 0, 0, 0]],
-        ['testBlurryShadow 3', ctx.getImageData(351, 498, 1, 1).data, [255, 0, 0, 0]],
-        ['testBlurryShadow 4', ctx.getImageData(351, 601, 1, 1).data, [255, 0, 0, 0]],
+        ['testBlurryAlphaShadow 1', ctx.getImageData(248, 498, 1, 1).data, [255, 0, 0, 0]],
+        ['testBlurryAlphaShadow 2', ctx.getImageData(248, 601, 1, 1).data, [255, 0, 0, 0]],
+        ['testBlurryAlphaShadow 3', ctx.getImageData(351, 498, 1, 1).data, [255, 0, 0, 0]],
+        ['testBlurryAlphaShadow 4', ctx.getImageData(351, 601, 1, 1).data, [255, 0, 0, 0]],
     ];
 
+rgbApprox = 1;
 generate_tests(testPixelShadow, testSolidShadow);
+
+rgbApprox = 3;
 alphaApprox = 5;
 generate_tests(testPixelShadow, testSolidAlphaShadow);
+
+rgbApprox = 0;
 alphaMax = 25;
 generate_tests(testPixelShadow, testBlurryShadow);
+
 alphaMax = 10;
 generate_tests(testPixelShadow, testBlurryAlphaShadow);
 
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow.html
index 2517bfb..0ad9cc4f 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokePath-gradient-shadow.html
@@ -53,70 +53,69 @@
 var imageData, data;
 ctx.fillStyle = 'black';
 
-function testPixelShadow(x, y, color)
+function testPixelShadow(x, y, color, rgbTolerance, alphaTolerance)
 {
-    if (color.length == 4) {
-        assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
-    } else {    // we expect to have [r, g, b, a, alphaApprox]
-        var data = ctx.getImageData(x, y, 1, 1).data;
-        assert_array_equals(data.slice(0,3), color.slice(0,3));
-        assert_approx_equals(data[3], color[3], color[4]);
-    }
+    var data = ctx.getImageData(x, y, 1, 1).data;
+    for (i = 0; i < 3; i++)
+        assert_approx_equals(data[i], color[i], rgbTolerance);
+    assert_approx_equals(data[3], color[3], alphaTolerance);
+
     // Plot test point.
     ctx.fillRect(x, y, 3, 3);
 }
 
+var rgbTolerance = 4;
 var alphaTolerance = 15;
 var testScenarios = [
-    ['Verify alpha shadow 1' ,400, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 2' ,400, 75,  [0, 0, 0, 0]],
-    ['Verify alpha shadow 3' ,400, 225, [0, 0, 0, 0]],
-    ['Verify alpha shadow 4' ,325, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 5' ,475, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 6' ,400,  50, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 7' ,500, 150, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 8' ,400, 250, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 9' ,300, 150, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 10' ,400, 25,  [0, 0, 0, 0]],
-    ['Verify alpha shadow 11' ,525, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 12' ,400, 275, [0, 0, 0, 0]],
-    ['Verify blurry shadow 1' ,275, 150, [0, 0, 0, 0]],
-    ['Verify blurry shadow 2' ,400, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 3' ,400, 325, [0, 0, 0, 0]],
-    ['Verify blurry shadow 4' ,475, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 5' ,400, 475, [0, 0, 0, 0]],
-    ['Verify blurry shadow 6' ,325, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 7' ,400, 300, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 8' ,400, 500, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 9' ,300, 400, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 10' ,500, 400, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 11' ,525, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 12' ,275, 400, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 1' ,400, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 2' ,400, 575, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 3' ,400, 725, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 4' ,325, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 5' ,475, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 6' ,400, 550, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 7' ,500, 650, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 8' ,400, 750, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 9' ,300, 650, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 10' ,400, 525, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 11' ,525, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 12' ,400, 775, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 13' ,275, 650, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 1' ,400, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 2' ,400, 825, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 3' ,475, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 4' ,400, 975, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 5' ,325, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 6' ,400, 800,  [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 7' ,400, 1000, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 8' ,300, 900,  [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 9' ,500, 900,  [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 10' ,525, 900,  [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 11' ,275, 900,  [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 12' ,400, 1025, [0, 0, 0, 0]],
+    ['Verify alpha shadow 1' ,400, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 2' ,400, 75,  [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 3' ,400, 225, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 4' ,325, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 5' ,475, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 6' ,400,  50, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 7' ,500, 150, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 8' ,400, 250, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 9' ,300, 150, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 10' ,400, 25,  [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 11' ,525, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 12' ,400, 275, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 1' ,275, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 2' ,400, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 3' ,400, 325, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 4' ,475, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 5' ,400, 475, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 6' ,325, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 7' ,400, 300, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 8' ,400, 500, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 9' ,300, 400, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 10' ,500, 400, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 11' ,525, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 12' ,275, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 1' ,400, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 2' ,400, 575, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 3' ,400, 725, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 4' ,325, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 5' ,475, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 6' ,400, 550, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 7' ,500, 650, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 8' ,400, 750, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 9' ,300, 650, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 10' ,400, 525, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 11' ,525, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 12' ,400, 775, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 13' ,275, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 1' ,400, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 2' ,400, 825, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 3' ,475, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 4' ,400, 975, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 5' ,325, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 6' ,400, 800,  [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 7' ,400, 1000, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 8' ,300, 900,  [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 9' ,500, 900,  [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 10' ,525, 900,  [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 11' ,275, 900,  [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 12' ,400, 1025, [0, 0, 0, 0], 0, 0],
 ];
 
 generate_tests(testPixelShadow, testScenarios);
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow.html
index 489149e7..7e2701d 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-strokeRect-gradient-shadow.html
@@ -45,73 +45,72 @@
 var imageData, data;
 ctx.fillStyle = 'black';
 
-function testPixelAlphaShadow(x, y, color)
+function testPixelAlphaShadow(x, y, color, rgbTolerance, alphaTolerance)
 {
-    if (color.length == 4) {
-        assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
-    } else {    // we expect to have [r, g, b, a, alphaApprox]
-        var data = ctx.getImageData(x, y, 1, 1).data;
-        assert_array_equals(data.slice(0,3), color.slice(0,3));
-        assert_approx_equals(data[3], color[3], color[4]);
-    }
+    var data = ctx.getImageData(x, y, 1, 1).data;
+    for (i = 0; i < 3; i++)
+        assert_approx_equals(data[i], color[i], rgbTolerance);
+    assert_approx_equals(data[3], color[3], alphaTolerance);
+
     // Plot test point.
     ctx.fillRect(x, y, 3, 3);
 }
 
+var rgbTolerance = 4;
 var alphaTolerance = 15;
 var testScenarios = [
-    ['Verify alpha shadow 1' , 400, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 2' , 400, 75, [0, 0, 0, 0]],
-    ['Verify alpha shadow 3' , 400, 225, [0, 0, 0, 0]],
-    ['Verify alpha shadow 4' , 325, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 5' , 475, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 6' , 400, 50, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 7' , 500, 150, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 8' , 400, 250, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 9' , 300, 150, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify alpha shadow 10' , 400, 25, [0, 0, 0, 0]],
-    ['Verify alpha shadow 11' , 525, 150, [0, 0, 0, 0]],
-    ['Verify alpha shadow 12' , 400, 275, [0, 0, 0, 0]],
-    ['Verify alpha shadow 13' , 275, 150, [0, 0, 0, 0]],
+    ['Verify alpha shadow 1' , 400, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 2' , 400, 75, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 3' , 400, 225, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 4' , 325, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 5' , 475, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 6' , 400, 50, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 7' , 500, 150, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 8' , 400, 250, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 9' , 300, 150, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify alpha shadow 10' , 400, 25, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 11' , 525, 150, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 12' , 400, 275, [0, 0, 0, 0], 0, 0],
+    ['Verify alpha shadow 13' , 275, 150, [0, 0, 0, 0], 0, 0],
 
-    ['Verify blurry shadow 1' , 400, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 2' , 400, 325, [0, 0, 0, 0]],
-    ['Verify blurry shadow 3' , 475, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 4' , 400, 475, [0, 0, 0, 0]],
-    ['Verify blurry shadow 5' , 325, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 6' , 400, 300, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 7' , 400, 500, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 8' , 300, 400, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 9' , 500, 400, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify blurry shadow 10' , 525, 400, [0, 0, 0, 0]],
-    ['Verify blurry shadow 11' , 275, 400, [0, 0, 0, 0]],
+    ['Verify blurry shadow 1' , 400, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 2' , 400, 325, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 3' , 475, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 4' , 400, 475, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 5' , 325, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 6' , 400, 300, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 7' , 400, 500, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 8' , 300, 400, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 9' , 500, 400, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify blurry shadow 10' , 525, 400, [0, 0, 0, 0], 0, 0],
+    ['Verify blurry shadow 11' , 275, 400, [0, 0, 0, 0], 0, 0],
 
-    ['Verify rotated alpha shadow 1' , 400, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 2' , 400, 575, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 3' , 400, 725, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 4' , 325, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 5' , 475, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 6' , 400, 550, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 7' , 500, 650, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 8' , 400, 750, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 9' , 300, 650, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated alpha shadow 10' , 400, 525, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 11' , 525, 650, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 12' , 400, 775, [0, 0, 0, 0]],
-    ['Verify rotated alpha shadow 13' , 275, 650, [0, 0, 0, 0]],
+    ['Verify rotated alpha shadow 1' , 400, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 2' , 400, 575, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 3' , 400, 725, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 4' , 325, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 5' , 475, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 6' , 400, 550, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 7' , 500, 650, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 8' , 400, 750, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 9' , 300, 650, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated alpha shadow 10' , 400, 525, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 11' , 525, 650, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 12' , 400, 775, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated alpha shadow 13' , 275, 650, [0, 0, 0, 0], 0, 0],
 
-    ['Verify rotated blurry shadow 1' , 400, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 2' , 400, 825, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 3' , 475, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 4' , 400, 975, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 5' , 325, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 6' , 400, 800, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 7' , 400, 1000, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 8' , 300, 900, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 9' , 500, 900, [255, 0, 0, 64, alphaTolerance]],
-    ['Verify rotated blurry shadow 10' , 525, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 11' , 275, 900, [0, 0, 0, 0]],
-    ['Verify rotated blurry shadow 12' , 400, 1025, [0, 0, 0, 0]],
+    ['Verify rotated blurry shadow 1' , 400, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 2' , 400, 825, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 3' , 475, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 4' , 400, 975, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 5' , 325, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 6' , 400, 800, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 7' , 400, 1000, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 8' , 300, 900, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 9' , 500, 900, [255, 0, 0, 64], rgbTolerance, alphaTolerance],
+    ['Verify rotated blurry shadow 10' , 525, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 11' , 275, 900, [0, 0, 0, 0], 0, 0],
+    ['Verify rotated blurry shadow 12' , 400, 1025, [0, 0, 0, 0], 0, 0],
 ];
 
 generate_tests(testPixelAlphaShadow, testScenarios);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
index 16f0dd9d..65e27324 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-item-selection-dialog-filtering.js
@@ -25,7 +25,7 @@
 
         var filteredSelectionDialog = new QuickOpen.FilteredListWidget(provider, history);
         filteredSelectionDialog.showAsDialog();
-        var promise = TestRunner.addSniffer(filteredSelectionDialog, "_itemsFilteredForTest").then(accept);
+        var promise = TestRunner.addSnifferPromise(filteredSelectionDialog, "_itemsFilteredForTest").then(accept);
         filteredSelectionDialog.setQuery(query);
         filteredSelectionDialog._updateAfterItemsLoaded();
         return promise;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-list-widget-providers.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-list-widget-providers.js
index 3630f19..14ed6d43 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-list-widget-providers.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/filtered-list-widget-providers.js
@@ -36,7 +36,7 @@
   ]);
 
   function setProvider(provider) {
-    var promise = TestRunner.addSniffer(filteredListWidget, "_itemsFilteredForTest").then(dump);
+    var promise = TestRunner.addSnifferPromise(filteredListWidget, "_itemsFilteredForTest").then(dump);
     filteredListWidget.setProvider(provider);
     return promise;
   }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/tabbed-pane.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/tabbed-pane.js
index 9782aba..204ff60ef 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/tabbed-pane.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/tabbed-pane.js
@@ -11,7 +11,7 @@
 
 var tabbedPane = new UI.TabbedPane();
 tabbedPane.show(UI.inspectorView.element);
-TestRunner.addSniffer(tabbedPane, '_innerUpdateTabElements').then(tabsAdded);
+TestRunner.addSnifferPromise(tabbedPane, '_innerUpdateTabElements').then(tabsAdded);
 for (var i = 0; i < 10; i++)
   tabbedPane.appendTab(i.toString(), 'Tab ' + i, new FocusableWidget('Widget ' + i));
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt.js b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt.js
index 292eadc..5401792f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-unit/text-prompt.js
@@ -7,7 +7,7 @@
 UI.inspectorView.element.appendChild(div);
 prompt.attachAndStartEditing(div);
 prompt.setText("hey");
-TestRunner.addSniffer(prompt, "_completionsReady").then(step2);
+TestRunner.addSnifferPromise(prompt, "_completionsReady").then(step2);
 prompt.complete();
 function step2() {
     TestRunner.addResult("Text:" + prompt.text());
@@ -16,7 +16,7 @@
     TestRunner.addResult("Test with inexact match:");
     prompt.clearAutocomplete();
     prompt.setText("inexactmatch");
-    TestRunner.addSniffer(prompt, "_completionsReady").then(step3);
+    TestRunner.addSnifferPromise(prompt, "_completionsReady").then(step3);
     prompt.complete();
 }
 function step3() {
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear-expected.txt
new file mode 100644
index 0000000..6431775
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear-expected.txt
@@ -0,0 +1,8 @@
+Tests that console is cleared upon requestClearMessages call.
+
+=== Before clear ===
+VM:3 one
+VM:4 two
+VM:5 three
+=== After clear ===
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear.js b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear.js
new file mode 100644
index 0000000..d132176
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/console-clear.js
@@ -0,0 +1,29 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  TestRunner.addResult("Tests that console is cleared upon requestClearMessages call.\n");
+
+  await TestRunner.loadPanel("console");
+  await TestRunner.loadModule("console_test_runner");
+
+  function log() {
+    // Fill console.
+    console.log("one");
+    console.log("two");
+    console.log("three");
+  }
+
+  await TestRunner.evaluateInPagePromise(`(${log.toString()})()`);
+  TestRunner.addResult("=== Before clear ===");
+  ConsoleTestRunner.dumpConsoleMessages();
+
+  Console.ConsoleView.clearConsole();
+  TestRunner.deprecatedRunAfterPendingDispatches(callback);
+  function callback() {
+    TestRunner.addResult("=== After clear ===");
+    ConsoleTestRunner.dumpConsoleMessages();
+    TestRunner.completeTest();
+  }
+})();
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test-expected.txt
new file mode 100644
index 0000000..1e52e11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test-expected.txt
@@ -0,0 +1,3 @@
+Start test
+Make sure the new test runner works
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test.js
new file mode 100644
index 0000000..e88e1a1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/devtools-js/simple-test.js
@@ -0,0 +1,9 @@
+// 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.
+
+(function() {
+  TestRunner.addResult('Start test');
+  TestRunner.addResult('Make sure the new test runner works');
+  TestRunner.completeTest();
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/download.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/download.html
index 65ea094a..db9e74f2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/download.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/download.html
@@ -18,7 +18,7 @@
 
     function responseReceived(requestId, time, resourceType, response)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/download\.zzz/.exec(request.url())) {
             InspectorTest.addResult("Received response for download.zzz");
             InspectorTest.addResult("SUCCESS");
@@ -28,14 +28,14 @@
 
     function loadingFinished(requestId, finishTime)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/download\.zzz/.exec(request.url()))
             InspectorTest.completeTest();
     }
 
     function loadingFailed(requestId, time, localizedDescription, canceled)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/download\.zzz/.exec(request.url()))
             InspectorTest.completeTest();
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/json-preview.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/json-preview.html
index 412b372d..44660ef7d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/json-preview.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/json-preview.html
@@ -8,7 +8,7 @@
     function createNetworkRequestWithJSONMIMEType(type)
     {
         InspectorTest.addResult("Creating a NetworkRequest with type: " + type);
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), 0, 'http://localhost');
+        var request = new SDK.NetworkRequest(0, 'http://localhost');
         request.mimeType = type;
         request._contentData = Promise.resolve({ error: null, content: '{"number": 42}', encoded: false });
         return request;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html
index df6ec9c..caeaf143 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-choose-preview-view.html
@@ -8,7 +8,7 @@
     function createNetworkRequest(mimeType, content, statusCode)
     {
         InspectorTest.addResult("Creating a NetworkRequest with mimeType: " + mimeType);
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), 0, 'http://localhost');
+        var request = new SDK.NetworkRequest(0, 'http://localhost');
         InspectorTest.addResult("Content: " + content.replace(/\0/g, "**NULL**"));
         request.mimeType = mimeType;
         request._contentData = Promise.resolve({error: null, content: content, encoded: false});
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-datareceived.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-datareceived.html
index 42a0d45..f079027 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-datareceived.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-datareceived.html
@@ -21,7 +21,7 @@
     var encodedBytesReceived = 0;
     function responseReceived(requestId, frameId, loaderId, time, resourceType, response)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/resource\.php/.exec(request.url())) {
             InspectorTest.addResult("Received response.");
             encodedBytesReceived += response.encodedDataLength;
@@ -30,7 +30,7 @@
 
     function loadingFinished(requestId, finishTime, encodedDataLength)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/resource\.php/.exec(request.url())) {
             InspectorTest.assertEquals(encodedBytesReceived, encodedDataLength, "Data length mismatch");
             InspectorTest.addResult("SUCCESS");
@@ -40,7 +40,7 @@
 
     function loadingFailed(requestId, time, localizedDescription, canceled)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/resource\.php/.exec(request.url())) {
             InspectorTest.addResult("Loading failed!");
             InspectorTest.completeTest();
@@ -50,7 +50,7 @@
     function dataReceived(requestId, time, dataLength, encodedDataLength)
     {
         InspectorTest.addSniffer(SDK.NetworkDispatcher.prototype, "dataReceived", dataReceived);
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/resource\.php/.exec(request.url()))
             encodedBytesReceived += encodedDataLength;
     }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-data-received-async-response-type-blob.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-data-received-async-response-type-blob.html
index 4db5357..4511b8d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-data-received-async-response-type-blob.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xhr-data-received-async-response-type-blob.html
@@ -13,7 +13,7 @@
 
     function dataReceived(requestId, time, dataLength, encodedDataLength)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/resource\.php/.exec(request.url())) {
             InspectorTest.addResult("Received data for resource.php");
             InspectorTest.addResult("SUCCESS");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xsl-content.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xsl-content.html
index 4181f7b..ca22e2f5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xsl-content.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-xsl-content.html
@@ -21,7 +21,7 @@
 
     function loadingFinished(requestId)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         request.requestContent().then(contentReceived.bind(this, request));
     }
     function contentReceived(request, content)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/request-name-path.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/request-name-path.html
index 8048eb4..8c2fe06 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/request-name-path.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/request-name-path.html
@@ -12,10 +12,11 @@
     {
         var mainTarget = SDK.targetManager.mainTarget();
         var currentTargetURL = mainTarget.inspectedURL();
+        var dispatcher = InspectorTest.networkManager._dispatcher;
         if (targetUrl)
             mainTarget.setInspectedURL(targetUrl);
         InspectorTest.addResult("Dumping request name and path for url: " + url);
-        var request = new SDK.NetworkRequest(InspectorTest.networkManager, 0, url);
+        var request = dispatcher._createNetworkRequest(0, "", "", url);
         InspectorTest.addResult("    name = " + request.name());
         InspectorTest.addResult("    path = " + request.path());
         InspectorTest.addResult("    targetUrl = " + (targetUrl ? targetUrl : currentTargetURL));
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/waterfall-images.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/waterfall-images.html
index 15432bce..b38b409 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/waterfall-images.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/waterfall-images.html
@@ -237,7 +237,7 @@
   }
 
   function makeRequest(requestData) {
-    var request = new SDK.NetworkRequest(InspectorTest.networkManager, (++requestIds).toString(), requestData.url);
+    var request = new SDK.NetworkRequest((++requestIds).toString(), requestData.url);
     request.setResourceType(requestData.type);
     request.setIssueTime(requestData.issueTime, requestData.wallIssueTime);
     request.timing = requestData.timing;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/x-frame-options-deny.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/x-frame-options-deny.html
index b2eadbcb..0cdad8dc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/x-frame-options-deny.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/x-frame-options-deny.html
@@ -18,7 +18,7 @@
 
     function responseReceived(requestId, time, resourceType, response)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/x-frame-options-deny\.cgi/.exec(request.url())) {
             InspectorTest.addResult("Received response for x-frame-options-deny.cgi");
             InspectorTest.addResult("SUCCESS");
@@ -28,14 +28,14 @@
 
     function loadingFinished(requestId, finishTime)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/x-frame-options-deny\.cgi/.exec(request.url()))
             InspectorTest.completeTest();
     }
 
     function loadingFailed(requestId, time, localizedDescription, canceled)
     {
-        var request = InspectorTest.networkLog.requestForId(InspectorTest.networkManager, requestId);
+        var request = InspectorTest.networkLog.requestByManagerAndId(InspectorTest.networkManager, requestId);
         if (/x-frame-options-deny\.cgi/.exec(request.url())) {
             InspectorTest.addResult("TODO(mkwst): This started failing when we moved XFO to the browser.");
             InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-headers.html b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-headers.html
index 8788e76..d247308 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-headers.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-har-headers.html
@@ -34,7 +34,7 @@
         request._transferSize = 539; // 39 = header size at the end of the day
     }
 
-    var testRequest = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), "testRequest", "http://example.com/inspector-test.js", 1); 
+    var testRequest = new SDK.NetworkRequest("testRequest", "http://example.com/inspector-test.js", 1); 
     setRequestValues(testRequest);
     var headersText = testRequest.requestHeadersText();
     var requestResults = {
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html
index 5c4cf47..057c3dd 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html
index af3304e..5a505d7d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
index 4fdbb573..964a428 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blank-origins-not-shown.html
@@ -5,10 +5,10 @@
 <script>
 function test()
 {
-    var request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
+    var request1 = new SDK.NetworkRequest(0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request1);
 
-    var request2 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAPElEQVR42mNgQAMZGRn/GfABkIIdO3b8x6kQpgAEsCpEVgADKAqxKcBQCCLwARRFIBodYygiyiSCighhAO4e2jskhrm3AAAAAElFTkSuQmCC", "https://foo.test", 0, 0, null);
+    var request2 = new SDK.NetworkRequest(0, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAPElEQVR42mNgQAMZGRn/GfABkIIdO3b8x6kQpgAEsCpEVgADKAqxKcBQCCLwARRFIBodYygiyiSCighhAO4e2jskhrm3AAAAAElFTkSuQmCC", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request2);
 
     InspectorTest.dumpSecurityPanelSidebarOrigins();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html
index 90ff911..3654078 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html
@@ -9,7 +9,7 @@
     var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: true, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.setBlockedReason(Protocol.Network.BlockedReason.MixedContent);
     request.mixedContentType = "blockable";
     InspectorTest.dispatchRequestFinished(request);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
index 4f856cc..375acca 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/failed-request.html
@@ -5,11 +5,11 @@
 <script>
 function test()
 {
-    var request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
+    var request1 = new SDK.NetworkRequest(0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
     request1.setSecurityState(Protocol.Security.SecurityState.Secure);
     InspectorTest.dispatchRequestFinished(request1);
 
-    var request2 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://does-not-resolve.test", "https://does-not-resolve.test", 0, 0, null);
+    var request2 = new SDK.NetworkRequest(0, "https://does-not-resolve.test", "https://does-not-resolve.test", 0, 0, null);
     // Leave the security state unknown.
     InspectorTest.dispatchRequestFinished(request2);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/interstitial-sidebar.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/interstitial-sidebar.html
index fa121cb0..99a1212 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/interstitial-sidebar.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/interstitial-sidebar.html
@@ -6,11 +6,11 @@
 function test()
 {
 
-    var request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/", "https://foo.test", 0, 0, null);
+    var request1 = new SDK.NetworkRequest(0, "https://foo.test/", "https://foo.test", 0, 0, null);
     request1.setSecurityState(Protocol.Security.SecurityState.Secure);
     InspectorTest.dispatchRequestFinished(request1);
 
-    var request2 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://bar.test/foo.jpg", "https://bar.test", 0, 0, null);
+    var request2 = new SDK.NetworkRequest(0, "https://bar.test/foo.jpg", "https://bar.test", 0, 0, null);
     request2.setSecurityState(Protocol.Security.SecurityState.Secure);
     InspectorTest.dispatchRequestFinished(request2);
 
@@ -20,7 +20,7 @@
     // Test that the sidebar is hidden when an interstitial is shown. https://crbug.com/559150
     InspectorTest.mainTarget.model(SDK.ResourceTreeModel).dispatchEventToListeners(SDK.ResourceTreeModel.Events.InterstitialShown);
     // Simulate a request finishing after the interstitial is shown, to make sure that doesn't show up in the sidebar.
-    var request3 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://bar.test/foo.jpg", "https://bar.test", 0, 0, null);
+    var request3 = new SDK.NetworkRequest(0, "https://bar.test/foo.jpg", "https://bar.test", 0, 0, null);
     request3.setSecurityState(Protocol.Security.SecurityState.Unknown);
     InspectorTest.dispatchRequestFinished(request3);
     InspectorTest.addResult("After interstitial is shown:");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/main-origin-assigned-despite-request-missing.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/main-origin-assigned-despite-request-missing.html
index bf22953..c82d58e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/main-origin-assigned-despite-request-missing.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/main-origin-assigned-despite-request-missing.html
@@ -19,13 +19,13 @@
     InspectorTest.addResult("Detected main origin: " + detectedMainOrigin);
 
     // Send subdownload resource requests to other origins.
-    const request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/favicon.ico", page_url, 0, 0, null);
+    const request1 = new SDK.NetworkRequest(0, "https://foo.test/favicon.ico", page_url, 0, 0, null);
     InspectorTest.dispatchRequestFinished(request1);
-    const request2 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://bar.test/bar.css", page_url, 0, 0, null);
+    const request2 = new SDK.NetworkRequest(0, "https://bar.test/bar.css", page_url, 0, 0, null);
     InspectorTest.dispatchRequestFinished(request2);
 
     // Send one request to the Same Origin as the original page to ensure it appears in the group.
-    const request3 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, detectedMainOrigin + "/favicon.ico", page_url, 0, 0, null);
+    const request3 = new SDK.NetworkRequest(0, detectedMainOrigin + "/favicon.ico", page_url, 0, 0, null);
     InspectorTest.dispatchRequestFinished(request3);
     InspectorTest.dumpSecurityPanelSidebarOrigins();
     InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
index 2735a0d..36ef3e3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
@@ -19,11 +19,11 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
 
-    var passive = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var passive = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     passive.mixedContentType = "optionally-blockable";
     InspectorTest.dispatchRequestFinished(passive);
 
-    var active = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var active = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     active.mixedContentType = "blockable";
     InspectorTest.dispatchRequestFinished(active);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html
index e73873a..11c03ff 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
index f12d2b7..1f40be4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
@@ -19,7 +19,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.mixedContentType = "optionally-blockable";
     InspectorTest.dispatchRequestFinished(request);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-view-then-interstitial.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-view-then-interstitial.html
index 186fa7a..70f7efc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-view-then-interstitial.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/origin-view-then-interstitial.html
@@ -5,7 +5,7 @@
 <script>
 function test()
 {
-    var request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/", "https://foo.test", 0, 0, null);
+    var request1 = new SDK.NetworkRequest(0, "https://foo.test/", "https://foo.test", 0, 0, null);
     request1.setSecurityState(Protocol.Security.SecurityState.Secure);
     InspectorTest.dispatchRequestFinished(request1);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html
index f1dbd39..ac26615 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.None, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
index 0df894d..36f61e2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html
index 90980a5..9a1e0cf 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html
@@ -9,7 +9,7 @@
     var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, "Test: Summary Override Text"));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.setBlockedReason(Protocol.Network.BlockedReason.MixedContent);
     request.mixedContentType = "blockable";
     InspectorTest.dispatchRequestFinished(request);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
index 22a52785..7dfd687 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content.html
@@ -9,7 +9,7 @@
     var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.setBlockedReason(Protocol.Network.BlockedReason.MixedContent);
     request.mixedContentType = "blockable";
     InspectorTest.dispatchRequestFinished(request);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-details-updated-with-security-state.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-details-updated-with-security-state.html
index 7abcf2b..29912287 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-details-updated-with-security-state.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-details-updated-with-security-state.html
@@ -6,17 +6,17 @@
 function test()
 {
     // Add a request without security details.
-    const request1 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
+    const request1 = new SDK.NetworkRequest(0, "https://foo.test/foo.jpg", "https://foo.test", 0, 0, null);
     request1.setSecurityState(Protocol.Security.SecurityState.Unknown);
     InspectorTest.dispatchRequestFinished(request1);
 
     // Add an unrelated request.
-    const request2 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://bar.test/bar.jpg", "https://bar.test", 0, 0, null);
+    const request2 = new SDK.NetworkRequest(0, "https://bar.test/bar.jpg", "https://bar.test", 0, 0, null);
     request2.setSecurityState(Protocol.Security.SecurityState.Unknown);
     InspectorTest.dispatchRequestFinished(request2);
 
     // Add a request to the first origin, this time including security details.
-    const request3 = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "https://foo.test/foo2.jpg", "https://foo.test", 0, 0, null);
+    const request3 = new SDK.NetworkRequest(0, "https://foo.test/foo2.jpg", "https://foo.test", 0, 0, null);
     request3.setSecurityState(Protocol.Security.SecurityState.Secure);
     let securityDetails = {};
     securityDetails.protocol = "TLS 1.2";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
index be304c9..f0deac5d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
@@ -33,7 +33,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, explanations, insecureContentStatus, null));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html
index b48536475..ef78e48 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html
@@ -10,7 +10,7 @@
 
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, "Test: Summary Override Text"));
 
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://foo.test", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     InspectorTest.dumpDeepInnerHTML(Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-summary-text")[0]);
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-unknown-resource.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-unknown-resource.html
index e667fd3..ca972bb0 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-unknown-resource.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-unknown-resource.html
@@ -5,7 +5,7 @@
 <script>
 function test()
 {
-    var request = new SDK.NetworkRequest(InspectorTest.mainTarget, 0, "http://unknown", "https://foo.test", 0, 0, null);
+    var request = new SDK.NetworkRequest(0, "http://unknown", "https://foo.test", 0, 0, null);
     InspectorTest.dispatchRequestFinished(request);
 
     InspectorTest.dumpSecurityPanelSidebarOrigins();
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/webshare-on-insecure-origin.html b/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/webshare-on-insecure-origin.html
index cf813cd..7265711 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/webshare-on-insecure-origin.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/powerfulFeatureRestrictions/webshare-on-insecure-origin.html
@@ -2,15 +2,12 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/get-host-info.js"></script>
-<script src="/js-test-resources/mojo-helpers.js"></script>
-<script src="/webshare/js-test-resources/mock-share-service.js"></script>
 <script>
 if (window.location.origin != get_host_info().UNAUTHENTICATED_ORIGIN) {
   window.location = get_host_info().UNAUTHENTICATED_ORIGIN + window.location.pathname;
 } else {
-  share_test((t, mock) => {
-    return callWithKeyDown(() => promise_rejects(
-        t, 'SecurityError', navigator.share({})));
-  }, "Requires secure context");
+  test(() => {
+    assert_false('share' in navigator, 'navigator has attribute \'share\'.');
+  }, 'navigator.share should be undefined in non-secure context');
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/inspector/curl-command.html b/third_party/WebKit/LayoutTests/inspector/curl-command.html
index ea10e6ed..445c1ab 100644
--- a/third_party/WebKit/LayoutTests/inspector/curl-command.html
+++ b/third_party/WebKit/LayoutTests/inspector/curl-command.html
@@ -9,7 +9,7 @@
 
     function newRequest(headers, data, opt_url)
     {
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), 0, opt_url || 'http://example.org/path', 0, 0, 0);
+        var request = new SDK.NetworkRequest(0, opt_url || 'http://example.org/path', 0, 0, 0);
         request.requestMethod = data ? "POST" : "GET";
         var headerList = [];
         if (headers) {
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-cookies-pane.html b/third_party/WebKit/LayoutTests/inspector/network/network-cookies-pane.html
index ac8a966..e50f25ef9 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-cookies-pane.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-cookies-pane.html
@@ -9,7 +9,7 @@
         var target = panel._networkLogView;
         var types = Common.resourceTypes;
 
-        var requestFoo = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), "", "", "", "", "");
+        var requestFoo = new SDK.NetworkRequest("", "", "", "", "");
         requestFoo.setResourceType(types.XHR);
         requestFoo.setRequestId("foo");
         requestFoo.setRequestHeaders([{name: 'Cookie', value: 'mycookie=myvalue;myother=myvalue2'}]);
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-filter-http-requests.html b/third_party/WebKit/LayoutTests/inspector/network/network-filter-http-requests.html
index 8caa48a..d0cdfcb 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-filter-http-requests.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-filter-http-requests.html
@@ -6,7 +6,7 @@
 function test() {
     function checkURL(url)
     {
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), url, url, "", "", "");
+        var request = new SDK.NetworkRequest(url, url, "", "", "");
         var result = Network.NetworkLogView.HTTPRequestsFilter(request);
         InspectorTest.addResult((result ? "" : "Non-") + "HTTP request URL: " + url);
     }
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-filter-updated-requests.html b/third_party/WebKit/LayoutTests/inspector/network/network-filter-updated-requests.html
index 15dd824..c54830b5 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-filter-updated-requests.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-filter-updated-requests.html
@@ -11,12 +11,12 @@
     target._resourceCategoryFilterUI._toggleTypeFilter(categoryName, false);
     InspectorTest.addResult("Clicked '" + categoryName + "' button.");
 
-    var requestFoo = new SDK.NetworkRequest(InspectorTest.networkManager, "", "", "", "", "");
+    var requestFoo = new SDK.NetworkRequest("", "", "", "", "");
     requestFoo.setResourceType(types.Script);
     requestFoo.setRequestId("foo");
     InspectorTest.networkManager._dispatcher._startNetworkRequest(requestFoo);
 
-    var requestBar = new SDK.NetworkRequest(InspectorTest.networkManager, "", "", "", "", "");
+    var requestBar = new SDK.NetworkRequest("", "", "", "", "");
     requestBar.setResourceType(types.Script);
     requestBar.setRequestId("bar");
     InspectorTest.networkManager._dispatcher._startNetworkRequest(requestBar);
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-request-parse-query-params.html b/third_party/WebKit/LayoutTests/inspector/network/network-request-parse-query-params.html
index eaee76b..8c580e2 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-request-parse-query-params.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-request-parse-query-params.html
@@ -7,7 +7,7 @@
     function checkQuery(query)
     {
         var url = "http://webkit.org?" + query;
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), url, url, "", "", "");
+        var request = new SDK.NetworkRequest(url, url, "", "", "");
         InspectorTest.addResult("Query: " + request.queryString());
         var params = request.queryParameters;
         InspectorTest.addResult("Parameters: ");
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-request-query-string.html b/third_party/WebKit/LayoutTests/inspector/network/network-request-query-string.html
index fccf180a..8605af39 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-request-query-string.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-request-query-string.html
@@ -6,7 +6,7 @@
 function test() {
     function checkURL(url)
     {
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), url, url, "", "", "");
+        var request = new SDK.NetworkRequest(url, url, "", "", "");
         InspectorTest.addResult("URL: " + url);
         InspectorTest.addResult("Query: " + request.queryString());
         InspectorTest.addResult("");
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html b/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html
index 649c948..6dfd7c54 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-status-non-http.html
@@ -16,7 +16,7 @@
         var urls = document.evaluate("//tbody/tr/td[position()=1]/@title", dataGrid, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
         var outputStrings = [];
 
-        for (var request of NetworkLog.networkLog.requestsForManager(InspectorTest.networkManager)) {
+        for (var request of NetworkLog.networkLog.requests()) {
             var line = request.displayName + ":" + request.statusCode + " " + request.statusText
             if (request.failed)
                 line += "(failed)";
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-toggle-type-filter.html b/third_party/WebKit/LayoutTests/inspector/network/network-toggle-type-filter.html
index 927aaa34..854d768 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-toggle-type-filter.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-toggle-type-filter.html
@@ -14,7 +14,7 @@
         InspectorTest.addResult((toggle ? "Toggled '" : "Clicked '") + buttonName + "' button.");
         target._resourceCategoryFilterUI._toggleTypeFilter(buttonName, toggle);
         var results = [];
-        var request = new SDK.NetworkRequest(SDK.targetManager.mainTarget(), "", "", "", "", "");
+        var request = new SDK.NetworkRequest("", "", "", "", "");
         for (var typeId in types) {
             var type = Common.resourceTypes[typeId];
             results.push(type.name() + ": " + target._resourceCategoryFilterUI.accept(type.category().title));
diff --git a/third_party/WebKit/LayoutTests/inspector/network/network-update-calculator-for-all-requests.html b/third_party/WebKit/LayoutTests/inspector/network/network-update-calculator-for-all-requests.html
index 34b35ae..cc6e26a 100644
--- a/third_party/WebKit/LayoutTests/inspector/network/network-update-calculator-for-all-requests.html
+++ b/third_party/WebKit/LayoutTests/inspector/network/network-update-calculator-for-all-requests.html
@@ -11,7 +11,7 @@
 
     function appendRequest(id, type, startTime, endTime)
     {
-        var request = new SDK.NetworkRequest(InspectorTest.networkManager, "", "", "", "", "");
+        var request = new SDK.NetworkRequest("", "", "", "", "");
         request.setResourceType(type);
         request.setRequestId(id);
         request.setIssueTime(startTime);
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
new file mode 100644
index 0000000..c701882
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
index 6208bc4..50a7923 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
index 819619a..47ca423 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
new file mode 100644
index 0000000..9080fab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
new file mode 100644
index 0000000..c701882
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
index d638819d..fefaf32 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/fillrect_gradient-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
index 85ad1689..ae32929 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
index ea41852..9080fab 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
new file mode 100644
index 0000000..2ec754d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
index 6b2fbc4b..9f1574a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-text-alignment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/fillrect_gradient-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
index f912c61..72c3721 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/fillrect_gradient-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
index 21794290..04dca73 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/gradient-add-second-start-end-stop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transforms/inline-in-transformed-multicol.html b/third_party/WebKit/LayoutTests/transforms/inline-in-transformed-multicol.html
new file mode 100644
index 0000000..bf77a18
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/transforms/inline-in-transformed-multicol.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="../resources/ahem.js"></script>
+<style>
+    body { margin:0; }
+</style>
+<div style="columns:3; width:100px; height:100px; transform:rotate(90deg); font:16px/1 Ahem; background:yellow;">
+    <span id="elm">XXX</span>
+</div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    test(function() {
+        var rects = document.getElementById("elm").getClientRects();
+        assert_equals(rects.length, 1);
+        var rect = rects[0];
+        assert_equals(rect.left, 84, "left");
+        assert_equals(rect.top, 0, "top");
+        assert_equals(rect.right, 100, "right");
+        assert_equals(rect.bottom, 48, "bottom");
+    }, "getClientRects of inline in transformed multicol");
+</script>
diff --git a/third_party/WebKit/LayoutTests/transforms/transformed-inline-block-in-multicol.html b/third_party/WebKit/LayoutTests/transforms/transformed-inline-block-in-multicol.html
new file mode 100644
index 0000000..20bfb87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/transforms/transformed-inline-block-in-multicol.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="../resources/ahem.js"></script>
+<style>
+    body { margin:0; }
+</style>
+<div style="columns:3; width:100px; height:100px; column-fill:auto; font:16px/1 Ahem; background:yellow;">
+    <span id="elm" style="display:inline-block; transform:translateX(16px) rotate(90deg); transform-origin:top left;">XXX</span>
+</div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script>
+    test(function() {
+        var rects = document.getElementById("elm").getClientRects();
+        assert_equals(rects.length, 1);
+        var rect = rects[0];
+        assert_equals(rect.left, 0, "left");
+        assert_equals(rect.top, 0, "top");
+        assert_between_inclusive(rect.right, 15.9, 16.1, "right");
+        assert_between_inclusive(rect.bottom, 47.9, 48.1, "bottom");
+    }, "getClientRects of transformed atomic inline in multicol");
+</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png b/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
deleted file mode 100644
index 07d1d8e..0000000
--- a/third_party/WebKit/LayoutTests/virtual/gpu-rasterization/images/cross-fade-overflow-position-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index 14538dc..e0f6d7b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -426,8 +426,9 @@
         return;
       }
 
-      std::unique_ptr<TextResourceDecoder> decoder(TextResourceDecoder::Create(
-          "application/javascript", WTF::TextEncoding(resource->Encoding())));
+      std::unique_ptr<TextResourceDecoder> decoder(
+          TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                      WTF::TextEncoding(resource->Encoding())));
       decoder->CheckForBOM(maybe_bom, kMaximumLengthOfBOM);
 
       // The encoding may change when we see the BOM. Check for BOM now
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index b2e1acd..34f7b232 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -574,6 +574,9 @@
     "$blink_core_output_dir/css/properties/CSSPropertyDescriptor.h",
     "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIBorderRadius.h",
     "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIFlex.h",
+    "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIFont.h",
+    "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIFontVariant.h",
+    "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIOverflow.h",
     "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPITextDecoration.h",
     "$blink_core_output_dir/css/properties/CSSShorthandPropertyAPIWebkitMarginCollapse.h",
   ]
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index d26178e0..32721fe 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -521,6 +521,9 @@
     "properties/CSSPropertyWebkitBorderWidthUtils.h",
     "properties/CSSShorthandPropertyAPIBorderRadius.cpp",
     "properties/CSSShorthandPropertyAPIFlex.cpp",
+    "properties/CSSShorthandPropertyAPIFont.cpp",
+    "properties/CSSShorthandPropertyAPIFontVariant.cpp",
+    "properties/CSSShorthandPropertyAPIOverflow.cpp",
     "properties/CSSShorthandPropertyAPITextDecoration.cpp",
     "properties/CSSShorthandPropertyAPIWebkitMarginCollapse.cpp",
     "resolver/AnimatedStyleBuilder.cpp",
@@ -538,6 +541,8 @@
     "resolver/FilterOperationResolver.h",
     "resolver/FontBuilder.cpp",
     "resolver/FontBuilder.h",
+    "resolver/FontStyleResolver.cpp",
+    "resolver/FontStyleResolver.h",
     "resolver/MatchRequest.h",
     "resolver/MatchResult.cpp",
     "resolver/MatchResult.h",
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index be437b4..c29bbbf 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -554,44 +554,6 @@
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(EFlexDirection e)
-    : CSSValue(kIdentifierClass) {
-  switch (e) {
-    case EFlexDirection::kRow:
-      value_id_ = CSSValueRow;
-      break;
-    case EFlexDirection::kRowReverse:
-      value_id_ = CSSValueRowReverse;
-      break;
-    case EFlexDirection::kColumn:
-      value_id_ = CSSValueColumn;
-      break;
-    case EFlexDirection::kColumnReverse:
-      value_id_ = CSSValueColumnReverse;
-      break;
-  }
-}
-
-template <>
-inline EFlexDirection CSSIdentifierValue::ConvertTo() const {
-  switch (value_id_) {
-    case CSSValueRow:
-      return EFlexDirection::kRow;
-    case CSSValueRowReverse:
-      return EFlexDirection::kRowReverse;
-    case CSSValueColumn:
-      return EFlexDirection::kColumn;
-    case CSSValueColumnReverse:
-      return EFlexDirection::kColumnReverse;
-    default:
-      break;
-  }
-
-  NOTREACHED();
-  return EFlexDirection::kRow;
-}
-
-template <>
 inline CSSIdentifierValue::CSSIdentifierValue(EFlexWrap e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index 39f003b..833718dd 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1215,10 +1215,10 @@
     {
       name: "flex-direction",
       type_name: "EFlexDirection",
-      field_template: "storage_only",
-      default_value: "EFlexDirection::kRow",
-      field_size: 2,
+      field_template: "keyword",
+      default_value: "row",
       field_group: "rare-non-inherited->flexible-box",
+      keywords: ["row", "row-reverse", "column", "column-reverse"],
     },
     {
       name: "flex-grow",
@@ -3664,10 +3664,14 @@
     {
       name: "font",
       longhands: "font-style;font-variant-ligatures;font-variant-caps;font-variant-numeric;font-weight;font-stretch;font-size;line-height;font-family",
+      api_class: true,
+      api_methods: ["parseShorthand"],
     },
     {
       name: "font-variant",
       longhands: "font-variant-ligatures;font-variant-caps;font-variant-numeric",
+      api_class: true,
+      api_methods: ["parseShorthand"],
       is_descriptor: true,
     },
     {
@@ -3738,6 +3742,8 @@
     {
       name: "overflow",
       longhands: "overflow-x;overflow-y",
+      api_class: true,
+      api_methods: ["parseShorthand"],
     },
     {
       name: "padding",
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index c6efe230..c21a17a 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -10,7 +10,6 @@
 #include "core/css/CSSContentDistributionValue.h"
 #include "core/css/CSSCursorImageValue.h"
 #include "core/css/CSSFontFaceSrcValue.h"
-#include "core/css/CSSFontFamilyValue.h"
 #include "core/css/CSSFunctionValue.h"
 #include "core/css/CSSGridAutoRepeatValue.h"
 #include "core/css/CSSGridLineNamesValue.h"
@@ -35,8 +34,6 @@
 #include "core/css/parser/CSSParserLocalContext.h"
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/parser/CSSVariableParser.h"
-#include "core/css/parser/FontVariantLigaturesParser.h"
-#include "core/css/parser/FontVariantNumericParser.h"
 #include "core/css/properties/CSSPropertyAPIOffsetAnchor.h"
 #include "core/css/properties/CSSPropertyAPIOffsetPosition.h"
 #include "core/css/properties/CSSPropertyAlignmentUtils.h"
@@ -71,12 +68,17 @@
   range_.ConsumeWhitespace();
 }
 
+// AddProperty takes implicit as an enum, below we're using a bool because
+// AddParsedProperty will be removed after we finish implemenation of property
+// APIs.
 void CSSPropertyParser::AddParsedProperty(CSSPropertyID resolved_property,
                                           CSSPropertyID current_shorthand,
                                           const CSSValue& value,
                                           bool important,
                                           bool implicit) {
-  AddProperty(resolved_property, current_shorthand, value, important, implicit,
+  AddProperty(resolved_property, current_shorthand, value, important,
+              implicit ? IsImplicitProperty::kImplicit
+                       : IsImplicitProperty::kNotImplicit,
               *parsed_properties_);
 }
 
@@ -282,10 +284,6 @@
   return true;
 }
 
-static CSSIdentifierValue* ConsumeFontVariantCSS21(CSSParserTokenRange& range) {
-  return ConsumeIdent<CSSValueNormal, CSSValueSmallCaps>(range);
-}
-
 static CSSValue* ConsumeFontVariantList(CSSParserTokenRange& range) {
   CSSValueList* values = CSSValueList::CreateCommaSeparated();
   do {
@@ -298,7 +296,8 @@
         return nullptr;
       return ConsumeIdent(range);
     }
-    CSSIdentifierValue* font_variant = ConsumeFontVariantCSS21(range);
+    CSSIdentifierValue* font_variant =
+        CSSPropertyFontUtils::ConsumeFontVariantCSS21(range);
     if (font_variant)
       values->Append(*font_variant);
   } while (ConsumeCommaIncludingWhitespace(range));
@@ -1740,211 +1739,6 @@
   return true;
 }
 
-bool CSSPropertyParser::ConsumeSystemFont(bool important) {
-  CSSValueID system_font_id = range_.ConsumeIncludingWhitespace().Id();
-  DCHECK_GE(system_font_id, CSSValueCaption);
-  DCHECK_LE(system_font_id, CSSValueStatusBar);
-  if (!range_.AtEnd())
-    return false;
-
-  FontStyle font_style = kFontStyleNormal;
-  FontWeight font_weight = kFontWeightNormal;
-  float font_size = 0;
-  AtomicString font_family;
-  LayoutTheme::GetTheme().SystemFont(system_font_id, font_style, font_weight,
-                                     font_size, font_family);
-
-  AddParsedProperty(CSSPropertyFontStyle, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(font_style == kFontStyleItalic
-                                                    ? CSSValueItalic
-                                                    : CSSValueNormal),
-                    important);
-  AddParsedProperty(CSSPropertyFontWeight, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(font_weight), important);
-  AddParsedProperty(CSSPropertyFontSize, CSSPropertyFont,
-                    *CSSPrimitiveValue::Create(
-                        font_size, CSSPrimitiveValue::UnitType::kPixels),
-                    important);
-  CSSValueList* font_family_list = CSSValueList::CreateCommaSeparated();
-  font_family_list->Append(*CSSFontFamilyValue::Create(font_family));
-  AddParsedProperty(CSSPropertyFontFamily, CSSPropertyFont, *font_family_list,
-                    important);
-
-  AddParsedProperty(CSSPropertyFontStretch, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  AddParsedProperty(CSSPropertyFontVariantCaps, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  AddParsedProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  AddParsedProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  AddParsedProperty(CSSPropertyLineHeight, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  return true;
-}
-
-bool CSSPropertyParser::ConsumeFont(bool important) {
-  // Let's check if there is an inherit or initial somewhere in the shorthand.
-  CSSParserTokenRange range = range_;
-  while (!range.AtEnd()) {
-    CSSValueID id = range.ConsumeIncludingWhitespace().Id();
-    if (id == CSSValueInherit || id == CSSValueInitial)
-      return false;
-  }
-  // Optional font-style, font-variant, font-stretch and font-weight.
-  CSSIdentifierValue* font_style = nullptr;
-  CSSIdentifierValue* font_variant_caps = nullptr;
-  CSSIdentifierValue* font_weight = nullptr;
-  CSSIdentifierValue* font_stretch = nullptr;
-  while (!range_.AtEnd()) {
-    CSSValueID id = range_.Peek().Id();
-    if (!font_style && CSSParserFastPaths::IsValidKeywordPropertyAndValue(
-                           CSSPropertyFontStyle, id, context_->Mode())) {
-      font_style = ConsumeIdent(range_);
-      continue;
-    }
-    if (!font_variant_caps &&
-        (id == CSSValueNormal || id == CSSValueSmallCaps)) {
-      // Font variant in the shorthand is particular, it only accepts normal or
-      // small-caps.
-      // See https://drafts.csswg.org/css-fonts/#propdef-font
-      font_variant_caps = ConsumeFontVariantCSS21(range_);
-      if (font_variant_caps)
-        continue;
-    }
-    if (!font_weight) {
-      font_weight = CSSPropertyFontUtils::ConsumeFontWeight(range_);
-      if (font_weight)
-        continue;
-    }
-    if (!font_stretch && CSSParserFastPaths::IsValidKeywordPropertyAndValue(
-                             CSSPropertyFontStretch, id, context_->Mode()))
-      font_stretch = ConsumeIdent(range_);
-    else
-      break;
-  }
-
-  if (range_.AtEnd())
-    return false;
-
-  AddParsedProperty(
-      CSSPropertyFontStyle, CSSPropertyFont,
-      font_style ? *font_style : *CSSIdentifierValue::Create(CSSValueNormal),
-      important);
-  AddParsedProperty(CSSPropertyFontVariantCaps, CSSPropertyFont,
-                    font_variant_caps
-                        ? *font_variant_caps
-                        : *CSSIdentifierValue::Create(CSSValueNormal),
-                    important);
-  AddParsedProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-  AddParsedProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont,
-                    *CSSIdentifierValue::Create(CSSValueNormal), important);
-
-  AddParsedProperty(
-      CSSPropertyFontWeight, CSSPropertyFont,
-      font_weight ? *font_weight : *CSSIdentifierValue::Create(CSSValueNormal),
-      important);
-  AddParsedProperty(CSSPropertyFontStretch, CSSPropertyFont,
-                    font_stretch ? *font_stretch
-                                 : *CSSIdentifierValue::Create(CSSValueNormal),
-                    important);
-
-  // Now a font size _must_ come.
-  CSSValue* font_size =
-      CSSPropertyFontUtils::ConsumeFontSize(range_, context_->Mode());
-  if (!font_size || range_.AtEnd())
-    return false;
-
-  AddParsedProperty(CSSPropertyFontSize, CSSPropertyFont, *font_size,
-                    important);
-
-  if (ConsumeSlashIncludingWhitespace(range_)) {
-    CSSValue* line_height =
-        CSSPropertyFontUtils::ConsumeLineHeight(range_, context_->Mode());
-    if (!line_height)
-      return false;
-    AddParsedProperty(CSSPropertyLineHeight, CSSPropertyFont, *line_height,
-                      important);
-  } else {
-    AddParsedProperty(CSSPropertyLineHeight, CSSPropertyFont,
-                      *CSSIdentifierValue::Create(CSSValueNormal), important);
-  }
-
-  // Font family must come now.
-  CSSValue* parsed_family_value =
-      CSSPropertyFontUtils::ConsumeFontFamily(range_);
-  if (!parsed_family_value)
-    return false;
-
-  AddParsedProperty(CSSPropertyFontFamily, CSSPropertyFont,
-                    *parsed_family_value, important);
-
-  // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires
-  // that "font-stretch", "font-size-adjust", and "font-kerning" be reset to
-  // their initial values but we don't seem to support them at the moment. They
-  // should also be added here once implemented.
-  return range_.AtEnd();
-}
-
-bool CSSPropertyParser::ConsumeFontVariantShorthand(bool important) {
-  if (IdentMatches<CSSValueNormal, CSSValueNone>(range_.Peek().Id())) {
-    AddParsedProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant,
-                      *ConsumeIdent(range_), important);
-    AddParsedProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant,
-                      *CSSIdentifierValue::Create(CSSValueNormal), important);
-    return range_.AtEnd();
-  }
-
-  CSSIdentifierValue* caps_value = nullptr;
-  FontVariantLigaturesParser ligatures_parser;
-  FontVariantNumericParser numeric_parser;
-  do {
-    FontVariantLigaturesParser::ParseResult ligatures_parse_result =
-        ligatures_parser.ConsumeLigature(range_);
-    FontVariantNumericParser::ParseResult numeric_parse_result =
-        numeric_parser.ConsumeNumeric(range_);
-    if (ligatures_parse_result ==
-            FontVariantLigaturesParser::ParseResult::kConsumedValue ||
-        numeric_parse_result ==
-            FontVariantNumericParser::ParseResult::kConsumedValue)
-      continue;
-
-    if (ligatures_parse_result ==
-            FontVariantLigaturesParser::ParseResult::kDisallowedValue ||
-        numeric_parse_result ==
-            FontVariantNumericParser::ParseResult::kDisallowedValue)
-      return false;
-
-    CSSValueID id = range_.Peek().Id();
-    switch (id) {
-      case CSSValueSmallCaps:
-      case CSSValueAllSmallCaps:
-      case CSSValuePetiteCaps:
-      case CSSValueAllPetiteCaps:
-      case CSSValueUnicase:
-      case CSSValueTitlingCaps:
-        // Only one caps value permitted in font-variant grammar.
-        if (caps_value)
-          return false;
-        caps_value = ConsumeIdent(range_);
-        break;
-      default:
-        return false;
-    }
-  } while (!range_.AtEnd());
-
-  AddParsedProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant,
-                    *ligatures_parser.FinalizeValue(), important);
-  AddParsedProperty(CSSPropertyFontVariantNumeric, CSSPropertyFontVariant,
-                    *numeric_parser.FinalizeValue(), important);
-  AddParsedProperty(
-      CSSPropertyFontVariantCaps, CSSPropertyFontVariant,
-      caps_value ? *caps_value : *CSSIdentifierValue::Create(CSSValueNormal),
-      important);
-  return true;
-}
-
 bool CSSPropertyParser::ConsumeBorderSpacing(bool important) {
   CSSValue* horizontal_spacing = ConsumeLength(
       range_, context_->Mode(), kValueRangeNonNegative, UnitlessQuirk::kAllow);
@@ -2980,43 +2774,6 @@
   }
 
   switch (property) {
-    case CSSPropertyOverflow: {
-      CSSValueID id = range_.ConsumeIncludingWhitespace().Id();
-      if (!CSSParserFastPaths::IsValidKeywordPropertyAndValue(
-              CSSPropertyOverflowY, id, context_->Mode()))
-        return false;
-      if (!range_.AtEnd())
-        return false;
-      CSSValue* overflow_y_value = CSSIdentifierValue::Create(id);
-
-      CSSValue* overflow_x_value = nullptr;
-
-      // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y.
-      // If
-      // this value has been set using the shorthand, then for now overflow-x
-      // will default to auto, but once we implement pagination controls, it
-      // should default to hidden. If the overflow-y value is anything but
-      // paged-x or paged-y, then overflow-x and overflow-y should have the
-      // same
-      // value.
-      if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY)
-        overflow_x_value = CSSIdentifierValue::Create(CSSValueAuto);
-      else
-        overflow_x_value = overflow_y_value;
-      AddParsedProperty(CSSPropertyOverflowX, CSSPropertyOverflow,
-                        *overflow_x_value, important);
-      AddParsedProperty(CSSPropertyOverflowY, CSSPropertyOverflow,
-                        *overflow_y_value, important);
-      return true;
-    }
-    case CSSPropertyFont: {
-      const CSSParserToken& token = range_.Peek();
-      if (token.Id() >= CSSValueCaption && token.Id() <= CSSValueStatusBar)
-        return ConsumeSystemFont(important);
-      return ConsumeFont(important);
-    }
-    case CSSPropertyFontVariant:
-      return ConsumeFontVariantShorthand(important);
     case CSSPropertyBorderSpacing:
       return ConsumeBorderSpacing(important);
     case CSSPropertyColumns:
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
index 7e9a362..006910e 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -108,10 +108,6 @@
   bool ConsumePlaceItemsShorthand(bool important);
   bool ConsumePlaceSelfShorthand(bool important);
 
-  bool ConsumeFont(bool important);
-  bool ConsumeFontVariantShorthand(bool important);
-  bool ConsumeSystemFont(bool important);
-
   bool ConsumeBorderSpacing(bool important);
 
   // CSS3 Parsing Routines (for properties specific to CSS3)
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
index 524e343..4811660 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
@@ -1461,9 +1461,11 @@
                  CSSPropertyID current_shorthand,
                  const CSSValue& value,
                  bool important,
-                 bool implicit,
+                 IsImplicitProperty implicit,
                  HeapVector<CSSProperty, 256>& properties) {
   DCHECK(!isPropertyAlias(resolved_property));
+  DCHECK(implicit == IsImplicitProperty::kNotImplicit ||
+         implicit == IsImplicitProperty::kImplicit);
 
   int shorthand_index = 0;
   bool set_from_shorthand = false;
@@ -1480,7 +1482,7 @@
 
   properties.push_back(CSSProperty(resolved_property, value, important,
                                    set_from_shorthand, shorthand_index,
-                                   implicit));
+                                   implicit == IsImplicitProperty::kImplicit));
 }
 
 }  // namespace CSSPropertyParserHelpers
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h
index fe5e17ad..8cf5e89 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.h
@@ -111,11 +111,13 @@
 
 CSSIdentifierValue* ConsumeShapeBox(CSSParserTokenRange&);
 
+enum class IsImplicitProperty { kNotImplicit, kImplicit };
+
 void AddProperty(CSSPropertyID resolved_property,
                  CSSPropertyID current_shorthand,
                  const CSSValue&,
                  bool important,
-                 bool implicit,
+                 IsImplicitProperty,
                  HeapVector<CSSProperty, 256>& properties);
 
 // Template implementations are at the bottom of the file for readability.
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
index 64c14df..0b223e2 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
@@ -161,4 +161,10 @@
   return CSSFontFeatureValue::Create(tag, tag_value);
 }
 
+CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontVariantCSS21(
+    CSSParserTokenRange& range) {
+  return CSSPropertyParserHelpers::ConsumeIdent<CSSValueNormal,
+                                                CSSValueSmallCaps>(range);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
index 0696ac6d..26fd14b0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
@@ -37,6 +37,8 @@
 
   static CSSValue* ConsumeFontFeatureSettings(CSSParserTokenRange&);
   static CSSFontFeatureValue* ConsumeFontFeatureTag(CSSParserTokenRange&);
+
+  static CSSIdentifierValue* ConsumeFontVariantCSS21(CSSParserTokenRange&);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
index f2ca520..8771bfe 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIBorderRadius.cpp
@@ -30,22 +30,26 @@
       CSSPropertyBorderTopLeftRadius, CSSPropertyBorderRadius,
       *CSSValuePair::Create(horizontal_radii[0], vertical_radii[0],
                             CSSValuePair::kDropIdenticalValues),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyBorderTopRightRadius, CSSPropertyBorderRadius,
       *CSSValuePair::Create(horizontal_radii[1], vertical_radii[1],
                             CSSValuePair::kDropIdenticalValues),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyBorderBottomRightRadius, CSSPropertyBorderRadius,
       *CSSValuePair::Create(horizontal_radii[2], vertical_radii[2],
                             CSSValuePair::kDropIdenticalValues),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderRadius,
       *CSSValuePair::Create(horizontal_radii[3], vertical_radii[3],
                             CSSValuePair::kDropIdenticalValues),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFlex.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFlex.cpp
index 954b946..dec40914 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFlex.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFlex.cpp
@@ -76,16 +76,18 @@
       CSSPropertyFlexGrow, CSSPropertyFlex,
       *CSSPrimitiveValue::Create(clampTo<float>(flex_grow),
                                  CSSPrimitiveValue::UnitType::kNumber),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFlexShrink, CSSPropertyFlex,
       *CSSPrimitiveValue::Create(clampTo<float>(flex_shrink),
                                  CSSPrimitiveValue::UnitType::kNumber),
-      important, false /* implicit */, properties);
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
 
-  CSSPropertyParserHelpers::AddProperty(CSSPropertyFlexBasis, CSSPropertyFlex,
-                                        *flex_basis, important,
-                                        false /* implicit */, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFlexBasis, CSSPropertyFlex, *flex_basis, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
 
   return true;
 }
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
new file mode 100644
index 0000000..f21e5ca4
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
@@ -0,0 +1,216 @@
+// 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 "core/css/properties/CSSShorthandPropertyAPIFont.h"
+
+#include "core/css/CSSFontFamilyValue.h"
+#include "core/css/CSSIdentifierValue.h"
+#include "core/css/CSSPrimitiveValueMappings.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSParserFastPaths.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "core/css/properties/CSSPropertyFontUtils.h"
+#include "platform/fonts/FontTraits.h"
+
+namespace blink {
+
+namespace {
+
+bool ConsumeSystemFont(bool important,
+                       CSSParserTokenRange& range,
+                       HeapVector<CSSProperty, 256>& properties) {
+  CSSValueID system_font_id = range.ConsumeIncludingWhitespace().Id();
+  DCHECK_GE(system_font_id, CSSValueCaption);
+  DCHECK_LE(system_font_id, CSSValueStatusBar);
+  if (!range.AtEnd())
+    return false;
+
+  FontStyle font_style = kFontStyleNormal;
+  FontWeight font_weight = kFontWeightNormal;
+  float font_size = 0;
+  AtomicString font_family;
+  LayoutTheme::GetTheme().SystemFont(system_font_id, font_style, font_weight,
+                                     font_size, font_family);
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontStyle, CSSPropertyFont,
+      *CSSIdentifierValue::Create(
+          font_style == kFontStyleItalic ? CSSValueItalic : CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontWeight, CSSPropertyFont,
+      *CSSIdentifierValue::Create(font_weight), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontSize, CSSPropertyFont,
+      *CSSPrimitiveValue::Create(font_size,
+                                 CSSPrimitiveValue::UnitType::kPixels),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+
+  CSSValueList* font_family_list = CSSValueList::CreateCommaSeparated();
+  font_family_list->Append(*CSSFontFamilyValue::Create(font_family));
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontFamily, CSSPropertyFont, *font_family_list, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontStretch, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantCaps, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantLigatures, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantNumeric, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyLineHeight, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  return true;
+}
+
+bool ConsumeFont(bool important,
+                 CSSParserTokenRange& range,
+                 const CSSParserContext& context,
+                 HeapVector<CSSProperty, 256>& properties) {
+  // Let's check if there is an inherit or initial somewhere in the shorthand.
+  CSSParserTokenRange range_copy = range;
+  while (!range_copy.AtEnd()) {
+    CSSValueID id = range_copy.ConsumeIncludingWhitespace().Id();
+    if (id == CSSValueInherit || id == CSSValueInitial)
+      return false;
+  }
+  // Optional font-style, font-variant, font-stretch and font-weight.
+  CSSIdentifierValue* font_style = nullptr;
+  CSSIdentifierValue* font_variant_caps = nullptr;
+  CSSIdentifierValue* font_weight = nullptr;
+  CSSIdentifierValue* font_stretch = nullptr;
+  while (!range.AtEnd()) {
+    CSSValueID id = range.Peek().Id();
+    if (!font_style && CSSParserFastPaths::IsValidKeywordPropertyAndValue(
+                           CSSPropertyFontStyle, id, context.Mode())) {
+      font_style = CSSPropertyParserHelpers::ConsumeIdent(range);
+      continue;
+    }
+    if (!font_variant_caps &&
+        (id == CSSValueNormal || id == CSSValueSmallCaps)) {
+      // Font variant in the shorthand is particular, it only accepts normal or
+      // small-caps.
+      // See https://drafts.csswg.org/css-fonts/#propdef-font
+      font_variant_caps = CSSPropertyFontUtils::ConsumeFontVariantCSS21(range);
+      if (font_variant_caps)
+        continue;
+    }
+    if (!font_weight) {
+      font_weight = CSSPropertyFontUtils::ConsumeFontWeight(range);
+      if (font_weight)
+        continue;
+    }
+    if (!font_stretch && CSSParserFastPaths::IsValidKeywordPropertyAndValue(
+                             CSSPropertyFontStretch, id, context.Mode()))
+      font_stretch = CSSPropertyParserHelpers::ConsumeIdent(range);
+    else
+      break;
+  }
+
+  if (range.AtEnd())
+    return false;
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontStyle, CSSPropertyFont,
+      font_style ? *font_style : *CSSIdentifierValue::Create(CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantCaps, CSSPropertyFont,
+      font_variant_caps ? *font_variant_caps
+                        : *CSSIdentifierValue::Create(CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantLigatures, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantNumeric, CSSPropertyFont,
+      *CSSIdentifierValue::Create(CSSValueNormal), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontWeight, CSSPropertyFont,
+      font_weight ? *font_weight : *CSSIdentifierValue::Create(CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontStretch, CSSPropertyFont,
+      font_stretch ? *font_stretch
+                   : *CSSIdentifierValue::Create(CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+
+  // Now a font size _must_ come.
+  CSSValue* font_size =
+      CSSPropertyFontUtils::ConsumeFontSize(range, context.Mode());
+  if (!font_size || range.AtEnd())
+    return false;
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontSize, CSSPropertyFont, *font_size, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+
+  if (CSSPropertyParserHelpers::ConsumeSlashIncludingWhitespace(range)) {
+    CSSValue* line_height =
+        CSSPropertyFontUtils::ConsumeLineHeight(range, context.Mode());
+    if (!line_height)
+      return false;
+    CSSPropertyParserHelpers::AddProperty(
+        CSSPropertyLineHeight, CSSPropertyFont, *line_height, important,
+        CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  } else {
+    CSSPropertyParserHelpers::AddProperty(
+        CSSPropertyLineHeight, CSSPropertyFont,
+        *CSSIdentifierValue::Create(CSSValueNormal), important,
+        CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  }
+
+  // Font family must come now.
+  CSSValue* parsed_family_value =
+      CSSPropertyFontUtils::ConsumeFontFamily(range);
+  if (!parsed_family_value)
+    return false;
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontFamily, CSSPropertyFont, *parsed_family_value, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+
+  // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires
+  // that "font-stretch", "font-size-adjust", and "font-kerning" be reset to
+  // their initial values but we don't seem to support them at the moment. They
+  // should also be added here once implemented.
+  return range.AtEnd();
+}
+
+}  // namespace
+
+bool CSSShorthandPropertyAPIFont::parseShorthand(
+    bool important,
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&,
+    HeapVector<CSSProperty, 256>& properties) {
+  const CSSParserToken& token = range.Peek();
+  if (token.Id() >= CSSValueCaption && token.Id() <= CSSValueStatusBar)
+    return ConsumeSystemFont(important, range, properties);
+  return ConsumeFont(important, range, context, properties);
+}
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFontVariant.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFontVariant.cpp
new file mode 100644
index 0000000..e49f4012
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFontVariant.cpp
@@ -0,0 +1,86 @@
+// 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 "core/css/properties/CSSShorthandPropertyAPIFontVariant.h"
+
+#include "core/css/CSSIdentifierValue.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+#include "core/css/parser/FontVariantLigaturesParser.h"
+#include "core/css/parser/FontVariantNumericParser.h"
+
+namespace blink {
+
+bool CSSShorthandPropertyAPIFontVariant::parseShorthand(
+    bool important,
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&,
+    HeapVector<CSSProperty, 256>& properties) {
+  if (CSSPropertyParserHelpers::IdentMatches<CSSValueNormal, CSSValueNone>(
+          range.Peek().Id())) {
+    CSSPropertyParserHelpers::AddProperty(
+        CSSPropertyFontVariantLigatures, CSSPropertyFontVariant,
+        *CSSPropertyParserHelpers::ConsumeIdent(range), important,
+        CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+    CSSPropertyParserHelpers::AddProperty(
+        CSSPropertyFontVariantCaps, CSSPropertyFontVariant,
+        *CSSIdentifierValue::Create(CSSValueNormal), important,
+        CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+    return range.AtEnd();
+  }
+
+  CSSIdentifierValue* caps_value = nullptr;
+  FontVariantLigaturesParser ligatures_parser;
+  FontVariantNumericParser numeric_parser;
+  do {
+    FontVariantLigaturesParser::ParseResult ligatures_parse_result =
+        ligatures_parser.ConsumeLigature(range);
+    FontVariantNumericParser::ParseResult numeric_parse_result =
+        numeric_parser.ConsumeNumeric(range);
+    if (ligatures_parse_result ==
+            FontVariantLigaturesParser::ParseResult::kConsumedValue ||
+        numeric_parse_result ==
+            FontVariantNumericParser::ParseResult::kConsumedValue)
+      continue;
+
+    if (ligatures_parse_result ==
+            FontVariantLigaturesParser::ParseResult::kDisallowedValue ||
+        numeric_parse_result ==
+            FontVariantNumericParser::ParseResult::kDisallowedValue)
+      return false;
+
+    CSSValueID id = range.Peek().Id();
+    switch (id) {
+      case CSSValueSmallCaps:
+      case CSSValueAllSmallCaps:
+      case CSSValuePetiteCaps:
+      case CSSValueAllPetiteCaps:
+      case CSSValueUnicase:
+      case CSSValueTitlingCaps:
+        // Only one caps value permitted in font-variant grammar.
+        if (caps_value)
+          return false;
+        caps_value = CSSPropertyParserHelpers::ConsumeIdent(range);
+        break;
+      default:
+        return false;
+    }
+  } while (!range.AtEnd());
+
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantLigatures, CSSPropertyFontVariant,
+      *ligatures_parser.FinalizeValue(), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantNumeric, CSSPropertyFontVariant,
+      *numeric_parser.FinalizeValue(), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyFontVariantCaps, CSSPropertyFontVariant,
+      caps_value ? *caps_value : *CSSIdentifierValue::Create(CSSValueNormal),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
+  return true;
+}
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIOverflow.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIOverflow.cpp
new file mode 100644
index 0000000..eef7d1b
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIOverflow.cpp
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/css/properties/CSSShorthandPropertyAPIOverflow.h"
+
+#include "core/css/CSSIdentifierValue.h"
+#include "core/css/parser/CSSParserContext.h"
+#include "core/css/parser/CSSParserFastPaths.h"
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+
+bool CSSShorthandPropertyAPIOverflow::parseShorthand(
+    bool important,
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext&,
+    HeapVector<CSSProperty, 256>& properties) {
+  CSSValueID id = range.ConsumeIncludingWhitespace().Id();
+  if (!CSSParserFastPaths::IsValidKeywordPropertyAndValue(CSSPropertyOverflowY,
+                                                          id, context.Mode()))
+    return false;
+  if (!range.AtEnd())
+    return false;
+  CSSValue* overflow_y_value = CSSIdentifierValue::Create(id);
+
+  CSSValue* overflow_x_value = nullptr;
+
+  // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y.
+  // If
+  // this value has been set using the shorthand, then for now overflow-x
+  // will default to auto, but once we implement pagination controls, it
+  // should default to hidden. If the overflow-y value is anything but
+  // paged-x or paged-y, then overflow-x and overflow-y should have the
+  // same
+  // value.
+  if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY)
+    overflow_x_value = CSSIdentifierValue::Create(CSSValueAuto);
+  else
+    overflow_x_value = overflow_y_value;
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyOverflowX, CSSPropertyOverflow, *overflow_x_value, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  CSSPropertyParserHelpers::AddProperty(
+      CSSPropertyOverflowY, CSSPropertyOverflow, *overflow_y_value, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+  return true;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMarginCollapse.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMarginCollapse.cpp
index cf22436..970c165 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMarginCollapse.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIWebkitMarginCollapse.cpp
@@ -25,12 +25,14 @@
   CSSValue* before_collapse = CSSIdentifierValue::Create(id);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginCollapse,
-      *before_collapse, important, false /* implicit */, properties);
+      *before_collapse, important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
 
   if (range.AtEnd()) {
     CSSPropertyParserHelpers::AddProperty(
         CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse,
-        *before_collapse, important, false /* implicit */, properties);
+        *before_collapse, important,
+        CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
     return true;
   }
 
@@ -40,8 +42,8 @@
     return false;
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse,
-      *CSSIdentifierValue::Create(id), important, false /* implicit */,
-      properties);
+      *CSSIdentifierValue::Create(id), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp b/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
index 2d3a0ac..131ca19a 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
@@ -256,11 +256,6 @@
   }
 }
 
-void FontBuilder::UpdateOrientation(FontDescription& description,
-                                    const ComputedStyle& style) {
-  description.SetOrientation(ComputeFontOrientation(style));
-}
-
 void FontBuilder::CheckForGenericFamilyChange(
     const FontDescription& old_description,
     FontDescription& new_description) {
@@ -340,9 +335,8 @@
   adjusted_size = GetComputedSizeFromSpecifiedSize(
       font_description, style.EffectiveZoom(), adjusted_size);
 
-  float multiplier = style.TextAutosizingMultiplier();
-  adjusted_size =
-      TextAutosizer::ComputeAutosizedFontSize(adjusted_size, multiplier);
+  adjusted_size = TextAutosizer::ComputeAutosizedFontSize(
+      adjusted_size, style.TextAutosizingMultiplier());
   font_description.SetAdjustedSize(adjusted_size);
 }
 
@@ -351,19 +345,13 @@
   float computed_size =
       GetComputedSizeFromSpecifiedSize(font_description, style.EffectiveZoom(),
                                        font_description.SpecifiedSize());
-  float multiplier = style.TextAutosizingMultiplier();
-  computed_size =
-      TextAutosizer::ComputeAutosizedFontSize(computed_size, multiplier);
+  computed_size = TextAutosizer::ComputeAutosizedFontSize(
+      computed_size, style.TextAutosizingMultiplier());
   font_description.SetComputedSize(computed_size);
 }
 
-void FontBuilder::CreateFont(FontSelector* font_selector,
-                             ComputedStyle& style) {
-  if (!flags_)
-    return;
-
-  FontDescription description = style.GetFontDescription();
-
+void FontBuilder::UpdateFontDescription(FontDescription& description,
+                                        FontOrientation font_orientation) {
   if (IsSet(PropertySetFlag::kFamily)) {
     description.SetGenericFamily(font_description_.GenericFamily());
     description.SetFamily(font_description_.Family());
@@ -373,6 +361,7 @@
     description.SetSpecifiedSize(font_description_.SpecifiedSize());
     description.SetIsAbsoluteSize(font_description_.IsAbsoluteSize());
   }
+
   if (IsSet(PropertySetFlag::kSizeAdjust))
     description.SetSizeAdjust(font_description_.SizeAdjust());
   if (IsSet(PropertySetFlag::kWeight))
@@ -401,7 +390,30 @@
     description.SetFontSmoothing(font_description_.FontSmoothing());
   if (IsSet(PropertySetFlag::kTextOrientation) ||
       IsSet(PropertySetFlag::kWritingMode))
-    UpdateOrientation(description, style);
+    description.SetOrientation(font_orientation);
+
+  float size = description.SpecifiedSize();
+  if (!size && description.KeywordSize()) {
+    size = FontSizeForKeyword(description.KeywordSize(),
+                              description.IsMonospace());
+  }
+
+  description.SetSpecifiedSize(size);
+  description.SetComputedSize(size);
+  if (size && description.HasSizeAdjust())
+    description.SetAdjustedSize(size);
+}
+
+void FontBuilder::CreateFont(FontSelector* font_selector,
+                             ComputedStyle& style) {
+  DCHECK(document_);
+
+  if (!flags_)
+    return;
+
+  FontDescription description = style.GetFontDescription();
+
+  UpdateFontDescription(description, ComputeFontOrientation(style));
 
   UpdateSpecifiedSize(description, style);
   UpdateComputedSize(description, style);
@@ -425,7 +437,7 @@
   UpdateSpecifiedSize(font_description, document_style);
   UpdateComputedSize(font_description, document_style);
 
-  UpdateOrientation(font_description, document_style);
+  font_description.SetOrientation(ComputeFontOrientation(document_style));
   document_style.SetFontDescription(font_description);
   document_style.GetFont().Update(font_selector);
 }
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
index 322fd70..93e3fa3 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
@@ -73,6 +73,8 @@
   void SetVariationSettings(PassRefPtr<FontVariationSettings>);
 
   // FIXME: These need to just vend a Font object eventually.
+  void UpdateFontDescription(FontDescription&,
+                             FontOrientation = FontOrientation::kHorizontal);
   void CreateFont(FontSelector*, ComputedStyle&);
 
   void CreateFontForDocument(FontSelector*, ComputedStyle&);
@@ -114,7 +116,6 @@
   void SetFamilyDescription(FontDescription&,
                             const FontDescription::FamilyDescription&);
   void SetSize(FontDescription&, const FontDescription::Size&);
-  void UpdateOrientation(FontDescription&, const ComputedStyle&);
   // This function fixes up the default font size if it detects that the current
   // generic font family has changed. -dwh
   void CheckForGenericFamilyChange(const FontDescription&, FontDescription&);
diff --git a/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp
new file mode 100644
index 0000000..440483f
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp
@@ -0,0 +1,58 @@
+// 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 "core/css/resolver/FontStyleResolver.h"
+
+#include "core/css/CSSToLengthConversionData.h"
+#include "core/css/resolver/FontBuilder.h"
+#include "core/css/resolver/StyleBuilderConverter.h"
+#include "platform/fonts/FontDescription.h"
+
+namespace blink {
+
+FontDescription FontStyleResolver::ComputeFont(
+    const StylePropertySet& property_set) {
+  FontBuilder builder(nullptr);
+
+  FontDescription fontDescription;
+  Font font(fontDescription);
+  CSSToLengthConversionData::FontSizes fontSizes(16, 16, &font);
+  CSSToLengthConversionData::ViewportSize viewportSize(0, 0);
+  CSSToLengthConversionData conversionData(nullptr, fontSizes, viewportSize, 1);
+
+  // CSSPropertyFontSize
+  builder.SetSize(StyleBuilderConverterBase::ConvertFontSize(
+      *property_set.GetPropertyCSSValue(CSSPropertyFontSize), conversionData,
+      FontDescription::Size(0, 0.0f, false)));
+
+  // CSSPropertyFontFamily
+  builder.SetFamilyDescription(StyleBuilderConverterBase::ConvertFontFamily(
+      *property_set.GetPropertyCSSValue(CSSPropertyFontFamily), &builder,
+      nullptr));
+
+  // CSSPropertyFontStretch
+  builder.SetStretch(ToCSSIdentifierValue(*property_set.GetPropertyCSSValue(
+                                              CSSPropertyFontStretch))
+                         .ConvertTo<FontStretch>());
+
+  // CSSPropertyFontStyle
+  builder.SetStyle(ToCSSIdentifierValue(
+                       *property_set.GetPropertyCSSValue(CSSPropertyFontStyle))
+                       .ConvertTo<FontStyle>());
+
+  // CSSPropertyFontVariantCaps
+  builder.SetVariantCaps(StyleBuilderConverterBase::ConvertFontVariantCaps(
+      *property_set.GetPropertyCSSValue(CSSPropertyFontVariantCaps)));
+
+  // CSSPropertyFontWeight
+  builder.SetWeight(StyleBuilderConverterBase::ConvertFontWeight(
+      *property_set.GetPropertyCSSValue(CSSPropertyFontWeight),
+      FontBuilder::InitialWeight()));
+
+  builder.UpdateFontDescription(fontDescription);
+
+  return fontDescription;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.h b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.h
new file mode 100644
index 0000000..77870f0
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.h
@@ -0,0 +1,28 @@
+// 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 FontStyleResolver_h
+#define FontStyleResolver_h
+
+#include "core/css/CSSPrimitiveValueMappings.h"
+#include "core/css/CSSValueIDMappings.h"
+#include "core/css/StylePropertySet.h"
+#include "platform/fonts/FontDescription.h"
+
+namespace blink {
+
+// FontStyleResolver is a simpler version of Font-related parts of
+// StyleResolver. This is needed because ComputedStyle/StyleResolver can't run
+// outside the main thread or without a document. This is a way of minimizing
+// duplicate code for when font parsing is needed.
+class CORE_EXPORT FontStyleResolver {
+  STATIC_ONLY(FontStyleResolver);
+
+ public:
+  static FontDescription ComputeFont(const StylePropertySet&);
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index 9178ad5..9c63a14 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -186,31 +186,33 @@
 }
 
 static bool ConvertFontFamilyName(
-    StyleResolverState& state,
     const CSSValue& value,
     FontDescription::GenericFamilyType& generic_family,
-    AtomicString& family_name) {
+    AtomicString& family_name,
+    FontBuilder* font_builder,
+    const Document* document_for_count) {
   if (value.IsFontFamilyValue()) {
     generic_family = FontDescription::kNoFamily;
     family_name = AtomicString(ToCSSFontFamilyValue(value).Value());
 #if OS(MACOSX)
     if (family_name == FontCache::LegacySystemFontFamily()) {
-      UseCounter::Count(state.GetDocument(), WebFeature::kBlinkMacSystemFont);
+      UseCounter::Count(*document_for_count, WebFeature::kBlinkMacSystemFont);
       family_name = FontFamilyNames::system_ui;
     }
 #endif
-  } else if (state.GetDocument().GetSettings()) {
+  } else if (font_builder) {
     generic_family =
         ConvertGenericFamily(ToCSSIdentifierValue(value).GetValueID());
-    family_name = state.GetFontBuilder().GenericFontFamilyName(generic_family);
+    family_name = font_builder->GenericFontFamilyName(generic_family);
   }
 
   return !family_name.IsEmpty();
 }
 
-FontDescription::FamilyDescription StyleBuilderConverter::ConvertFontFamily(
-    StyleResolverState& state,
-    const CSSValue& value) {
+FontDescription::FamilyDescription StyleBuilderConverterBase::ConvertFontFamily(
+    const CSSValue& value,
+    FontBuilder* font_builder,
+    const Document* document_for_count) {
   DCHECK(value.IsValueList());
 
   FontDescription::FamilyDescription desc(FontDescription::kNoFamily);
@@ -221,7 +223,8 @@
         FontDescription::kNoFamily;
     AtomicString family_name;
 
-    if (!ConvertFontFamilyName(state, *family, generic_family, family_name))
+    if (!ConvertFontFamilyName(*family, generic_family, family_name,
+                               font_builder, document_for_count))
       continue;
 
     if (!curr_family) {
@@ -241,6 +244,15 @@
   return desc;
 }
 
+FontDescription::FamilyDescription StyleBuilderConverter::ConvertFontFamily(
+    StyleResolverState& state,
+    const CSSValue& value) {
+  return StyleBuilderConverterBase::ConvertFontFamily(
+      value,
+      state.GetDocument().GetSettings() ? &state.GetFontBuilder() : nullptr,
+      &state.GetDocument());
+}
+
 PassRefPtr<FontFeatureSettings>
 StyleBuilderConverter::ConvertFontFeatureSettings(StyleResolverState& state,
                                                   const CSSValue& value) {
@@ -276,29 +288,24 @@
   return settings;
 }
 
-static float ComputeFontSize(StyleResolverState& state,
+static float ComputeFontSize(const CSSToLengthConversionData& conversion_data,
                              const CSSPrimitiveValue& primitive_value,
                              const FontDescription::Size& parent_size) {
   if (primitive_value.IsLength())
-    return primitive_value.ComputeLength<float>(state.FontSizeConversionData());
+    return primitive_value.ComputeLength<float>(conversion_data);
   if (primitive_value.IsCalculatedPercentageWithLength())
     return primitive_value.CssCalcValue()
-        ->ToCalcValue(state.FontSizeConversionData())
+        ->ToCalcValue(conversion_data)
         ->Evaluate(parent_size.value);
 
   NOTREACHED();
   return 0;
 }
 
-FontDescription::Size StyleBuilderConverter::ConvertFontSize(
-    StyleResolverState& state,
-    const CSSValue& value) {
-  FontDescription::Size parent_size(0, 0.0f, false);
-
-  // FIXME: Find out when parentStyle could be 0?
-  if (state.ParentStyle())
-    parent_size = state.ParentFontDescription().GetSize();
-
+FontDescription::Size StyleBuilderConverterBase::ConvertFontSize(
+    const CSSValue& value,
+    const CSSToLengthConversionData& conversion_data,
+    FontDescription::Size parent_size) {
   if (value.IsIdentifierValue()) {
     CSSValueID value_id = ToCSSIdentifierValue(value).GetValueID();
     if (FontSize::IsValidValueID(value_id))
@@ -312,17 +319,26 @@
     return FontBuilder::InitialSize();
   }
 
-  bool parent_is_absolute_size = state.ParentFontDescription().IsAbsoluteSize();
-
   const CSSPrimitiveValue& primitive_value = ToCSSPrimitiveValue(value);
-  if (primitive_value.IsPercentage())
+  if (primitive_value.IsPercentage()) {
     return FontDescription::Size(
         0, (primitive_value.GetFloatValue() * parent_size.value / 100.0f),
-        parent_is_absolute_size);
+        parent_size.is_absolute);
+  }
 
   return FontDescription::Size(
-      0, ComputeFontSize(state, primitive_value, parent_size),
-      parent_is_absolute_size || !primitive_value.IsFontRelativeLength());
+      0, ComputeFontSize(conversion_data, primitive_value, parent_size),
+      parent_size.is_absolute || !primitive_value.IsFontRelativeLength());
+}
+
+FontDescription::Size StyleBuilderConverter::ConvertFontSize(
+    StyleResolverState& state,
+    const CSSValue& value) {
+  return StyleBuilderConverterBase::ConvertFontSize(
+      value, state.FontSizeConversionData(),
+      // FIXME: Find out when parentStyle could be 0?
+      state.ParentStyle() ? state.ParentFontDescription().GetSize()
+                          : FontDescription::Size(0, 0.0f, false));
 }
 
 float StyleBuilderConverter::ConvertFontSizeAdjust(StyleResolverState& state,
@@ -366,24 +382,28 @@
   }
 }
 
-FontWeight StyleBuilderConverter::ConvertFontWeight(StyleResolverState& state,
-                                                    const CSSValue& value) {
+FontWeight StyleBuilderConverterBase::ConvertFontWeight(
+    const CSSValue& value,
+    FontWeight parent_weight) {
   const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
   switch (identifier_value.GetValueID()) {
     case CSSValueBolder:
-      return FontDescription::BolderWeight(
-          state.ParentStyle()->GetFontDescription().Weight());
+      return FontDescription::BolderWeight(parent_weight);
     case CSSValueLighter:
-      return FontDescription::LighterWeight(
-          state.ParentStyle()->GetFontDescription().Weight());
+      return FontDescription::LighterWeight(parent_weight);
     default:
       return identifier_value.ConvertTo<FontWeight>();
   }
 }
 
-FontDescription::FontVariantCaps StyleBuilderConverter::ConvertFontVariantCaps(
-    StyleResolverState&,
-    const CSSValue& value) {
+FontWeight StyleBuilderConverter::ConvertFontWeight(StyleResolverState& state,
+                                                    const CSSValue& value) {
+  return StyleBuilderConverterBase::ConvertFontWeight(
+      value, state.ParentStyle()->GetFontDescription().Weight());
+}
+
+FontDescription::FontVariantCaps
+StyleBuilderConverterBase::ConvertFontVariantCaps(const CSSValue& value) {
   SECURITY_DCHECK(value.IsIdentifierValue());
   CSSValueID value_id = ToCSSIdentifierValue(value).GetValueID();
   switch (value_id) {
@@ -406,6 +426,12 @@
   }
 }
 
+FontDescription::FontVariantCaps StyleBuilderConverter::ConvertFontVariantCaps(
+    StyleResolverState&,
+    const CSSValue& value) {
+  return StyleBuilderConverterBase::ConvertFontVariantCaps(value);
+}
+
 FontDescription::VariantLigatures
 StyleBuilderConverter::ConvertFontVariantLigatures(StyleResolverState&,
                                                    const CSSValue& value) {
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
index 02b3614..673e0ff 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
@@ -54,6 +54,23 @@
 class TextSizeAdjust;
 class TranslateTransformOperation;
 
+class StyleBuilderConverterBase {
+  STATIC_ONLY(StyleBuilderConverterBase);
+
+ public:
+  static FontWeight ConvertFontWeight(const CSSValue&, FontWeight);
+  static FontDescription::FontVariantCaps ConvertFontVariantCaps(
+      const CSSValue&);
+  static FontDescription::FamilyDescription ConvertFontFamily(
+      const CSSValue&,
+      FontBuilder*,
+      const Document* document_for_count);
+  static FontDescription::Size ConvertFontSize(
+      const CSSValue&,
+      const CSSToLengthConversionData&,
+      FontDescription::Size parent_size);
+};
+
 // Note that we assume the parser only allows valid CSSValue types.
 class StyleBuilderConverter {
   STATIC_ONLY(StyleBuilderConverter);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index cc393cd..aec4122 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1989,6 +1989,9 @@
         rules->at(i)->SelectorList().SelectorsText());
 }
 
+// Font properties are also handled by FontStyleResolver outside the main
+// thread. If you add/remove properties here, make sure they are also properly
+// handled by FontStyleResolver.
 void StyleResolver::ComputeFont(ComputedStyle* style,
                                 const StylePropertySet& property_set) {
   CSSPropertyID properties[] = {
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 7373851b..018d32e 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -1234,7 +1234,7 @@
   // FIXME: Handle table/inline-table with a caption.
   if (element_layout_object->IsBoxModelObject() ||
       element_layout_object->IsBR())
-    element_layout_object->AbsoluteQuads(quads);
+    element_layout_object->AbsoluteQuads(quads, kUseTransforms);
 }
 
 ClientRectList* Element::getClientRects() {
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
index 7523950..e4f398b9 100644
--- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
@@ -235,9 +235,10 @@
   client_->CountFeature(static_cast<uint32_t>(feature));
 }
 
-void WebSharedWorkerImpl::PostMessageToPageInspector(const String& message) {
+void WebSharedWorkerImpl::PostMessageToPageInspector(int session_id,
+                                                     const String& message) {
   DCHECK(IsMainThread());
-  worker_inspector_proxy_->DispatchMessageFromWorker(message);
+  worker_inspector_proxy_->DispatchMessageFromWorker(session_id, message);
 }
 
 void WebSharedWorkerImpl::DidCloseWorkerGlobalScope() {
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.h b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.h
index 0d73710..a5508c3d 100644
--- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.h
@@ -114,7 +114,7 @@
 
   // Callback methods for SharedWorkerReportingProxy.
   void CountFeature(WebFeature);
-  void PostMessageToPageInspector(const String& message);
+  void PostMessageToPageInspector(int session_id, const String& message);
   void DidCloseWorkerGlobalScope();
   void DidTerminateWorkerThread();
 
diff --git a/third_party/WebKit/Source/core/fileapi/FileReaderLoader.cpp b/third_party/WebKit/Source/core/fileapi/FileReaderLoader.cpp
index 2a81b7dd..0162edd 100644
--- a/third_party/WebKit/Source/core/fileapi/FileReaderLoader.cpp
+++ b/third_party/WebKit/Source/core/fileapi/FileReaderLoader.cpp
@@ -365,9 +365,11 @@
   // override the provided encoding.
   // FIXME: consider supporting incremental decoding to improve the perf.
   StringBuilder builder;
-  if (!decoder_)
+  if (!decoder_) {
     decoder_ = TextResourceDecoder::Create(
-        "text/plain", encoding_.IsValid() ? encoding_ : UTF8Encoding());
+        TextResourceDecoder::kPlainTextContent,
+        encoding_.IsValid() ? encoding_ : UTF8Encoding());
+  }
   builder.Append(decoder_->Decode(static_cast<const char*>(raw_data_->Data()),
                                   raw_data_->ByteLength()));
 
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index 06633f0ff..9a010b9c 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -3485,21 +3485,29 @@
 void HTMLMediaElement::DidEnterFullscreen() {
   UpdateControlsVisibility();
 
-  // FIXME: There is no embedder-side handling in layout test mode.
-  if (GetWebMediaPlayer() && !LayoutTestSupport::IsRunningLayoutTest())
-    GetWebMediaPlayer()->EnteredFullscreen();
+  if (web_media_player_) {
+    // FIXME: There is no embedder-side handling in layout test mode.
+    if (!LayoutTestSupport::IsRunningLayoutTest())
+      web_media_player_->EnteredFullscreen();
+    web_media_player_->OnDisplayTypeChanged(DisplayType());
+  }
+
   // Cache this in case the player is destroyed before leaving fullscreen.
   in_overlay_fullscreen_video_ = UsesOverlayFullscreenVideo();
-  if (in_overlay_fullscreen_video_)
+  if (in_overlay_fullscreen_video_) {
     GetDocument().GetLayoutViewItem().Compositor()->SetNeedsCompositingUpdate(
         kCompositingUpdateRebuildTree);
+  }
 }
 
 void HTMLMediaElement::DidExitFullscreen() {
   UpdateControlsVisibility();
 
-  if (GetWebMediaPlayer())
+  if (GetWebMediaPlayer()) {
     GetWebMediaPlayer()->ExitedFullscreen();
+    GetWebMediaPlayer()->OnDisplayTypeChanged(DisplayType());
+  }
+
   if (in_overlay_fullscreen_video_)
     GetDocument().GetLayoutViewItem().Compositor()->SetNeedsCompositingUpdate(
         kCompositingUpdateRebuildTree);
@@ -4084,6 +4092,11 @@
   return ShouldShowControls(RecordMetricsBehavior::kDoRecord);
 }
 
+WebMediaPlayer::DisplayType HTMLMediaElement::DisplayType() const {
+  return IsFullscreen() ? WebMediaPlayer::DisplayType::kFullscreen
+                        : WebMediaPlayer::DisplayType::kInline;
+}
+
 void HTMLMediaElement::CheckViewportIntersectionTimerFired(TimerBase*) {
   bool should_report_root_bounds = true;
   IntersectionGeometry geometry(nullptr, *this, Vector<Length>(),
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.h b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
index f29eaca5..4154c9d 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.h
@@ -420,6 +420,7 @@
   bool IsAutoplayingMuted() final;
   void ActivateViewportIntersectionMonitoring(bool) final;
   bool HasNativeControls() final;
+  WebMediaPlayer::DisplayType DisplayType() const override;
 
   void LoadTimerFired(TimerBase*);
   void ProgressEventTimerFired(TimerBase*);
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
index 5e07ff3..49f93b2 100644
--- a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
@@ -243,6 +243,8 @@
 // TODO(zqzhang): this callback could be used to hide native controls instead of
 // using a settings. See `HTMLMediaElement::onMediaControlsEnabledChange`.
 void HTMLVideoElement::OnBecamePersistentVideo(bool value) {
+  is_picture_in_picture_ = value;
+
   if (value) {
     // Record the type of video. If it is already fullscreen, it is a video with
     // native controls, otherwise it is assumed to be with custom controls.
@@ -290,6 +292,9 @@
     if (fullscreen_element)
       fullscreen_element->SetContainsPersistentVideo(false);
   }
+
+  if (GetWebMediaPlayer())
+    GetWebMediaPlayer()->OnDisplayTypeChanged(DisplayType());
 }
 
 bool HTMLVideoElement::IsPersistent() const {
@@ -521,6 +526,12 @@
   remoting_interstitial_->Hide();
 }
 
+WebMediaPlayer::DisplayType HTMLVideoElement::DisplayType() const {
+  if (is_picture_in_picture_)
+    return WebMediaPlayer::DisplayType::kPictureInPicture;
+  return HTMLMediaElement::DisplayType();
+}
+
 void HTMLVideoElement::DisableMediaRemoting() {
   media_remoting_status_ = MediaRemotingStatus::kDisabled;
   if (GetWebMediaPlayer())
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.h b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
index 99fe901..4969b434 100644
--- a/third_party/WebKit/Source/core/html/HTMLVideoElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
@@ -147,6 +147,7 @@
 
   void MediaRemotingStarted() final;
   void MediaRemotingStopped() final;
+  WebMediaPlayer::DisplayType DisplayType() const final;
 
  private:
   friend class MediaCustomControlsFullscreenDetectorTest;
@@ -183,7 +184,12 @@
 
   AtomicString default_poster_url_;
 
+  // TODO(mlamouri): merge these later. At the moment, the former is used for
+  // CSS rules used to hide the custom controls and the latter is used to report
+  // the display type. It's unclear whether using the CSS rules also when native
+  // controls are used would or would not have side effects.
   bool is_persistent_ = false;
+  bool is_picture_in_picture_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp
index ed0100e..918ada4 100644
--- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp
+++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.cpp
@@ -117,17 +117,6 @@
   return WTF::TextEncoding(buffer.data());
 }
 
-TextResourceDecoder::ContentType TextResourceDecoder::DetermineContentType(
-    const String& mime_type) {
-  if (DeprecatedEqualIgnoringCase(mime_type, "text/css"))
-    return kCSSContent;
-  if (DeprecatedEqualIgnoringCase(mime_type, "text/html"))
-    return kHTMLContent;
-  if (DOMImplementation::IsXMLMIMEType(mime_type))
-    return kXMLContent;
-  return kPlainTextContent;
-}
-
 const WTF::TextEncoding& TextResourceDecoder::DefaultEncoding(
     ContentType content_type,
     const WTF::TextEncoding& specified_default_encoding) {
@@ -141,11 +130,11 @@
 }
 
 TextResourceDecoder::TextResourceDecoder(
-    const String& mime_type,
+    ContentType content_type,
     const WTF::TextEncoding& specified_default_encoding,
     EncodingDetectionOption encoding_detection_option,
     const KURL& hint_url)
-    : content_type_(DetermineContentType(mime_type)),
+    : content_type_(content_type),
       encoding_(DefaultEncoding(content_type_, specified_default_encoding)),
       source_(kDefaultEncoding),
       hint_encoding_(0),
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h
index 7963841..f88fa47 100644
--- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h
+++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoder.h
@@ -49,26 +49,35 @@
     kEncodingFromParentFrame
   };
 
+  enum ContentType {
+    kPlainTextContent,
+    kHTMLContent,
+    kXMLContent,
+    kCSSContent,
+    kMaxContentType = kCSSContent
+  };  // PlainText only checks for BOM.
+
   static std::unique_ptr<TextResourceDecoder> Create(
-      const String& mime_type,
+      ContentType content_type,
       const WTF::TextEncoding& default_encoding = WTF::TextEncoding()) {
-    return WTF::WrapUnique(new TextResourceDecoder(
-        mime_type, default_encoding, kUseContentAndBOMBasedDetection, KURL()));
+    return WTF::WrapUnique(
+        new TextResourceDecoder(content_type, default_encoding,
+                                kUseContentAndBOMBasedDetection, KURL()));
   }
 
   static std::unique_ptr<TextResourceDecoder> CreateWithAutoDetection(
-      const String& mime_type,
+      ContentType content_type,
       const WTF::TextEncoding& default_encoding,
       const KURL& url) {
-    return WTF::WrapUnique(new TextResourceDecoder(mime_type, default_encoding,
-                                                   kUseAllAutoDetection, url));
+    return WTF::WrapUnique(new TextResourceDecoder(
+        content_type, default_encoding, kUseAllAutoDetection, url));
   }
 
   // Corresponds to utf-8 decode in Encoding spec:
   // https://encoding.spec.whatwg.org/#utf-8-decode.
   static std::unique_ptr<TextResourceDecoder> CreateAlwaysUseUTF8ForText() {
     return WTF::WrapUnique(new TextResourceDecoder(
-        "plain/text", UTF8Encoding(), kAlwaysUseUTF8ForText, KURL()));
+        kPlainTextContent, UTF8Encoding(), kAlwaysUseUTF8ForText, KURL()));
   }
   ~TextResourceDecoder();
 
@@ -111,19 +120,12 @@
     kAlwaysUseUTF8ForText
   };
 
-  TextResourceDecoder(const String& mime_type,
+  TextResourceDecoder(ContentType,
                       const WTF::TextEncoding& default_encoding,
                       EncodingDetectionOption,
                       const KURL& hint_url);
 
  private:
-  enum ContentType {
-    kPlainTextContent,
-    kHTMLContent,
-    kXMLContent,
-    kCSSContent
-  };  // PlainText only checks for BOM.
-  static ContentType DetermineContentType(const String& mime_type);
   static const WTF::TextEncoding& DefaultEncoding(
       ContentType,
       const WTF::TextEncoding& default_encoding);
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h
index 3f6d8c0..5b3c0b8 100644
--- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h
+++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderForFuzzing.h
@@ -15,21 +15,18 @@
 
 class TextResourceDecoderForFuzzing : public TextResourceDecoder {
  public:
-  // Note: mimeTypes can be quite long and still valid for XML. See the
-  // comment in DOMImplementation.cpp which says:
-  // Per RFCs 3023 and 2045, an XML MIME type is of the form:
-  // ^[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+/[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+\+xml$
-  //
-  // Similarly, charsets can be long too (see the various encodings in
-  // wtf/text). For instance: "unicode-1-1-utf-8". To ensure good coverage,
-  // set a generous max limit for these sizes (32 bytes should be good).
+  // Note: Charsets can be long (see the various encodings in wtf/text). For
+  // instance: "unicode-1-1-utf-8". To ensure good coverage, set a generous max
+  // limit for these sizes (32 bytes should be good).
   TextResourceDecoderForFuzzing(FuzzedDataProvider& fuzzed_data)
-      : TextResourceDecoder(
-            String::FromUTF8(fuzzed_data.ConsumeBytesInRange(0, 32)),
-            WTF::TextEncoding(
-                String::FromUTF8(fuzzed_data.ConsumeBytesInRange(0, 32))),
-            FuzzedOption(fuzzed_data),
-            KURL()) {}
+      : TextResourceDecoder(static_cast<TextResourceDecoder::ContentType>(
+                                fuzzed_data.ConsumeInt32InRange(
+                                    TextResourceDecoder::kPlainTextContent,
+                                    TextResourceDecoder::kMaxContentType)),
+                            WTF::TextEncoding(String::FromUTF8(
+                                fuzzed_data.ConsumeBytesInRange(0, 32))),
+                            FuzzedOption(fuzzed_data),
+                            KURL()) {}
 
  private:
   static TextResourceDecoder::EncodingDetectionOption FuzzedOption(
diff --git a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderTest.cpp b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderTest.cpp
index ebb420b..84f6e54 100644
--- a/third_party/WebKit/Source/core/html/parser/TextResourceDecoderTest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/TextResourceDecoderTest.cpp
@@ -8,15 +8,9 @@
 
 namespace blink {
 
-namespace {
-
-const char kUTF16TextMimeType[] = "text/plain; charset=utf-16";
-
-}  // namespace
-
 TEST(TextResourceDecoderTest, BasicUTF16) {
   std::unique_ptr<TextResourceDecoder> decoder =
-      TextResourceDecoder::Create(kUTF16TextMimeType);
+      TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent);
   WTF::String decoded;
 
   const unsigned char kFooLE[] = {0xff, 0xfe, 0x66, 0x00,
@@ -26,7 +20,7 @@
   decoded = decoded + decoder->Flush();
   EXPECT_EQ("foo", decoded);
 
-  decoder = TextResourceDecoder::Create(kUTF16TextMimeType);
+  decoder = TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent);
   const unsigned char kFooBE[] = {0xfe, 0xff, 0x00, 0x66,
                                   0x00, 0x6f, 0x00, 0x6f};
   decoded =
@@ -37,7 +31,7 @@
 
 TEST(TextResourceDecoderTest, UTF16Pieces) {
   std::unique_ptr<TextResourceDecoder> decoder =
-      TextResourceDecoder::Create(kUTF16TextMimeType);
+      TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent);
 
   WTF::String decoded;
   const unsigned char kFoo[] = {0xff, 0xfe, 0x66, 0x00, 0x6f, 0x00, 0x6f, 0x00};
diff --git a/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp b/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp
index d2559e9..1a67319 100644
--- a/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp
+++ b/third_party/WebKit/Source/core/html/track/vtt/VTTParser.cpp
@@ -82,7 +82,9 @@
 VTTParser::VTTParser(VTTParserClient* client, Document& document)
     : document_(&document),
       state_(kInitial),
-      decoder_(TextResourceDecoder::Create("text/plain", UTF8Encoding())),
+      decoder_(
+          TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                      UTF8Encoding())),
       current_start_time_(0),
       current_end_time_(0),
       client_(client) {}
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index 6f98e31..6c45055 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -143,22 +143,26 @@
     const String& mime_type,
     const String& text_encoding_name) {
   if (!text_encoding_name.IsEmpty()) {
-    return TextResourceDecoder::Create("text/plain",
+    return TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
                                        WTF::TextEncoding(text_encoding_name));
   }
   if (DOMImplementation::IsXMLMIMEType(mime_type)) {
     std::unique_ptr<TextResourceDecoder> decoder =
-        TextResourceDecoder::Create("application/xml");
+        TextResourceDecoder::Create(TextResourceDecoder::kXMLContent);
     decoder->UseLenientXMLDecoding();
     return decoder;
   }
-  if (DeprecatedEqualIgnoringCase(mime_type, "text/html"))
-    return TextResourceDecoder::Create("text/html", UTF8Encoding());
+  if (DeprecatedEqualIgnoringCase(mime_type, "text/html")) {
+    return TextResourceDecoder::Create(TextResourceDecoder::kHTMLContent,
+                                       UTF8Encoding());
+  }
   if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) ||
-      DOMImplementation::IsJSONMIMEType(mime_type))
-    return TextResourceDecoder::Create("text/plain", UTF8Encoding());
+      DOMImplementation::IsJSONMIMEType(mime_type)) {
+    return TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                       UTF8Encoding());
+  }
   if (DOMImplementation::IsTextMIMEType(mime_type)) {
-    return TextResourceDecoder::Create("text/plain",
+    return TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
                                        WTF::TextEncoding("ISO-8859-1"));
   }
   return std::unique_ptr<TextResourceDecoder>();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp
index 9c5c332..fead904 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.cpp
@@ -46,6 +46,11 @@
 static const char kAttachedWorkerIds[] = "attachedWorkerIds";
 };
 
+namespace {
+// TODO(dgozman): support multiple sessions in protocol.
+static const int kSessionId = 1;
+}  // namespace
+
 InspectorWorkerAgent::InspectorWorkerAgent(InspectedFrames* inspected_frames)
     : inspected_frames_(inspected_frames) {}
 
@@ -104,16 +109,17 @@
   WorkerInspectorProxy* proxy = connected_proxies_.at(target_id);
   if (!proxy)
     return Response::Error("Not attached to a target with given id");
-  proxy->SendMessageToInspector(message);
+  proxy->SendMessageToInspector(kSessionId, message);
   return Response::OK();
 }
 
-void InspectorWorkerAgent::SetTracingSessionId(const String& session_id) {
-  tracing_session_id_ = session_id;
-  if (session_id.IsEmpty())
+void InspectorWorkerAgent::SetTracingSessionId(
+    const String& tracing_session_id) {
+  tracing_session_id_ = tracing_session_id;
+  if (tracing_session_id.IsEmpty())
     return;
   for (auto& id_proxy : connected_proxies_)
-    id_proxy.value->WriteTimelineStartedEvent(session_id);
+    id_proxy.value->WriteTimelineStartedEvent(tracing_session_id);
 }
 
 void InspectorWorkerAgent::ShouldWaitForDebuggerOnWorkerStart(bool* result) {
@@ -136,7 +142,7 @@
     return;
   AttachedWorkerIds()->remove(proxy->InspectorId());
   GetFrontend()->detachedFromTarget(proxy->InspectorId());
-  proxy->DisconnectFromInspector(this);
+  proxy->DisconnectFromInspector(kSessionId, this);
   connected_proxies_.erase(proxy->InspectorId());
 }
 
@@ -157,7 +163,7 @@
       AttachedWorkerIds()->remove(id_proxy.key);
       GetFrontend()->detachedFromTarget(id_proxy.key);
     }
-    id_proxy.value->DisconnectFromInspector(this);
+    id_proxy.value->DisconnectFromInspector(kSessionId, this);
   }
   connected_proxies_.clear();
 }
@@ -172,7 +178,7 @@
   for (auto& id_proxy : connected_proxies_) {
     AttachedWorkerIds()->remove(id_proxy.key);
     GetFrontend()->detachedFromTarget(id_proxy.key);
-    id_proxy.value->DisconnectFromInspector(this);
+    id_proxy.value->DisconnectFromInspector(kSessionId, this);
   }
   connected_proxies_.clear();
 }
@@ -192,7 +198,7 @@
 void InspectorWorkerAgent::ConnectToProxy(WorkerInspectorProxy* proxy,
                                           bool waiting_for_debugger) {
   connected_proxies_.Set(proxy->InspectorId(), proxy);
-  proxy->ConnectToInspector(this);
+  proxy->ConnectToInspector(kSessionId, this);
   DCHECK(GetFrontend());
   AttachedWorkerIds()->setBoolean(proxy->InspectorId(), true);
   GetFrontend()->attachedToTarget(protocol::Target::TargetInfo::create()
@@ -206,7 +212,9 @@
 
 void InspectorWorkerAgent::DispatchMessageFromWorker(
     WorkerInspectorProxy* proxy,
+    int session_id,
     const String& message) {
+  DCHECK(session_id == kSessionId);
   GetFrontend()->receivedMessageFromTarget(proxy->InspectorId(), message);
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h
index 28d0109c..e7a4ce7 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorWorkerAgent.h
@@ -79,6 +79,7 @@
 
   // WorkerInspectorProxy::PageInspector implementation.
   void DispatchMessageFromWorker(WorkerInspectorProxy*,
+                                 int session_id,
                                  const String& message) override;
 
   Member<InspectedFrames> inspected_frames_;
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
index bb020d7..08f91c4 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -61,46 +61,53 @@
   DCHECK(!thread_);
 }
 
-void WorkerInspectorController::ConnectFrontend() {
-  if (session_)
+void WorkerInspectorController::ConnectFrontend(int session_id) {
+  if (sessions_.find(session_id) != sessions_.end())
     return;
 
-  // sessionId will be overwritten by WebDevToolsAgent::sendProtocolNotification
-  // call.
-  session_ = new InspectorSession(this, probe_sink_.Get(), 0,
-                                  debugger_->GetV8Inspector(),
-                                  debugger_->ContextGroupId(thread_), nullptr);
-  session_->Append(
+  InspectorSession* session = new InspectorSession(
+      this, probe_sink_.Get(), session_id, debugger_->GetV8Inspector(),
+      debugger_->ContextGroupId(thread_), nullptr);
+  session->Append(
       new InspectorLogAgent(thread_->GetConsoleMessageStorage(), nullptr));
-  thread_->GetWorkerBackingThread().BackingThread().AddTaskObserver(this);
+  if (sessions_.IsEmpty())
+    thread_->GetWorkerBackingThread().BackingThread().AddTaskObserver(this);
+  sessions_.insert(session_id, session);
 }
 
-void WorkerInspectorController::DisconnectFrontend() {
-  if (!session_)
+void WorkerInspectorController::DisconnectFrontend(int session_id) {
+  auto it = sessions_.find(session_id);
+  if (it == sessions_.end())
     return;
-  session_->Dispose();
-  session_.Clear();
-  thread_->GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
+  it->value->Dispose();
+  sessions_.erase(it);
+  if (sessions_.IsEmpty())
+    thread_->GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
 }
 
 void WorkerInspectorController::DispatchMessageFromFrontend(
+    int session_id,
     const String& message) {
-  if (!session_)
+  auto it = sessions_.find(session_id);
+  if (it == sessions_.end())
     return;
   String method;
   if (!protocol::DispatcherBase::getCommandName(message, &method))
     return;
-  session_->DispatchProtocolMessage(method, message);
+  it->value->DispatchProtocolMessage(method, message);
 }
 
 void WorkerInspectorController::Dispose() {
-  DisconnectFrontend();
+  Vector<int> ids;
+  CopyKeysToVector(sessions_, ids);
+  for (int session_id : ids)
+    DisconnectFrontend(session_id);
   thread_ = nullptr;
 }
 
 void WorkerInspectorController::FlushProtocolNotifications() {
-  if (session_)
-    session_->flushProtocolNotifications();
+  for (auto& it : sessions_)
+    it.value->flushProtocolNotifications();
 }
 
 void WorkerInspectorController::SendProtocolMessage(int session_id,
@@ -108,19 +115,20 @@
                                                     const String& response,
                                                     const String& state) {
   // Worker messages are wrapped, no need to handle callId or state.
-  thread_->GetWorkerReportingProxy().PostMessageToPageInspector(response);
+  thread_->GetWorkerReportingProxy().PostMessageToPageInspector(session_id,
+                                                                response);
 }
 
 void WorkerInspectorController::WillProcessTask() {}
 
 void WorkerInspectorController::DidProcessTask() {
-  if (session_)
-    session_->flushProtocolNotifications();
+  for (auto& it : sessions_)
+    it.value->flushProtocolNotifications();
 }
 
 DEFINE_TRACE(WorkerInspectorController) {
   visitor->Trace(probe_sink_);
-  visitor->Trace(session_);
+  visitor->Trace(sessions_);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
index ee4ca40..b13c7bc 100644
--- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
+++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
@@ -35,6 +35,7 @@
 #include "core/inspector/InspectorTaskRunner.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Forward.h"
+#include "platform/wtf/HashMap.h"
 #include "platform/wtf/Noncopyable.h"
 #include "platform/wtf/RefPtr.h"
 #include "public/platform/WebThread.h"
@@ -58,9 +59,9 @@
 
   CoreProbeSink* GetProbeSink() const { return probe_sink_.Get(); }
 
-  void ConnectFrontend();
-  void DisconnectFrontend();
-  void DispatchMessageFromFrontend(const String&);
+  void ConnectFrontend(int session_id);
+  void DisconnectFrontend(int session_id);
+  void DispatchMessageFromFrontend(int session_id, const String& message);
   void Dispose();
   void FlushProtocolNotifications();
 
@@ -80,7 +81,7 @@
   WorkerThreadDebugger* debugger_;
   WorkerThread* thread_;
   Member<CoreProbeSink> probe_sink_;
-  Member<InspectorSession> session_;
+  HeapHashMap<int, Member<InspectorSession>> sessions_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
index 5c28245..fa43ddc9 100644
--- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
+++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -46,7 +46,7 @@
     FloatClipRect geometry_mapper_rect((FloatRect(local_rect)));
     if (object.PaintProperties() || object.LocalBorderBoxProperties()) {
       geometry_mapper_rect.MoveBy(FloatPoint(object.PaintOffset()));
-      GeometryMapper::SourceToDestinationVisualRect(
+      GeometryMapper::LocalToAncestorVisualRect(
           *object.LocalBorderBoxProperties(), ancestor.ContentsProperties(),
           geometry_mapper_rect);
       geometry_mapper_rect.MoveBy(-FloatPoint(ancestor.PaintOffset()));
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
index f0f2bcd..aa69d04 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -76,11 +76,17 @@
   DCHECK(layout_box->IsFloating());
 
   if (parent && parent->IsLayoutBlockFlow()) {
+    LayoutBlockFlow& containing_block = *ToLayoutBlockFlow(parent);
     FloatingObject* floating_object =
-        ToLayoutBlockFlow(parent)->InsertFloatingObject(*layout_box);
+        containing_block.InsertFloatingObject(*layout_box);
     floating_object->SetIsInPlacedTree(false);
-    floating_object->SetX(positioned_float.paint_offset.left);
-    floating_object->SetY(positioned_float.paint_offset.top);
+    LayoutUnit logical_left = positioned_float.paint_offset.inline_offset;
+    LayoutUnit logical_top = positioned_float.paint_offset.block_offset;
+    // Update floating_object's logical left and top position (which is the same
+    // as inline and block offset). Note that this does not update the actual
+    // LayoutObject established by the float, just the FloatingObject.
+    containing_block.SetLogicalLeftForFloat(*floating_object, logical_left);
+    containing_block.SetLogicalTopForFloat(*floating_object, logical_top);
     floating_object->SetIsPlaced(true);
     floating_object->SetIsInPlacedTree(true);
   }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
index 9fb6d23..44b48823 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_floats_utils.cc
@@ -89,20 +89,19 @@
   return exclusion;
 }
 
-// Updates the Floating Object's left and top offsets.
-NGPhysicalOffset CalculateFloatingObjectPaintOffset(
+// Updates the Floating object's offsets.
+NGLogicalOffset CalculateFloatingObjectPaintOffset(
     const NGConstraintSpace& new_parent_space,
     const NGLogicalOffset& float_logical_offset,
     const NGUnpositionedFloat& unpositioned_float) {
-  // TODO(glebl): We should use physical offset here.
-  LayoutUnit left_offset = unpositioned_float.from_offset.inline_offset -
-                           new_parent_space.BfcOffset().inline_offset +
-                           float_logical_offset.inline_offset;
+  LayoutUnit inline_offset = unpositioned_float.from_offset.inline_offset -
+                             new_parent_space.BfcOffset().inline_offset +
+                             float_logical_offset.inline_offset;
   DCHECK(unpositioned_float.parent_bfc_block_offset);
-  LayoutUnit top_offset = unpositioned_float.from_offset.block_offset -
-                          unpositioned_float.parent_bfc_block_offset.value() +
-                          float_logical_offset.block_offset;
-  return {left_offset, top_offset};
+  LayoutUnit block_offset = unpositioned_float.from_offset.block_offset -
+                            unpositioned_float.parent_bfc_block_offset.value() +
+                            float_logical_offset.block_offset;
+  return {inline_offset, block_offset};
 }
 
 WTF::Optional<LayoutUnit> CalculateFragmentationOffset(
@@ -270,7 +269,7 @@
 
   NGLogicalOffset logical_offset = CalculateLogicalOffsetForOpportunity(
       opportunity, float_offset, unpositioned_float);
-  NGPhysicalOffset paint_offset = CalculateFloatingObjectPaintOffset(
+  NGLogicalOffset paint_offset = CalculateFloatingObjectPaintOffset(
       *new_parent_space, logical_offset, *unpositioned_float);
 
   return NGPositionedFloat(std::move(physical_fragment), logical_offset,
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_positioned_float.h b/third_party/WebKit/Source/core/layout/ng/ng_positioned_float.h
index addcf46..79e2ebb0 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_positioned_float.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_positioned_float.h
@@ -6,6 +6,7 @@
 #define NGPositionedFloat_h
 
 #include "core/CoreExport.h"
+#include "core/layout/ng/geometry/ng_logical_offset.h"
 
 namespace blink {
 
@@ -15,7 +16,7 @@
 struct CORE_EXPORT NGPositionedFloat {
   NGPositionedFloat(RefPtr<NGPhysicalBoxFragment> fragment,
                     const NGLogicalOffset& logical_offset,
-                    const NGPhysicalOffset& paint_offset)
+                    const NGLogicalOffset& paint_offset)
       : fragment(fragment),
         logical_offset(logical_offset),
         paint_offset(paint_offset) {}
@@ -30,7 +31,7 @@
   // parent.
   // {@code paint_offset} is calculated when we know to which parent this float
   // would be attached.
-  NGPhysicalOffset paint_offset;
+  NGLogicalOffset paint_offset;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp b/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp
index a71f775..2fe7d76 100644
--- a/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp
+++ b/third_party/WebKit/Source/core/loader/TextResourceDecoderBuilder.cpp
@@ -86,6 +86,16 @@
   return WTF::TextEncoding();
 }
 
+TextResourceDecoder::ContentType DetermineContentType(const String& mime_type) {
+  if (DeprecatedEqualIgnoringCase(mime_type, "text/css"))
+    return TextResourceDecoder::kCSSContent;
+  if (DeprecatedEqualIgnoringCase(mime_type, "text/html"))
+    return TextResourceDecoder::kHTMLContent;
+  if (DOMImplementation::IsXMLMIMEType(mime_type))
+    return TextResourceDecoder::kXMLContent;
+  return TextResourceDecoder::kPlainTextContent;
+}
+
 }  // namespace
 
 TextResourceDecoderBuilder::TextResourceDecoderBuilder(
@@ -107,14 +117,17 @@
               : WTF::TextEncoding(settings->GetDefaultTextEncodingName());
       // Disable autodetection for XML to honor the default encoding (UTF-8) for
       // unlabelled documents.
-      if (DOMImplementation::IsXMLMIMEType(mime_type_))
-        return TextResourceDecoder::Create(mime_type_, hint_encoding);
+      if (DOMImplementation::IsXMLMIMEType(mime_type_)) {
+        return TextResourceDecoder::Create(TextResourceDecoder::kXMLContent,
+                                           hint_encoding);
+      }
       return TextResourceDecoder::CreateWithAutoDetection(
-          mime_type_, hint_encoding, document->Url());
+          DetermineContentType(mime_type_), hint_encoding, document->Url());
     }
   }
 
-  return TextResourceDecoder::Create(mime_type_, encoding_from_domain);
+  return TextResourceDecoder::Create(DetermineContentType(mime_type_),
+                                     encoding_from_domain);
 }
 
 inline void TextResourceDecoderBuilder::SetupEncoding(
diff --git a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
index 05866e82..380eec13 100644
--- a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
@@ -69,7 +69,7 @@
     : StyleSheetResource(resource_request,
                          kCSSStyleSheet,
                          options,
-                         "text/css",
+                         TextResourceDecoder::kCSSContent,
                          charset),
       did_notify_first_data_(false) {}
 
diff --git a/third_party/WebKit/Source/core/loader/resource/DocumentResource.cpp b/third_party/WebKit/Source/core/loader/resource/DocumentResource.cpp
index a6941fc..e80640e 100644
--- a/third_party/WebKit/Source/core/loader/resource/DocumentResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/DocumentResource.cpp
@@ -42,7 +42,11 @@
 DocumentResource::DocumentResource(const ResourceRequest& request,
                                    Type type,
                                    const ResourceLoaderOptions& options)
-    : TextResource(request, type, options, "application/xml", String()) {
+    : TextResource(request,
+                   type,
+                   options,
+                   TextResourceDecoder::kXMLContent,
+                   String()) {
   // FIXME: We'll support more types to support HTMLImports.
   DCHECK_EQ(type, kSVGDocument);
 }
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
index 275ea24..cc819e0 100644
--- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
@@ -55,7 +55,7 @@
     : TextResource(resource_request,
                    kScript,
                    options,
-                   "application/javascript",
+                   TextResourceDecoder::kPlainTextContent,
                    charset) {}
 
 ScriptResource::~ScriptResource() {}
diff --git a/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h b/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h
index e7a690b..1653c45 100644
--- a/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h
+++ b/third_party/WebKit/Source/core/loader/resource/StyleSheetResource.h
@@ -45,9 +45,9 @@
   StyleSheetResource(const ResourceRequest& request,
                      Type type,
                      const ResourceLoaderOptions& options,
-                     const String& mime_type,
+                     TextResourceDecoder::ContentType content_type,
                      const String& charset)
-      : TextResource(request, type, options, mime_type, charset) {}
+      : TextResource(request, type, options, content_type, charset) {}
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/resource/TextResource.cpp b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp
index 04f9652..91d4a814 100644
--- a/third_party/WebKit/Source/core/loader/resource/TextResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/TextResource.cpp
@@ -13,11 +13,11 @@
 TextResource::TextResource(const ResourceRequest& resource_request,
                            Resource::Type type,
                            const ResourceLoaderOptions& options,
-                           const String& mime_type,
+                           TextResourceDecoder::ContentType content_type,
                            const String& charset)
     : Resource(resource_request, type, options),
-      decoder_(
-          TextResourceDecoder::Create(mime_type, WTF::TextEncoding(charset))) {}
+      decoder_(TextResourceDecoder::Create(content_type,
+                                           WTF::TextEncoding(charset))) {}
 
 TextResource::~TextResource() {}
 
diff --git a/third_party/WebKit/Source/core/loader/resource/TextResource.h b/third_party/WebKit/Source/core/loader/resource/TextResource.h
index dceb5c95c..8ba18c6 100644
--- a/third_party/WebKit/Source/core/loader/resource/TextResource.h
+++ b/third_party/WebKit/Source/core/loader/resource/TextResource.h
@@ -5,9 +5,10 @@
 #ifndef TextResource_h
 #define TextResource_h
 
-#include "core/CoreExport.h"
-#include "platform/loader/fetch/Resource.h"
 #include <memory>
+#include "core/CoreExport.h"
+#include "core/html/parser/TextResourceDecoder.h"
+#include "platform/loader/fetch/Resource.h"
 
 namespace blink {
 
@@ -27,7 +28,7 @@
   TextResource(const ResourceRequest&,
                Type,
                const ResourceLoaderOptions&,
-               const String& mime_type,
+               TextResourceDecoder::ContentType,
                const String& charset);
   ~TextResource() override;
 
diff --git a/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp b/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
index f222f060..b7c08df 100644
--- a/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
@@ -75,7 +75,7 @@
     : StyleSheetResource(resource_request,
                          kXSLStyleSheet,
                          options,
-                         "text/xsl",
+                         TextResourceDecoder::kXMLContent,
                          charset) {}
 
 void XSLStyleSheetResource::DidAddClient(ResourceClient* c) {
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
index 1e9b5af5..cdeb6df 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
@@ -126,7 +126,7 @@
           context.tree_builder_context_->current.clip, nullptr);
 
       FloatClipRect float_rect((FloatRect(rect)));
-      GeometryMapper::SourceToDestinationVisualRect(
+      GeometryMapper::LocalToAncestorVisualRect(
           current_tree_state, container_contents_properties, float_rect);
       result = LayoutRect(float_rect.Rect());
     }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
index 3a703ca..238cf7c9d 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipper.cpp
@@ -458,12 +458,12 @@
   if (HasOverflowClip(layer_)) {
     FloatClipRect clip_rect((FloatRect(LocalVisualRect())));
     clip_rect.MoveBy(FloatPoint(layer_.GetLayoutObject().PaintOffset()));
-    GeometryMapper::SourceToDestinationVisualRect(
+    GeometryMapper::LocalToAncestorVisualRect(
         source_property_tree_state, destination_property_tree_state, clip_rect);
     output.SetRect(clip_rect);
   } else {
     const FloatClipRect& clipped_rect_in_root_layer_space =
-        GeometryMapper::SourceToDestinationClipRect(
+        GeometryMapper::LocalToAncestorClipRect(
             source_property_tree_state, destination_property_tree_state);
     output.SetRect(clipped_rect_in_root_layer_space);
   }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 4e0b191..f3ec46e9 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -87,7 +87,7 @@
       source.MoveBy((source_object)->PaintOffset());                           \
       auto contents_properties = (ancestor)->ContentsProperties();             \
       FloatClipRect actual_float_rect((FloatRect(source)));                    \
-      GeometryMapper::SourceToDestinationVisualRect(                           \
+      GeometryMapper::LocalToAncestorVisualRect(                               \
           *(source_object)->LocalBorderBoxProperties(), contents_properties,   \
           actual_float_rect);                                                  \
       LayoutRect actual(actual_float_rect.Rect());                             \
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
index 9ac62480..7aade4d 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -140,7 +140,7 @@
   PropertyTreeState local_state(context.transform, context.clip, effect);
 
   const auto& clip_rect =
-      GeometryMapper::SourceToDestinationClipRect(local_state, ancestor_state);
+      GeometryMapper::LocalToAncestorClipRect(local_state, ancestor_state);
   // HasRadius() is ignored because it doesn't affect descendants' visual rects.
   LayoutRect result(clip_rect.Rect());
   if (!clip_rect.IsInfinite())
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 96c93d9..cb5af429 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -705,17 +705,6 @@
                    length);
   }
 
-  // flex-direction (aka -webkit-flex-direction)
-  static EFlexDirection InitialFlexDirection() { return EFlexDirection::kRow; }
-  EFlexDirection FlexDirection() const {
-    return static_cast<EFlexDirection>(
-        rare_non_inherited_data_->flexible_box_data_->flex_direction_);
-  }
-  void SetFlexDirection(EFlexDirection direction) {
-    SET_NESTED_VAR(rare_non_inherited_data_, flexible_box_data_,
-                   flex_direction_, static_cast<unsigned>(direction));
-  }
-
   // flex-grow (aka -webkit-flex-grow)
   static float InitialFlexGrow() { return 0; }
   float FlexGrow() const {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 6939201..cb64a7cd 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -146,7 +146,6 @@
 
 // CSS3 Flexbox Properties
 
-enum class EFlexDirection { kRow, kRowReverse, kColumn, kColumnReverse };
 enum class EFlexWrap { kNowrap, kWrap, kWrapReverse };
 
 // CSS3 Image Values
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
index ea3b366c..e263977 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
@@ -56,6 +56,7 @@
 }
 
 void SharedWorkerReportingProxy::PostMessageToPageInspector(
+    int session_id,
     const String& message) {
   DCHECK(!IsMainThread());
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
@@ -64,7 +65,7 @@
       ->PostTask(
           BLINK_FROM_HERE,
           CrossThreadBind(&WebSharedWorkerImpl::PostMessageToPageInspector,
-                          CrossThreadUnretained(worker_), message));
+                          CrossThreadUnretained(worker_), session_id, message));
 }
 
 void SharedWorkerReportingProxy::DidCloseWorkerGlobalScope() {
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.h b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.h
index b04aedb..45fc865 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.h
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.h
@@ -35,7 +35,7 @@
                             MessageLevel,
                             const String& message,
                             SourceLocation*) override;
-  void PostMessageToPageInspector(const WTF::String&) override;
+  void PostMessageToPageInspector(int session_id, const WTF::String&) override;
   void DidEvaluateWorkerScript(bool success) override {}
   void DidCloseWorkerGlobalScope() override;
   void WillDestroyWorkerGlobalScope() override {}
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
index fbf32be9..7cba209 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
@@ -159,10 +159,11 @@
 }
 
 void ThreadedMessagingProxyBase::PostMessageToPageInspector(
+    int session_id,
     const String& message) {
   DCHECK(IsParentContextThread());
   if (worker_inspector_proxy_)
-    worker_inspector_proxy_->DispatchMessageFromWorker(message);
+    worker_inspector_proxy_->DispatchMessageFromWorker(session_id, message);
 }
 
 ThreadableLoadingContext*
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
index 058bd25..1d8205b 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
@@ -54,7 +54,7 @@
                             MessageLevel,
                             const String& message,
                             std::unique_ptr<SourceLocation>);
-  void PostMessageToPageInspector(const String&);
+  void PostMessageToPageInspector(int session_id, const String&);
 
   // 'virtual' for testing.
   virtual void WorkerThreadTerminated();
diff --git a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
index e88f7285..7c31e77d 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
@@ -46,6 +46,7 @@
 }
 
 void ThreadedObjectProxyBase::PostMessageToPageInspector(
+    int session_id,
     const String& message) {
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
   // run even on a suspended page.
@@ -54,7 +55,7 @@
       ->PostTask(BLINK_FROM_HERE,
                  CrossThreadBind(
                      &ThreadedMessagingProxyBase::PostMessageToPageInspector,
-                     MessagingProxyWeakPtr(), message));
+                     MessagingProxyWeakPtr(), session_id, message));
 }
 
 void ThreadedObjectProxyBase::DidCloseWorkerGlobalScope() {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.h
index d2c9488..cf597dc 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.h
@@ -35,7 +35,7 @@
                             MessageLevel,
                             const String& message,
                             SourceLocation*) override;
-  void PostMessageToPageInspector(const String&) override;
+  void PostMessageToPageInspector(int session_id, const String&) override;
   void DidCloseWorkerGlobalScope() override;
   void DidTerminateWorkerThread() override;
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
index c9e1c7a..0a3bed7 100644
--- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
@@ -36,9 +36,7 @@
 }
 
 WorkerInspectorProxy::WorkerInspectorProxy()
-    : worker_thread_(nullptr),
-      execution_context_(nullptr),
-      page_inspector_(nullptr) {}
+    : worker_thread_(nullptr), execution_context_(nullptr) {}
 
 WorkerInspectorProxy* WorkerInspectorProxy::Create() {
   return new WorkerInspectorProxy();
@@ -84,13 +82,15 @@
   }
 
   worker_thread_ = nullptr;
-  page_inspector_ = nullptr;
+  page_inspectors_.clear();
   execution_context_ = nullptr;
 }
 
-void WorkerInspectorProxy::DispatchMessageFromWorker(const String& message) {
-  if (page_inspector_)
-    page_inspector_->DispatchMessageFromWorker(this, message);
+void WorkerInspectorProxy::DispatchMessageFromWorker(int session_id,
+                                                     const String& message) {
+  auto it = page_inspectors_.find(session_id);
+  if (it != page_inspectors_.end())
+    it->value->DispatchMessageFromWorker(this, session_id, message);
 }
 
 void WorkerInspectorProxy::AddConsoleMessageFromWorker(
@@ -101,63 +101,74 @@
       level, message, std::move(location), inspector_id_));
 }
 
-static void ConnectToWorkerGlobalScopeInspectorTask(
-    WorkerThread* worker_thread) {
+static void ConnectToWorkerGlobalScopeInspectorTask(WorkerThread* worker_thread,
+                                                    int session_id) {
   if (WorkerInspectorController* inspector =
-          worker_thread->GetWorkerInspectorController())
-    inspector->ConnectFrontend();
+          worker_thread->GetWorkerInspectorController()) {
+    inspector->ConnectFrontend(session_id);
+  }
 }
 
 void WorkerInspectorProxy::ConnectToInspector(
+    int session_id,
     WorkerInspectorProxy::PageInspector* page_inspector) {
   if (!worker_thread_)
     return;
-  DCHECK(!page_inspector_);
-  page_inspector_ = page_inspector;
+  DCHECK(page_inspectors_.find(session_id) == page_inspectors_.end());
+  page_inspectors_.insert(session_id, page_inspector);
   worker_thread_->AppendDebuggerTask(
       CrossThreadBind(ConnectToWorkerGlobalScopeInspectorTask,
-                      CrossThreadUnretained(worker_thread_)));
+                      CrossThreadUnretained(worker_thread_), session_id));
 }
 
 static void DisconnectFromWorkerGlobalScopeInspectorTask(
-    WorkerThread* worker_thread) {
+    WorkerThread* worker_thread,
+    int session_id) {
   if (WorkerInspectorController* inspector =
-          worker_thread->GetWorkerInspectorController())
-    inspector->DisconnectFrontend();
+          worker_thread->GetWorkerInspectorController()) {
+    inspector->DisconnectFrontend(session_id);
+  }
 }
 
 void WorkerInspectorProxy::DisconnectFromInspector(
+    int session_id,
     WorkerInspectorProxy::PageInspector* page_inspector) {
-  DCHECK(page_inspector_ == page_inspector);
-  page_inspector_ = nullptr;
-  if (worker_thread_)
+  DCHECK(page_inspectors_.at(session_id) == page_inspector);
+  page_inspectors_.erase(session_id);
+  if (worker_thread_) {
     worker_thread_->AppendDebuggerTask(
         CrossThreadBind(DisconnectFromWorkerGlobalScopeInspectorTask,
-                        CrossThreadUnretained(worker_thread_)));
+                        CrossThreadUnretained(worker_thread_), session_id));
+  }
 }
 
-static void DispatchOnInspectorBackendTask(const String& message,
+static void DispatchOnInspectorBackendTask(int session_id,
+                                           const String& message,
                                            WorkerThread* worker_thread) {
   if (WorkerInspectorController* inspector =
-          worker_thread->GetWorkerInspectorController())
-    inspector->DispatchMessageFromFrontend(message);
+          worker_thread->GetWorkerInspectorController()) {
+    inspector->DispatchMessageFromFrontend(session_id, message);
+  }
 }
 
-void WorkerInspectorProxy::SendMessageToInspector(const String& message) {
-  if (worker_thread_)
+void WorkerInspectorProxy::SendMessageToInspector(int session_id,
+                                                  const String& message) {
+  if (worker_thread_) {
     worker_thread_->AppendDebuggerTask(
-        CrossThreadBind(DispatchOnInspectorBackendTask, message,
+        CrossThreadBind(DispatchOnInspectorBackendTask, session_id, message,
                         CrossThreadUnretained(worker_thread_)));
+  }
 }
 
-void WorkerInspectorProxy::WriteTimelineStartedEvent(const String& session_id) {
+void WorkerInspectorProxy::WriteTimelineStartedEvent(
+    const String& tracing_session_id) {
   if (!worker_thread_)
     return;
   TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
                        "TracingSessionIdForWorker", TRACE_EVENT_SCOPE_THREAD,
                        "data",
                        InspectorTracingSessionIdForWorkerEvent::Data(
-                           session_id, InspectorId(), worker_thread_));
+                           tracing_session_id, InspectorId(), worker_thread_));
 }
 
 DEFINE_TRACE(WorkerInspectorProxy) {
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
index dd45a5b..64313fa7 100644
--- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
@@ -10,6 +10,7 @@
 #include "core/workers/WorkerThread.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Forward.h"
+#include "platform/wtf/HashMap.h"
 
 namespace blink {
 
@@ -30,21 +31,22 @@
    public:
     virtual ~PageInspector() {}
     virtual void DispatchMessageFromWorker(WorkerInspectorProxy*,
-                                           const String&) = 0;
+                                           int session_id,
+                                           const String& message) = 0;
   };
 
   WorkerThreadStartMode WorkerStartMode(ExecutionContext*);
   void WorkerThreadCreated(ExecutionContext*, WorkerThread*, const KURL&);
   void WorkerThreadTerminated();
-  void DispatchMessageFromWorker(const String&);
+  void DispatchMessageFromWorker(int session_id, const String&);
   void AddConsoleMessageFromWorker(MessageLevel,
                                    const String& message,
                                    std::unique_ptr<SourceLocation>);
 
-  void ConnectToInspector(PageInspector*);
-  void DisconnectFromInspector(PageInspector*);
-  void SendMessageToInspector(const String&);
-  void WriteTimelineStartedEvent(const String& session_id);
+  void ConnectToInspector(int session_id, PageInspector*);
+  void DisconnectFromInspector(int session_id, PageInspector*);
+  void SendMessageToInspector(int session_id, const String& message);
+  void WriteTimelineStartedEvent(const String& tracing_session_id);
 
   const String& Url() { return url_; }
   ExecutionContext* GetExecutionContext() { return execution_context_; }
@@ -59,7 +61,7 @@
 
   WorkerThread* worker_thread_;
   Member<ExecutionContext> execution_context_;
-  PageInspector* page_inspector_;
+  HashMap<int, PageInspector*> page_inspectors_;
   String url_;
   String inspector_id_;
 };
diff --git a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
index e4447fa..58493f3 100644
--- a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
@@ -57,7 +57,7 @@
                                     MessageLevel,
                                     const String& message,
                                     SourceLocation*) {}
-  virtual void PostMessageToPageInspector(const String&) {}
+  virtual void PostMessageToPageInspector(int session_id, const String&) {}
 
   // Invoked when the new WorkerGlobalScope is created. This is called after
   // didLoadWorkerScript().
diff --git a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
index d6bee49e..8493752 100644
--- a/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerScriptLoader.cpp
@@ -180,10 +180,12 @@
 
   if (!decoder_) {
     if (!response_encoding_.IsEmpty()) {
-      decoder_ = TextResourceDecoder::Create(
-          "text/javascript", WTF::TextEncoding(response_encoding_));
+      decoder_ =
+          TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                      WTF::TextEncoding(response_encoding_));
     } else {
-      decoder_ = TextResourceDecoder::Create("text/javascript", UTF8Encoding());
+      decoder_ = TextResourceDecoder::Create(
+          TextResourceDecoder::kPlainTextContent, UTF8Encoding());
     }
   }
 
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index ad9014f1..50de328 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -1709,18 +1709,21 @@
 }
 
 std::unique_ptr<TextResourceDecoder> XMLHttpRequest::CreateDecoder() const {
-  if (response_type_code_ == kResponseTypeJSON)
-    return TextResourceDecoder::Create("application/json", UTF8Encoding());
+  if (response_type_code_ == kResponseTypeJSON) {
+    return TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                       UTF8Encoding());
+  }
 
   if (!final_response_charset_.IsEmpty()) {
     return TextResourceDecoder::Create(
-        "text/plain", WTF::TextEncoding(final_response_charset_));
+        TextResourceDecoder::kPlainTextContent,
+        WTF::TextEncoding(final_response_charset_));
   }
 
   // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
   if (ResponseIsXML()) {
     std::unique_ptr<TextResourceDecoder> decoder =
-        TextResourceDecoder::Create("application/xml");
+        TextResourceDecoder::Create(TextResourceDecoder::kXMLContent);
     // Don't stop on encoding errors, unlike it is done for other kinds
     // of XML resources. This matches the behavior of previous WebKit
     // versions, Firefox and Opera.
@@ -1729,10 +1732,13 @@
     return decoder;
   }
 
-  if (ResponseIsHTML())
-    return TextResourceDecoder::Create("text/html", UTF8Encoding());
+  if (ResponseIsHTML()) {
+    return TextResourceDecoder::Create(TextResourceDecoder::kHTMLContent,
+                                       UTF8Encoding());
+  }
 
-  return TextResourceDecoder::Create("text/plain", UTF8Encoding());
+  return TextResourceDecoder::Create(TextResourceDecoder::kPlainTextContent,
+                                     UTF8Encoding());
 }
 
 void XMLHttpRequest::DidReceiveData(const char* data, unsigned len) {
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index ed73390..95a770ac 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -146,6 +146,8 @@
   "front_end/console/module.json",
   "front_end/console_model/ConsoleModel.js",
   "front_end/console_model/module.json",
+  "front_end/console_test_runner/ConsoleTestRunner.js",
+  "front_end/console_test_runner/module.json",
   "front_end/cookie_table/CookiesTable.js",
   "front_end/cookie_table/module.json",
   "front_end/coverage/coverageListView.css",
@@ -286,6 +288,10 @@
   "front_end/inline_editor/SwatchPopoverHelper.js",
   "front_end/inspector.js",
   "front_end/inspector.json",
+  "front_end/integration_test_runner.js",
+  "front_end/integration_test_runner.json",
+  "front_end/integration_test_runner/IntegrationTestRunner.js",
+  "front_end/integration_test_runner/module.json",
   "front_end/layer_viewer/layerDetailsView.css",
   "front_end/layer_viewer/LayerDetailsView.js",
   "front_end/layer_viewer/layers3DView.css",
@@ -936,6 +942,7 @@
 devtools_applications = [
   "inspector",
   "toolbox",
+  "integration_test_runner",
   "unit_test_runner",
   "formatter_worker",
   "audits2_worker",
@@ -1088,6 +1095,7 @@
   inputs = helper_scripts + all_devtools_files + generated_scripts + [
              "front_end/inspector.html",
              "front_end/toolbox.html",
+             "front_end/integration_test_runner.html",
              "front_end/unit_test_runner.html",
            ]
 
@@ -1114,12 +1122,14 @@
     inputs = all_devtools_files + [
                "front_end/inspector.html",
                "front_end/toolbox.html",
+               "front_end/integration_test_runner.html",
                "front_end/unit_test_runner.html",
              ]
 
     outputs = [
       "$resources_out_debug_dir/inspector.html",
       "$resources_out_debug_dir/toolbox.html",
+      "$resources_out_debug_dir/integration_test_runner.html",
       "$resources_out_debug_dir/unit_test_runner.html",
     ]
 
diff --git a/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js b/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js
index 1771d4c..e669294 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits/AuditController.js
@@ -72,7 +72,9 @@
     }
 
     var networkManager = target.model(SDK.NetworkManager);
-    var requests = networkManager ? NetworkLog.networkLog.requestsForManager(networkManager).slice() : [];
+    var requests =
+        NetworkLog.networkLog.requests().filter(request => SDK.NetworkManager.forRequest(request) === networkManager);
+
     var compositeProgress = new Common.CompositeProgress(this._progress);
     var subprogresses = [];
     for (var i = 0; i < categories.length; ++i)
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
index a37aad2..a3d831928 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMPresentationUtils.js
@@ -213,7 +213,7 @@
 };
 
 /**
- * @param {!SDK.Target} target
+ * @param {?SDK.Target} target
  * @param {!Components.Linkifier} linkifier
  * @param {!Protocol.Runtime.StackTrace=} stackTrace
  * @return {!Element}
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index c3aafbe..ad35836 100644
--- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -427,8 +427,8 @@
     this.scriptId = scriptId || null;
     this.workerId = workerId || null;
 
-    var networkManager = (runtimeModel && requestId) ? runtimeModel.target().model(SDK.NetworkManager) : null;
-    this.request = (networkManager && requestId) ? NetworkLog.networkLog.requestForId(networkManager, requestId) : null;
+    var manager = runtimeModel ? runtimeModel.target().model(SDK.NetworkManager) : null;
+    this.request = (manager && requestId) ? NetworkLog.networkLog.requestByManagerAndId(manager, requestId) : null;
 
     if (this.request) {
       var initiator = this.request.initiator();
diff --git a/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js
new file mode 100644
index 0000000..1f84b873
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/console_test_runner/ConsoleTestRunner.js
@@ -0,0 +1,146 @@
+// 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.
+
+/**
+ * @fileoverview using private properties isn't a Closure violation in tests.
+ * @suppress {accessControls}
+ */
+
+/**
+ * @param {boolean} printOriginatingCommand
+ * @param {boolean} dumpClassNames
+ * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter
+ */
+ConsoleTestRunner.dumpConsoleMessages = function(printOriginatingCommand, dumpClassNames, formatter) {
+  TestRunner.addResults(
+      ConsoleTestRunner.dumpConsoleMessagesIntoArray(printOriginatingCommand, dumpClassNames, formatter));
+};
+
+/**
+ * @param {boolean} printOriginatingCommand
+ * @param {boolean} dumpClassNames
+ * @param {function(!Element, !ConsoleModel.ConsoleMessage):string=} formatter
+ * @return {!Array<string>}
+ */
+ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingCommand, dumpClassNames, formatter) {
+  formatter = formatter || ConsoleTestRunner.prepareConsoleMessageText;
+  var result = [];
+  ConsoleTestRunner.disableConsoleViewport();
+  var consoleView = Console.ConsoleView.instance();
+  if (consoleView._needsFullUpdate)
+    consoleView._updateMessageList();
+  var viewMessages = consoleView._visibleViewMessages;
+  for (var i = 0; i < viewMessages.length; ++i) {
+    var uiMessage = viewMessages[i];
+    var message = uiMessage.consoleMessage();
+    var element = uiMessage.element();
+
+    if (dumpClassNames) {
+      var classNames = [];
+      for (var node = element.firstChild; node; node = node.traverseNextNode(element)) {
+        if (node.nodeType === Node.ELEMENT_NODE && node.className) {
+          classNames.push(node.className.replace('platform-linux', 'platform-*')
+                              .replace('platform-mac', 'platform-*')
+                              .replace('platform-windows', 'platform-*'));
+        }
+      }
+    }
+
+    if (ConsoleTestRunner.dumpConsoleTableMessage(uiMessage, false, result)) {
+      if (dumpClassNames)
+        result.push(classNames.join(' > '));
+    } else {
+      var messageText = formatter(element, message);
+      messageText = messageText.replace(/VM\d+/g, 'VM');
+      result.push(messageText + (dumpClassNames ? ' ' + classNames.join(' > ') : ''));
+    }
+
+    if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage())
+      result.push('Originating from: ' + uiMessage.consoleMessage().originatingMessage().messageText);
+  }
+  return result;
+};
+
+/**
+ * @param {!Element} messageElement
+ * @param {!ConsoleModel.ConsoleMessage} consoleMessage
+ * @return {string}
+ */
+ConsoleTestRunner.prepareConsoleMessageText = function(messageElement, consoleMessage) {
+  var messageText = messageElement.deepTextContent().replace(/\u200b/g, '');
+  // Replace scriptIds with generic scriptId string to avoid flakiness.
+  messageText = messageText.replace(/VM\d+/g, 'VM');
+  // Remove line and column of evaluate method.
+  messageText = messageText.replace(/(at eval \(eval at evaluate) \(:\d+:\d+\)/, '$1');
+
+  if (messageText.startsWith('Navigated to')) {
+    var fileName = messageText.split(' ').pop().split('/').pop();
+    messageText = 'Navigated to ' + fileName;
+  }
+  // The message might be extremely long in case of dumping stack overflow message.
+  messageText = messageText.substring(0, 1024);
+  return messageText;
+};
+
+/**
+ * @param {!Console.ConsoleViewMessage} viewMessage
+ * @param {boolean} forceInvalidate
+ * @param {!Array<string>} results
+ * @return {boolean}
+ */
+ConsoleTestRunner.dumpConsoleTableMessage = function(viewMessage, forceInvalidate, results) {
+  if (forceInvalidate)
+    Console.ConsoleView.instance()._viewport.invalidate();
+  var table = viewMessage.element();
+  var headers = table.querySelectorAll('th > div:first-child');
+  if (!headers.length)
+    return false;
+
+  var headerLine = '';
+  for (var i = 0; i < headers.length; i++)
+    headerLine += headers[i].textContent + ' | ';
+
+  addResult('HEADER ' + headerLine);
+
+  var rows = table.querySelectorAll('.data-container tr');
+
+  for (var i = 0; i < rows.length; i++) {
+    var row = rows[i];
+    var rowLine = '';
+    var items = row.querySelectorAll('td > span');
+    for (var j = 0; j < items.length; j++)
+      rowLine += items[j].textContent + ' | ';
+
+    if (rowLine.trim())
+      addResult('ROW ' + rowLine);
+  }
+
+  /**
+   * @param {string} x
+   */
+  function addResult(x) {
+    if (results)
+      results.push(x);
+    else
+      TestRunner.addResult(x);
+  }
+
+  return true;
+};
+
+ConsoleTestRunner.disableConsoleViewport = function() {
+  ConsoleTestRunner.fixConsoleViewportDimensions(600, 2000);
+};
+
+/**
+ * @param {number} width
+ * @param {number} height
+ */
+ConsoleTestRunner.fixConsoleViewportDimensions = function(width, height) {
+  var viewport = Console.ConsoleView.instance()._viewport;
+  viewport.element.style.width = width + 'px';
+  viewport.element.style.height = height + 'px';
+  viewport.element.style.position = 'absolute';
+  viewport.invalidate();
+};
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/console_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/console_test_runner/module.json
new file mode 100644
index 0000000..3a9a7cc
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/console_test_runner/module.json
@@ -0,0 +1,11 @@
+{
+  "dependencies": [
+    "test_runner",
+    "integration_test_runner",
+    "console",
+    "console_model"
+  ],
+  "scripts": [
+    "ConsoleTestRunner.js"
+  ]
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.html b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.html
new file mode 100644
index 0000000..1773c31
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.html
@@ -0,0 +1,15 @@
+<!--
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+-->
+<!doctype html>
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' https://chrome-devtools-frontend.appspot.com">
+    <script type="text/javascript" src="Runtime.js"></script>
+    <script type="text/javascript" src="integration_test_runner.js"></script>
+</head>
+<body id="-blink-dev-tools"></body>
+</html>
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.js b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.js
new file mode 100644
index 0000000..3eddfa01
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.js
@@ -0,0 +1,10 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+if (self.testRunner) {
+  testRunner.dumpAsText();
+  testRunner.waitUntilDone();
+}
+
+Runtime.startApplication('integration_test_runner');
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
new file mode 100644
index 0000000..df1387c
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner.json
@@ -0,0 +1,75 @@
+{
+  "modules" : [
+    { "name": "test_runner", "type": "autostart" },
+    { "name": "integration_test_runner", "type": "autostart" },
+    { "name": "console_test_runner" },
+
+
+
+    { "name": "platform", "type": "autostart" },
+    { "name": "dom_extension", "type": "autostart" },
+    { "name": "main", "type": "autostart" },
+    { "name": "components", "type": "autostart"},
+    { "name": "ui", "type": "autostart" },
+    { "name": "sdk", "type": "autostart" },
+    { "name": "protocol", "type": "autostart" },
+    { "name": "host", "type": "autostart" },
+    { "name": "common", "type": "autostart" },
+    { "name": "emulation", "type": "autostart" },
+    { "name": "workspace", "type": "autostart" },
+    { "name": "bindings", "type": "autostart" },
+    { "name": "persistence", "type": "autostart" },
+    { "name": "extensions", "type": "autostart" },
+    { "name": "services", "type": "autostart" },
+    { "name": "elements", "condition": "!v8only" },
+    { "name": "network", "condition": "!v8only" },
+    { "name": "sources" },
+    { "name": "timeline", "condition": "!v8only" },
+    { "name": "timeline_model", "condition": "!v8only" },
+    { "name": "product_registry", "type": "autostart" },
+    { "name": "product_registry_impl", "condition": "!v8only", "type": "remote" },
+    { "name": "profiler" },
+    { "name": "resources", "condition": "!v8only" },
+    { "name": "audits", "condition": "!v8only" },
+    { "name": "audits2", "condition": "!v8only" },
+    { "name": "devices" },
+    { "name": "security", "condition": "!v8only" },
+    { "name": "console" },
+    { "name": "source_frame" },
+    { "name": "text_editor" },
+    { "name": "cm" },
+    { "name": "cm_modes", "type": "remote" },
+    { "name": "settings" },
+    { "name": "layers", "condition": "!v8only" },
+    { "name": "layer_viewer", "condition": "!v8only" },
+    { "name": "snippets" },
+    { "name": "diff" },
+    { "name": "terminal", "type": "remote" },
+    { "name": "sass", "condition": "!v8only" },
+    { "name": "accessibility", "condition": "!v8only", "type": "remote" },
+    { "name": "animation", "condition": "!v8only" },
+    { "name": "coverage" },
+    { "name": "screencast", "condition": "remoteFrontend", "type": "remote" },
+    { "name": "emulated_devices", "condition": "!v8only" , "type": "remote" },
+    { "name": "perf_ui" },
+    { "name": "quick_open" },
+    { "name": "cookie_table" },
+    { "name": "inline_editor" },
+    { "name": "color_picker" },
+    { "name": "data_grid" },
+    { "name": "heap_snapshot_model" },
+    { "name": "event_listeners" },
+    { "name": "object_ui"},
+    { "name": "help", "type": "autostart"},
+    { "name": "workspace_diff" },
+    { "name": "console_model", "type": "autostart"},
+    { "name": "network_log", "type": "autostart"},
+    { "name": "text_utils", "type": "autostart"},
+    { "name": "changes"},
+    { "name": "mobile_throttling", "type": "autostart"},
+    { "name": "network_priorities"},
+    { "name": "formatter" }
+  ],
+
+  "has_html": true
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js
new file mode 100644
index 0000000..8743227a
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/IntegrationTestRunner.js
@@ -0,0 +1,99 @@
+// 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.
+
+/**
+ * Export all public members onto TestRunner namespace so test writers have a simpler API.
+ * @fileoverview using private properties isn't a Closure violation in tests.
+ * @suppress {accessControls}
+ */
+
+/**
+ * @param {!SDK.Target} target
+ */
+IntegrationTestRunner._setupTestHelpers = function(target) {
+  TestRunner.CSSAgent = target.cssAgent();
+  TestRunner.DeviceOrientationAgent = target.deviceOrientationAgent();
+  TestRunner.DOMAgent = target.domAgent();
+  TestRunner.DOMDebuggerAgent = target.domdebuggerAgent();
+  TestRunner.DebuggerAgent = target.debuggerAgent();
+  TestRunner.EmulationAgent = target.emulationAgent();
+  TestRunner.HeapProfilerAgent = target.heapProfilerAgent();
+  TestRunner.InspectorAgent = target.inspectorAgent();
+  TestRunner.NetworkAgent = target.networkAgent();
+  TestRunner.PageAgent = target.pageAgent();
+  TestRunner.ProfilerAgent = target.profilerAgent();
+  TestRunner.RuntimeAgent = target.runtimeAgent();
+  TestRunner.TargetAgent = target.targetAgent();
+
+  TestRunner.networkManager = target.model(SDK.NetworkManager);
+  TestRunner.securityOriginManager = target.model(SDK.SecurityOriginManager);
+  TestRunner.resourceTreeModel = target.model(SDK.ResourceTreeModel);
+  TestRunner.debuggerModel = target.model(SDK.DebuggerModel);
+  TestRunner.runtimeModel = target.model(SDK.RuntimeModel);
+  TestRunner.domModel = target.model(SDK.DOMModel);
+  TestRunner.domDebuggerModel = target.model(SDK.DOMDebuggerModel);
+  TestRunner.cssModel = target.model(SDK.CSSModel);
+  TestRunner.cpuProfilerModel = target.model(SDK.CPUProfilerModel);
+  TestRunner.serviceWorkerManager = target.model(SDK.ServiceWorkerManager);
+  TestRunner.tracingManager = target.model(SDK.TracingManager);
+  TestRunner.mainTarget = target;
+};
+
+/**
+ * @param {string} code
+ * @param {!Function} callback
+ */
+TestRunner.evaluateInPage = async function(code, callback) {
+  var response = await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console'});
+  if (!response[Protocol.Error]) {
+    TestRunner.safeWrap(callback)(
+        TestRunner.runtimeModel.createRemoteObject(response.result), response.exceptionDetails);
+  }
+};
+
+/**
+ * @param {string} code
+ * @return {!Promise<!SDK.RemoteObject>}
+ */
+TestRunner.evaluateInPagePromise = function(code) {
+  return new Promise(success => TestRunner.evaluateInPage(code, success));
+};
+
+/**
+ * @param {!Function} callback
+ */
+TestRunner.deprecatedRunAfterPendingDispatches = function(callback) {
+  var targets = SDK.targetManager.targets();
+  var promises = targets.map(target => new Promise(resolve => target._deprecatedRunAfterPendingDispatches(resolve)));
+  Promise.all(promises).then(TestRunner.safeWrap(callback));
+};
+
+/** @type {boolean} */
+IntegrationTestRunner._startedTest = false;
+
+/**
+ * @implements {SDK.TargetManager.Observer}
+ */
+IntegrationTestRunner.TestObserver = class {
+  /**
+   * @param {!SDK.Target} target
+   * @override
+   */
+  targetAdded(target) {
+    if (IntegrationTestRunner._startedTest)
+      return;
+    IntegrationTestRunner._startedTest = true;
+    IntegrationTestRunner._setupTestHelpers(target);
+    TestRunner.executeTestScript();
+  }
+
+  /**
+   * @param {!SDK.Target} target
+   * @override
+   */
+  targetRemoved(target) {
+  }
+};
+
+SDK.targetManager.observeTargets(new IntegrationTestRunner.TestObserver());
diff --git a/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json
new file mode 100644
index 0000000..a1301c8e
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/integration_test_runner/module.json
@@ -0,0 +1,9 @@
+{
+  "dependencies": [
+    "test_runner",
+    "sdk"
+  ],
+  "scripts": [
+    "IntegrationTestRunner.js"
+  ]
+}
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 949c844..217e11c 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -47,6 +47,24 @@
     SDK.ResourceTreeModel.reloadAllPages(hard);
   }
 
+  /**
+   * @param {string} label
+   */
+  static time(label) {
+    if (Host.isUnderTest())
+      return;
+    console.time(label);
+  }
+
+  /**
+   * @param {string} label
+   */
+  static timeEnd(label) {
+    if (Host.isUnderTest())
+      return;
+    console.timeEnd(label);
+  }
+
   _loaded() {
     console.timeStamp('Main._loaded');
     Runtime.setPlatform(Host.platform());
@@ -149,7 +167,7 @@
    * @suppressGlobalPropertiesCheck
    */
   _createAppUI() {
-    console.time('Main._createAppUI');
+    Main.Main.time('Main._createAppUI');
 
     UI.viewManager = new UI.ViewManager();
 
@@ -218,7 +236,7 @@
     this._registerMessageSinkListener();
 
     self.runtime.extension(Common.AppProvider).instance().then(this._showAppUI.bind(this));
-    console.timeEnd('Main._createAppUI');
+    Main.Main.timeEnd('Main._createAppUI');
   }
 
   /**
@@ -226,7 +244,7 @@
    * @suppressGlobalPropertiesCheck
    */
   _showAppUI(appProvider) {
-    console.time('Main._showAppUI');
+    Main.Main.time('Main._showAppUI');
     var app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
     // It is important to kick controller lifetime after apps are instantiated.
     Components.dockController.initialize();
@@ -265,17 +283,17 @@
 
     // Allow UI cycles to repaint prior to creating connection.
     setTimeout(this._initializeTarget.bind(this), 0);
-    console.timeEnd('Main._showAppUI');
+    Main.Main.timeEnd('Main._showAppUI');
   }
 
   _initializeTarget() {
-    console.time('Main._initializeTarget');
+    Main.Main.time('Main._initializeTarget');
     SDK.targetManager.connectToMainTarget(webSocketConnectionLost);
 
     InspectorFrontendHost.readyForTest();
     // Asynchronously run the extensions.
     setTimeout(this._lateInitialization.bind(this), 100);
-    console.timeEnd('Main._initializeTarget');
+    Main.Main.timeEnd('Main._initializeTarget');
 
     function webSocketConnectionLost() {
       if (!Main._disconnectedScreenWithReasonWasShown)
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index 7ed8b3042..cc6679d 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -854,7 +854,9 @@
       this._nameBadgeElement.classList.add('network-badge');
     }
     cell.appendChild(this._nameBadgeElement);
-    cell.createTextChild(this._request.networkManager().target().decorateLabel(this._request.name().trimMiddle(100)));
+    var name = this._request.name().trimMiddle(100);
+    var networkManager = SDK.NetworkManager.forRequest(this._request);
+    cell.createTextChild(networkManager ? networkManager.target().decorateLabel(name) : name);
     this._appendSubtitle(cell, this._request.path());
     cell.title = this._request.url();
   }
@@ -934,8 +936,8 @@
 
       case SDK.NetworkRequest.InitiatorType.Redirect:
         cell.title = initiator.url;
-        console.assert(request.redirectSource);
-        var redirectSource = /** @type {!SDK.NetworkRequest} */ (request.redirectSource);
+        var redirectSource = /** @type {!SDK.NetworkRequest} */ (request.redirectSource());
+        console.assert(redirectSource);
         if (this.parentView().nodeForRequest(redirectSource)) {
           cell.appendChild(
               Components.Linkifier.linkifyRevealable(redirectSource, Bindings.displayNameForURL(redirectSource.url())));
@@ -946,8 +948,9 @@
         break;
 
       case SDK.NetworkRequest.InitiatorType.Script:
+        var networkManager = SDK.NetworkManager.forRequest(request);
         this._linkifiedInitiatorAnchor = this.parentView().linkifier.linkifyScriptLocation(
-            request.networkManager().target(), initiator.scriptId, initiator.url, initiator.lineNumber,
+            networkManager ? networkManager.target() : null, initiator.scriptId, initiator.url, initiator.lineNumber,
             initiator.columnNumber);
         this._linkifiedInitiatorAnchor.title = '';
         cell.appendChild(this._linkifiedInitiatorAnchor);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
index 7436810..22dfdd0 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -611,7 +611,10 @@
         selectedNodeNumber++;
         selectedTransferSize += requestTransferSize;
       }
-      if (request.url() === request.networkManager().target().inspectedURL() &&
+      var networkManager = SDK.NetworkManager.forRequest(request);
+      // TODO(allada) inspectedURL should be stored in PageLoad used instead of target so HAR requests can have an
+      // inspected url.
+      if (networkManager && request.url() === networkManager.target().inspectedURL() &&
           request.resourceType() === Common.resourceTypes.Document)
         baseTime = request.startTime;
       if (request.endTime > maxTime)
@@ -963,8 +966,8 @@
     node[Network.NetworkLogView._isFilteredOutSymbol] = true;
     node[Network.NetworkLogView._isMatchingSearchQuerySymbol] = false;
 
-    if (request.redirects)
-      request.redirects.forEach(this._refreshRequest.bind(this));
+    for (var redirect = request.redirectSource(); redirect; redirect = redirect.redirectSource())
+      this._refreshRequest(redirect);
     return node;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
index 9e3cef2..ba5937a 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -542,8 +542,9 @@
     return {
       box: anchor.boxInWindow(),
       show: popover => {
+        var manager = anchor.request ? SDK.NetworkManager.forRequest(anchor.request) : null;
         var content = Components.DOMPresentationUtils.buildStackTracePreviewContents(
-            anchor.request.networkManager().target(), this._popupLinkifier, initiator.stack);
+            manager ? manager.target() : null, this._popupLinkifier, initiator.stack);
         popover.contentElement.appendChild(content);
         return Promise.resolve(true);
       },
diff --git a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
index 9c32457b..dfb54f2 100644
--- a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
+++ b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
@@ -38,10 +38,8 @@
     this._requests = [];
     /** @type {!Set<!SDK.NetworkRequest>} */
     this._requestsSet = new Set();
-    /** @type {!Map<!SDK.NetworkManager, !Map<string, !SDK.NetworkRequest>>} */
-    this._requestsByManagerAndId = new Map();
     /** @type {!Map<!SDK.NetworkManager, !NetworkLog.PageLoad>} */
-    this._currentPageLoad = new Map();
+    this._pageLoadForManager = new Map();
     this._isRecording = true;
     SDK.targetManager.observeModels(SDK.NetworkManager, this);
   }
@@ -73,7 +71,6 @@
     }
 
     networkManager[NetworkLog.NetworkLog._events] = eventListeners;
-    this._requestsByManagerAndId.set(networkManager, new Map());
   }
 
   /**
@@ -81,7 +78,6 @@
    * @param {!SDK.NetworkManager} networkManager
    */
   modelRemoved(networkManager) {
-    this._requestsByManagerAndId.delete(networkManager);
     this._removeNetworkManagerListeners(networkManager);
   }
 
@@ -124,11 +120,17 @@
 
   /**
    * @param {!SDK.NetworkManager} networkManager
-   * @return {!Array<!SDK.NetworkRequest>}
+   * @param {!Protocol.Network.RequestId} requestId
+   * @return {?SDK.NetworkRequest}
    */
-  requestsForManager(networkManager) {
-    var map = this._requestsByManagerAndId.get(networkManager);
-    return map ? Array.from(map.values()) : [];
+  requestByManagerAndId(networkManager, requestId) {
+    // We itterate backwards because the last item will likely be the one needed for console network request lookups.
+    for (var i = this._requests.length - 1; i >= 0; i--) {
+      var request = this._requests[i];
+      if (requestId === request.requestId() && networkManager === SDK.NetworkManager.forRequest(request))
+        return request;
+    }
+    return null;
   }
 
   /**
@@ -137,11 +139,8 @@
    * @return {?SDK.NetworkRequest}
    */
   _requestByManagerAndURL(networkManager, url) {
-    var map = this._requestsByManagerAndId.get(networkManager);
-    if (!map)
-      return null;
-    for (var request of map.values()) {
-      if (request.url() === url)
+    for (var request of this._requests) {
+      if (url === request.url() && networkManager === SDK.NetworkManager.forRequest(request))
         return request;
     }
     return null;
@@ -177,9 +176,10 @@
     var scriptId = null;
     var initiator = request.initiator();
 
-    if (request.redirectSource) {
+    var redirectSource = request.redirectSource();
+    if (redirectSource) {
       type = SDK.NetworkRequest.InitiatorType.Redirect;
-      url = request.redirectSource.url();
+      url = redirectSource.url();
     } else if (initiator) {
       if (initiator.type === Protocol.Network.InitiatorType.Parser) {
         type = SDK.NetworkRequest.InitiatorType.Parser;
@@ -214,12 +214,11 @@
   initiatorGraphForRequest(request) {
     /** @type {!Set<!SDK.NetworkRequest>} */
     var initiated = new Set();
-    var map = this._requestsByManagerAndId.get(request.networkManager());
-    if (map) {
-      for (var otherRequest of map.values()) {
-        if (this._initiatorChain(otherRequest).has(request))
-          initiated.add(otherRequest);
-      }
+    var networkManager = SDK.NetworkManager.forRequest(request);
+    for (var otherRequest of this._requests) {
+      var otherRequestManager = SDK.NetworkManager.forRequest(request);
+      if (networkManager === otherRequestManager && this._initiatorChain(otherRequest).has(request))
+        initiated.add(otherRequest);
     }
     return {initiators: this._initiatorChain(request), initiated: initiated};
   }
@@ -255,8 +254,9 @@
     if (request[NetworkLog.NetworkLog._initiatorDataSymbol].request !== undefined)
       return request[NetworkLog.NetworkLog._initiatorDataSymbol].request;
     var url = this.initiatorInfoForRequest(request).url;
+    var networkManager = SDK.NetworkManager.forRequest(request);
     request[NetworkLog.NetworkLog._initiatorDataSymbol].request =
-        this._requestByManagerAndURL(request.networkManager(), url);
+        networkManager ? this._requestByManagerAndURL(networkManager, url) : null;
     return request[NetworkLog.NetworkLog._initiatorDataSymbol].request;
   }
 
@@ -278,18 +278,14 @@
    */
   _onMainFrameNavigated(event) {
     var mainFrame = /** @type {!SDK.ResourceTreeFrame} */ (event.data);
-    var networkManager = mainFrame.resourceTreeModel().target().model(SDK.NetworkManager);
-    if (!networkManager)
+    var manager = mainFrame.resourceTreeModel().target().model(SDK.NetworkManager);
+    if (!manager)
       return;
 
-    var oldManagerRequests = this.requestsForManager(networkManager);
+    var oldManagerRequests = this._requests.filter(request => SDK.NetworkManager.forRequest(request) === manager);
     var oldRequestsSet = this._requestsSet;
     this._requests = [];
     this._requestsSet = new Set();
-    var idMap = new Map();
-    // TODO(allada) This should be removed in a future patch, but if somewhere else does a request on this in a reset
-    // event it may cause problems.
-    this._requestsByManagerAndId.set(networkManager, idMap);
     this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.Reset);
 
     // Preserve requests from the new session.
@@ -300,8 +296,11 @@
         continue;
       if (!currentPageLoad) {
         currentPageLoad = new NetworkLog.PageLoad(request);
-        if (request.redirects)
-          requestsToAdd.pushAll(request.redirects);
+        var redirectSource = request.redirectSource();
+        while (redirectSource) {
+          requestsToAdd.push(redirectSource);
+          redirectSource = redirectSource.redirectSource();
+        }
       }
       requestsToAdd.push(request);
     }
@@ -310,7 +309,6 @@
       oldRequestsSet.delete(request);
       this._requests.push(request);
       this._requestsSet.add(request);
-      idMap.set(request.requestId(), request);
       request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] = currentPageLoad;
       this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.RequestAdded, request);
     }
@@ -324,7 +322,7 @@
     }
 
     if (currentPageLoad)
-      this._currentPageLoad.set(networkManager, currentPageLoad);
+      this._pageLoadForManager.set(manager, currentPageLoad);
   }
 
   /**
@@ -334,11 +332,10 @@
     var request = /** @type {!SDK.NetworkRequest} */ (event.data);
     this._requests.push(request);
     this._requestsSet.add(request);
-    var idMap = this._requestsByManagerAndId.get(request.networkManager());
-    if (idMap)
-      idMap.set(request.requestId(), request);
-    request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] =
-        this._currentPageLoad.get(request.networkManager()) || null;
+    var manager = SDK.NetworkManager.forRequest(request);
+    var pageLoad = manager ? this._pageLoadForManager.get(manager) : null;
+    if (pageLoad)
+      request[NetworkLog.NetworkLog._pageLoadForRequestSymbol] = pageLoad;
     this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.RequestAdded, request);
   }
 
@@ -366,7 +363,7 @@
    */
   _onDOMContentLoaded(resourceTreeModel, event) {
     var networkManager = resourceTreeModel.target().model(SDK.NetworkManager);
-    var pageLoad = networkManager ? this._currentPageLoad.get(networkManager) : null;
+    var pageLoad = networkManager ? this._pageLoadForManager.get(networkManager) : null;
     if (pageLoad)
       pageLoad.contentLoadTime = /** @type {number} */ (event.data);
   }
@@ -376,29 +373,18 @@
    */
   _onLoad(event) {
     var networkManager = event.data.resourceTreeModel.target().model(SDK.NetworkManager);
-    var pageLoad = networkManager ? this._currentPageLoad.get(networkManager) : null;
+    var pageLoad = networkManager ? this._pageLoadForManager.get(networkManager) : null;
     if (pageLoad)
       pageLoad.loadTime = /** @type {number} */ (event.data.loadTime);
   }
 
-  /**
-   * @param {!SDK.NetworkManager} networkManager
-   * @param {!Protocol.Network.RequestId} requestId
-   * @return {?SDK.NetworkRequest}
-   */
-  requestForId(networkManager, requestId) {
-    var map = this._requestsByManagerAndId.get(networkManager);
-    return map ? (map.get(requestId) || null) : null;
-  }
-
   reset() {
     this._requests = [];
     this._requestsSet.clear();
-    this._requestsByManagerAndId.forEach(map => map.clear());
-    var networkManagers = new Set(SDK.targetManager.models(SDK.NetworkManager));
-    for (var networkManager of this._currentPageLoad.keys()) {
-      if (!networkManagers.has(networkManager))
-        this._currentPageLoad.delete(networkManager);
+    var managers = new Set(SDK.targetManager.models(SDK.NetworkManager));
+    for (var manager of this._pageLoadForManager.keys()) {
+      if (!managers.has(manager))
+        this._pageLoadForManager.delete(manager);
     }
 
     this.dispatchEventToListeners(NetworkLog.NetworkLog.Events.Reset);
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
index b27e2c5e..64bbd62 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkManager.js
@@ -59,18 +59,29 @@
 
   /**
    * @param {!SDK.NetworkRequest} request
+   * @return {?SDK.NetworkManager}
+   */
+  static forRequest(request) {
+    return request[SDK.NetworkManager._networkManagerForRequestSymbol];
+  }
+
+  /**
+   * @param {!SDK.NetworkRequest} request
    * @return {boolean}
    */
   static canReplayRequest(request) {
-    return request.resourceType() === Common.resourceTypes.XHR;
+    return !!request[SDK.NetworkManager._networkManagerForRequestSymbol] &&
+        request.resourceType() === Common.resourceTypes.XHR;
   }
 
   /**
    * @param {!SDK.NetworkRequest} request
    */
   static replayRequest(request) {
-    // TODO(allada) networkAgent() will be removed from NetworkRequest, but in the mean time we extract it from request.
-    request.networkManager()._networkAgent.replayXHR(request.requestId());
+    var manager = request[SDK.NetworkManager._networkManagerForRequestSymbol];
+    if (!manager)
+      return;
+    manager._networkAgent.replayXHR(request.requestId());
   }
 
   /**
@@ -82,7 +93,9 @@
       return {error: 'Content for WebSockets is currently not supported', content: null, encoded: false};
     if (!request.finished)
       await request.once(SDK.NetworkRequest.Events.FinishedLoading);
-    var manager = request.networkManager();
+    var manager = SDK.NetworkManager.forRequest(request);
+    if (!manager)
+      return {error: 'No network manager for request', content: null, encoded: false};
     var response = await manager._networkAgent.invoke_getResponseBody({requestId: request.requestId()});
     var error = response[Protocol.Error] || null;
     return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
@@ -189,12 +202,16 @@
 /** @typedef {{url: string, enabled: boolean}} */
 SDK.NetworkManager.BlockedPattern;
 
+SDK.NetworkManager._networkManagerForRequestSymbol = Symbol('NetworkManager');
 
 /**
  * @implements {Protocol.NetworkDispatcher}
  * @unrestricted
  */
 SDK.NetworkDispatcher = class {
+  /**
+   * @param {!SDK.NetworkManager} manager
+   */
   constructor(manager) {
     this._manager = manager;
     /** @type {!Object<!Protocol.Network.RequestId, !SDK.NetworkRequest>} */
@@ -488,7 +505,8 @@
    * @param {!Protocol.Network.Initiator=} initiator
    */
   webSocketCreated(requestId, requestURL, initiator) {
-    var networkRequest = new SDK.NetworkRequest(this._manager, requestId, requestURL, '', '', '', initiator || null);
+    var networkRequest = new SDK.NetworkRequest(requestId, requestURL, '', '', '', initiator || null);
+    networkRequest[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager;
     networkRequest.setResourceType(Common.resourceTypes.WebSocket);
     this._startNetworkRequest(networkRequest);
   }
@@ -636,16 +654,16 @@
    */
   _appendRedirect(requestId, time, redirectURL) {
     var originalNetworkRequest = this._inflightRequestsById[requestId];
-    var previousRedirects = originalNetworkRequest.redirects || [];
-    originalNetworkRequest.setRequestId(requestId + ':redirected.' + previousRedirects.length);
-    delete originalNetworkRequest.redirects;
-    if (previousRedirects.length > 0)
-      originalNetworkRequest.redirectSource = previousRedirects[previousRedirects.length - 1];
+    var redirectCount = 0;
+    for (var redirect = originalNetworkRequest.redirectSource(); redirect; redirect = redirect.redirectSource())
+      redirectCount++;
+
+    originalNetworkRequest.setRequestId(requestId + ':redirected.' + redirectCount);
     this._finishNetworkRequest(originalNetworkRequest, time, -1);
     var newNetworkRequest = this._createNetworkRequest(
         requestId, originalNetworkRequest.frameId, originalNetworkRequest.loaderId, redirectURL,
         originalNetworkRequest.documentURL, originalNetworkRequest.initiator());
-    newNetworkRequest.redirects = previousRedirects.concat(originalNetworkRequest);
+    newNetworkRequest.setRedirectSource(originalNetworkRequest);
     return newNetworkRequest;
   }
 
@@ -700,7 +718,9 @@
    * @param {?Protocol.Network.Initiator} initiator
    */
   _createNetworkRequest(requestId, frameId, loaderId, url, documentURL, initiator) {
-    return new SDK.NetworkRequest(this._manager, requestId, url, documentURL, frameId, loaderId, initiator);
+    var request = new SDK.NetworkRequest(requestId, url, documentURL, frameId, loaderId, initiator);
+    request[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager;
+    return request;
   }
 };
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
index 7de550b..b80bcd3 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
@@ -33,7 +33,6 @@
  */
 SDK.NetworkRequest = class extends Common.Object {
   /**
-   * @param {!SDK.NetworkManager} networkManager
    * @param {!Protocol.Network.RequestId} requestId
    * @param {string} url
    * @param {string} documentURL
@@ -41,10 +40,9 @@
    * @param {!Protocol.Network.LoaderId} loaderId
    * @param {?Protocol.Network.Initiator} initiator
    */
-  constructor(networkManager, requestId, url, documentURL, frameId, loaderId, initiator) {
+  constructor(requestId, url, documentURL, frameId, loaderId, initiator) {
     super();
 
-    this._networkManager = networkManager;
     this._requestId = requestId;
     this.setUrl(url);
     this._documentURL = documentURL;
@@ -52,6 +50,8 @@
     this._loaderId = loaderId;
     /** @type {?Protocol.Network.Initiator} */
     this._initiator = initiator;
+    /** @type {?SDK.NetworkRequest} */
+    this._redirectSource = null;
     this._issueTime = -1;
     this._startTime = -1;
     this._endTime = -1;
@@ -529,7 +529,8 @@
     } else {
       this._path = this._parsedURL.host + this._parsedURL.folderPathComponents;
 
-      var inspectedURL = this._networkManager.target().inspectedURL().asParsedURL();
+      var networkManager = SDK.NetworkManager.forRequest(this);
+      var inspectedURL = networkManager ? networkManager.target().inspectedURL().asParsedURL() : null;
       this._path = this._path.trimURL(inspectedURL ? inspectedURL.host : '');
       if (this._parsedURL.lastPathComponent || this._parsedURL.queryParams) {
         this._name =
@@ -589,17 +590,15 @@
   /**
    * @return {?SDK.NetworkRequest}
    */
-  get redirectSource() {
-    if (this.redirects && this.redirects.length > 0)
-      return this.redirects[this.redirects.length - 1];
+  redirectSource() {
     return this._redirectSource;
   }
 
   /**
-   * @param {?SDK.NetworkRequest} x
+   * @param {?SDK.NetworkRequest} originatingRequest
    */
-  set redirectSource(x) {
-    this._redirectSource = x;
+  setRedirectSource(originatingRequest) {
+    this._redirectSource = originatingRequest;
   }
 
   /**
@@ -1088,13 +1087,6 @@
     this._eventSourceMessages.push(message);
     this.dispatchEventToListeners(SDK.NetworkRequest.Events.EventSourceMessageAdded, message);
   }
-
-  /**
-   * @return {!SDK.NetworkManager}
-   */
-  networkManager() {
-    return this._networkManager;
-  }
 };
 
 /** @enum {symbol} */
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
index a7a6b816..53a5e6c8 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -64,7 +64,8 @@
    * @return {?SDK.ResourceTreeFrame}
    */
   static frameForRequest(request) {
-    var resourceTreeModel = request.networkManager().target().model(SDK.ResourceTreeModel);
+    var networkManager = SDK.NetworkManager.forRequest(request);
+    var resourceTreeModel = networkManager ? networkManager.target().model(SDK.ResourceTreeModel) : null;
     if (!resourceTreeModel)
       return null;
     return resourceTreeModel.frameForId(request.frameId);
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
index 66e9556..900ed24 100644
--- a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
+++ b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
@@ -4,7 +4,7 @@
 
 /* eslint-disable no-console */
 
-/** @type {!{notifyDone: function()}|undefined} */
+/** @type {!{logToStderr: function(), notifyDone: function()}|undefined} */
 self.testRunner;
 
 TestRunner.executeTestScript = function() {
@@ -58,6 +58,16 @@
 };
 
 /**
+ * @param {!Array<string>} textArray
+ */
+TestRunner.addResults = function(textArray) {
+  if (!textArray)
+    return;
+  for (var i = 0, size = textArray.length; i < size; ++i)
+    TestRunner.addResult(textArray[i]);
+};
+
+/**
  * @param {!Array<function()>} tests
  */
 TestRunner.runTests = function(tests) {
@@ -80,9 +90,40 @@
 /**
  * @param {!Object} receiver
  * @param {string} methodName
+ * @param {!Function} override
+ * @param {boolean} opt_sticky
+ */
+TestRunner.addSniffer = function(receiver, methodName, override, opt_sticky) {
+  override = TestRunner.safeWrap(override);
+
+  var original = receiver[methodName];
+  if (typeof original !== 'function')
+    throw new Error('Cannot find method to override: ' + methodName);
+
+  receiver[methodName] = function(var_args) {
+    try {
+      var result = original.apply(this, arguments);
+    } finally {
+      if (!opt_sticky)
+        receiver[methodName] = original;
+    }
+    // In case of exception the override won't be called.
+    try {
+      Array.prototype.push.call(arguments, result);
+      override.apply(this, arguments);
+    } catch (e) {
+      throw new Error('Exception in overriden method \'' + methodName + '\': ' + e);
+    }
+    return result;
+  };
+};
+
+/**
+ * @param {!Object} receiver
+ * @param {string} methodName
  * @return {!Promise<*>}
  */
-TestRunner.addSniffer = function(receiver, methodName) {
+TestRunner.addSnifferPromise = function(receiver, methodName) {
   return new Promise(function(resolve, reject) {
     var original = receiver[methodName];
     if (typeof original !== 'function') {
@@ -110,6 +151,14 @@
 };
 
 /**
+ * @param {string} module
+ * @return {!Promise<undefined>}
+ */
+TestRunner.loadModule = function(module) {
+  return self.runtime.loadModulePromise(module);
+};
+
+/**
  * @param {!Array<string>} lazyModules
  * @return {!Promise<!Array<undefined>>}
  */
@@ -118,6 +167,14 @@
 };
 
 /**
+ * @param {string} panel
+ * @return {!Promise<!UI.Panel>}
+ */
+TestRunner.loadPanel = function(panel) {
+  return UI.inspectorView.panel(panel);
+};
+
+/**
  * @param {string} key
  * @param {boolean=} ctrlKey
  * @param {boolean=} altKey
@@ -137,6 +194,43 @@
   });
 };
 
+/**
+ * @param {!Function} func
+ * @param {!Function=} onexception
+ * @return {!Function}
+ */
+TestRunner.safeWrap = function(func, onexception) {
+  /**
+   * @this {*}
+   */
+  function result() {
+    if (!func)
+      return;
+    var wrapThis = this;
+    try {
+      return func.apply(wrapThis, arguments);
+    } catch (e) {
+      TestRunner.addResult('Exception while running: ' + func + '\n' + (e.stack || e));
+      if (onexception)
+        TestRunner.safeWrap(onexception)();
+      else
+        TestRunner.completeTest();
+    }
+  }
+  return result;
+};
+
+/**
+ * @param {!Function} testFunction
+ * @return {!Function}
+ */
+function debugTest(testFunction) {
+  self.test = testFunction;
+  TestRunner.addResult = console.log;
+  TestRunner.completeTest = () => console.log('Test completed');
+  return () => {};
+}
+
 (function() {
   /**
    * @param {string|!Event} message
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/module.json b/third_party/WebKit/Source/devtools/front_end/test_runner/module.json
index ebd476c4..715a8db 100644
--- a/third_party/WebKit/Source/devtools/front_end/test_runner/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/test_runner/module.json
@@ -1,4 +1,7 @@
 {
+  "dependencies": [
+    "ui"
+  ],
   "scripts": [
     "TestRunner.js"
   ]
diff --git a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py
index 35bf161..3c4c487f 100755
--- a/third_party/WebKit/Source/devtools/scripts/compile_frontend.py
+++ b/third_party/WebKit/Source/devtools/scripts/compile_frontend.py
@@ -110,6 +110,7 @@
 application_descriptors = [
     'inspector.json',
     'toolbox.json',
+    'integration_test_runner.json',
     'unit_test_runner.json',
     'formatter_worker.json',
     'heap_snapshot_worker.json',
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 9cb78c37..d7ac2f59 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
@@ -20,6 +20,7 @@
 const APPLICATION_DESCRIPTORS = [
   'inspector.json',
   'toolbox.json',
+  'integration_test_runner.json',
   'unit_test_runner.json',
   'formatter_worker.json',
   'heap_snapshot_worker.json',
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
index 263ee29..b5ff0b1 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
@@ -48,7 +48,7 @@
                             MessageLevel,
                             const String& message,
                             SourceLocation*) override {}
-  void PostMessageToPageInspector(const String&) override {}
+  void PostMessageToPageInspector(int session_id, const String&) override {}
   void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override {}
   void DidEvaluateWorkerScript(bool success) override {}
   void DidCloseWorkerGlobalScope() override {}
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
index db94ccde..114d28f 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -261,8 +261,9 @@
                                  message.column_number, nullptr)));
 }
 
-void WebEmbeddedWorkerImpl::PostMessageToPageInspector(const String& message) {
-  worker_inspector_proxy_->DispatchMessageFromWorker(message);
+void WebEmbeddedWorkerImpl::PostMessageToPageInspector(int session_id,
+                                                       const String& message) {
+  worker_inspector_proxy_->DispatchMessageFromWorker(session_id, message);
 }
 
 void WebEmbeddedWorkerImpl::PrepareShadowPageForLoader() {
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
index 782b87af..e526ac9 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
@@ -78,7 +78,7 @@
                                const WebString& message) override;
   void AddMessageToConsole(const WebConsoleMessage&) override;
 
-  void PostMessageToPageInspector(const WTF::String&);
+  void PostMessageToPageInspector(int session_id, const WTF::String&);
   std::unique_ptr<blink::WebURLLoader> CreateURLLoader() override {
     // TODO(yhirano): Stop using Platform::CreateURLLoader() here.
     return Platform::Current()->CreateURLLoader();
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index 5ca48a5..c887b77 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -435,6 +435,7 @@
 // Parses basic-card data to avoid parsing JSON in the browser.
 void SetBasicCardMethodData(const ScriptValue& input,
                             PaymentMethodDataPtr& output,
+                            ExecutionContext& execution_context,
                             ExceptionState& exception_state) {
   BasicCardRequest basic_card;
   V8BasicCardRequest::toImpl(input.GetIsolate(), input.V8Value(), basic_card,
@@ -483,6 +484,12 @@
         }
       }
     }
+
+    if (output->supported_types.size() != arraysize(kBasicCardTypes)) {
+      execution_context.AddConsoleMessage(ConsoleMessage::Create(
+          kJSMessageSource, kWarningMessageLevel,
+          "Cannot yet distinguish credit, debit, and prepaid cards."));
+    }
   }
 }
 
@@ -490,6 +497,7 @@
     const Vector<String>& supported_methods,
     const ScriptValue& input,
     PaymentMethodDataPtr& output,
+    ExecutionContext& execution_context,
     ExceptionState& exception_state) {
   DCHECK(!input.IsEmpty());
   v8::Local<v8::String> value;
@@ -522,15 +530,11 @@
   }
   if (RuntimeEnabledFeatures::PaymentRequestBasicCardEnabled() &&
       supported_methods.Contains("basic-card")) {
-    SetBasicCardMethodData(input, output, exception_state);
+    SetBasicCardMethodData(input, output, execution_context, exception_state);
     if (exception_state.HadException())
       exception_state.ClearException();
   }
-}
 
-void CountPaymentRequestNetworkNameInSupportedMethods(
-    const Vector<String>& supported_methods,
-    ExecutionContext& execution_context) {
   for (size_t i = 0; i < arraysize(kBasicCardNetworks); ++i) {
     if (supported_methods.Contains(kBasicCardNetworks[i].name)) {
       Deprecation::CountDeprecation(
@@ -590,8 +594,6 @@
         return;
       }
     }
-    CountPaymentRequestNetworkNameInSupportedMethods(
-        modifier.supportedMethods(), execution_context);
 
     output.back()->method_data =
         payments::mojom::blink::PaymentMethodData::New();
@@ -600,7 +602,7 @@
     if (modifier.hasData() && !modifier.data().IsEmpty()) {
       StringifyAndParseMethodSpecificData(
           modifier.supportedMethods(), modifier.data(),
-          output.back()->method_data, exception_state);
+          output.back()->method_data, execution_context, exception_state);
     } else {
       output.back()->method_data->stringified_data = "";
     }
@@ -721,9 +723,6 @@
       }
     }
 
-    CountPaymentRequestNetworkNameInSupportedMethods(
-        payment_method_data.supportedMethods(), execution_context);
-
     output.push_back(payments::mojom::blink::PaymentMethodData::New());
     output.back()->supported_methods = payment_method_data.supportedMethods();
 
@@ -731,7 +730,7 @@
         !payment_method_data.data().IsEmpty()) {
       StringifyAndParseMethodSpecificData(
           payment_method_data.supportedMethods(), payment_method_data.data(),
-          output.back(), exception_state);
+          output.back(), execution_context, exception_state);
     } else {
       output.back()->stringified_data = "";
     }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
index 45e215b..8cf550e6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
@@ -511,6 +511,7 @@
 }
 
 void ServiceWorkerGlobalScopeProxy::PostMessageToPageInspector(
+    int session_id,
     const String& message) {
   DCHECK(embedded_worker_);
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
@@ -519,7 +520,8 @@
       ->PostTask(
           BLINK_FROM_HERE,
           CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
-                          CrossThreadUnretained(embedded_worker_), message));
+                          CrossThreadUnretained(embedded_worker_), session_id,
+                          message));
 }
 
 void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
index 15cad682..6b0ffc9 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
@@ -145,7 +145,7 @@
                             MessageLevel,
                             const String& message,
                             SourceLocation*) override;
-  void PostMessageToPageInspector(const String&) override;
+  void PostMessageToPageInspector(int session_id, const String&) override;
   void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
   void DidInitializeWorkerContext() override;
   void WillEvaluateWorkerScript(size_t script_size,
diff --git a/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp b/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
index 67e0bf8..fbec9e5 100644
--- a/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
+++ b/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
@@ -104,12 +104,6 @@
 
 ScriptPromise NavigatorShare::share(ScriptState* script_state,
                                     const ShareData& share_data) {
-  String error_message;
-  if (!ExecutionContext::From(script_state)->IsSecureContext(error_message)) {
-    DOMException* error = DOMException::Create(kSecurityError, error_message);
-    return ScriptPromise::RejectWithDOMException(script_state, error);
-  }
-
   Document* doc = ToDocument(ExecutionContext::From(script_state));
   DCHECK(doc);
   KURL full_url = doc->CompleteURL(share_data.url());
diff --git a/third_party/WebKit/Source/modules/webshare/NavigatorShare.idl b/third_party/WebKit/Source/modules/webshare/NavigatorShare.idl
index 49cdd07f..a5c4b308 100644
--- a/third_party/WebKit/Source/modules/webshare/NavigatorShare.idl
+++ b/third_party/WebKit/Source/modules/webshare/NavigatorShare.idl
@@ -7,6 +7,6 @@
 [
   OriginTrialEnabled=WebShare
 ] partial interface Navigator {
-  [CallWith=ScriptState, MeasureAs=WebShareShare]
+  [SecureContext, CallWith=ScriptState, MeasureAs=WebShareShare]
   Promise<void> share(ShareData data);
 };
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
index 171e6a32..44f49632 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
@@ -31,8 +31,8 @@
       local_state.Clip()->LocalTransformSpace();
   if (transform_node != ancestor_state.Transform()) {
     const TransformationMatrix& local_to_ancestor_matrix =
-        GeometryMapper::LocalToAncestorMatrix(transform_node,
-                                              ancestor_state.Transform());
+        GeometryMapper::SourceToDestinationProjection(
+            transform_node, ancestor_state.Transform());
     // Clips are only in descendant spaces that are transformed by one
     // or more scrolls.
     DCHECK(local_to_ancestor_matrix.IsIdentityOrTranslation());
@@ -121,8 +121,8 @@
           const TransformPaintPropertyNode* transform_node =
               paired_state->Effect()->LocalTransformSpace();
           const TransformationMatrix& local_to_ancestor_matrix =
-              GeometryMapper::LocalToAncestorMatrix(transform_node,
-                                                    paired_state->Transform());
+              GeometryMapper::SourceToDestinationProjection(
+                  transform_node, paired_state->Transform());
           // Effects are only in descendant spaces that are transformed by one
           // or more scrolls.
           DCHECK(local_to_ancestor_matrix.IsIdentityOrTranslation());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
index d744746..29415f55 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp
@@ -9,60 +9,111 @@
 
 namespace blink {
 
-const TransformationMatrix& GeometryMapper::IdentityMatrix() {
-  DEFINE_STATIC_LOCAL(TransformationMatrix, identity, (TransformationMatrix()));
-  return identity;
-}
-
-const FloatClipRect& GeometryMapper::InfiniteClip() {
-  DEFINE_STATIC_LOCAL(FloatClipRect, infinite, (FloatClipRect()));
-  return infinite;
-}
-
-FloatClipRect& GeometryMapper::TempRect() {
-  DEFINE_STATIC_LOCAL(FloatClipRect, temp, (FloatClipRect()));
-  return temp;
-}
-
-void GeometryMapper::SourceToDestinationVisualRect(
-    const PropertyTreeState& source_state,
-    const PropertyTreeState& destination_state,
-    FloatClipRect& rect) {
+const TransformationMatrix& GeometryMapper::SourceToDestinationProjection(
+    const TransformPaintPropertyNode* source,
+    const TransformPaintPropertyNode* destination) {
+  DCHECK(source && destination);
   bool success = false;
-  SourceToDestinationVisualRectInternal(source_state, destination_state, rect,
-                                        success);
+  const auto& result =
+      SourceToDestinationProjectionInternal(source, destination, success);
   DCHECK(success);
+  return result;
 }
 
-void GeometryMapper::SourceToDestinationVisualRectInternal(
-    const PropertyTreeState& source_state,
-    const PropertyTreeState& destination_state,
-    FloatClipRect& mapping_rect,
+// Returns flatten(destination_to_screen)^-1 * flatten(source_to_screen)
+//
+// In case that source and destination are coplanar in tree hierarchy [1],
+// computes destination_to_plane_root ^ -1 * source_to_plane_root.
+// It can be proved that [2] the result will be the same (except numerical
+// errors) when the plane root has invertible screen projection, and this
+// offers fallback definition when plane root is singular. For example:
+// <div style="transform:rotateY(90deg); overflow:scroll;">
+//   <div id="A" style="opacity:0.5;">
+//     <div id="B" style="position:absolute;"></div>
+//   </div>
+// </div>
+// Both A and B have non-invertible screen projection, nevertheless it is
+// useful to define projection between A and B. Say, the transform may be
+// animated in compositor thus become visible.
+// As SPv1 treats 3D transforms as compositing trigger, that implies mappings
+// within the same compositing layer can only contain 2D transforms, thus
+// intra-composited-layer queries are guaranteed to be handled correctly.
+//
+// [1] As defined by that all local transforms between source and some common
+//     ancestor 'plane root' and all local transforms between the destination
+//     and the plane root being flat.
+// [2] destination_to_screen = plane_root_to_screen * destination_to_plane_root
+//     source_to_screen = plane_root_to_screen * source_to_plane_root
+//     output = flatten(destination_to_screen)^-1 * flatten(source_to_screen)
+//     = flatten(plane_root_to_screen * destination_to_plane_root)^-1 *
+//       flatten(plane_root_to_screen * source_to_plane_root)
+//     Because both destination_to_plane_root and source_to_plane_root are
+//     already flat,
+//     = flatten(plane_root_to_screen * flatten(destination_to_plane_root))^-1 *
+//       flatten(plane_root_to_screen * flatten(source_to_plane_root))
+//     By flatten lemma [3] flatten(A * flatten(B)) = flatten(A) * flatten(B),
+//     = flatten(destination_to_plane_root)^-1 *
+//       flatten(plane_root_to_screen)^-1 *
+//       flatten(plane_root_to_screen) * flatten(source_to_plane_root)
+//     If flatten(plane_root_to_screen) is invertible, they cancel out:
+//     = flatten(destination_to_plane_root)^-1 * flatten(source_to_plane_root)
+//     = destination_to_plane_root^-1 * source_to_plane_root
+// [3] Flatten lemma: https://goo.gl/DNKyOc
+const TransformationMatrix&
+GeometryMapper::SourceToDestinationProjectionInternal(
+    const TransformPaintPropertyNode* source,
+    const TransformPaintPropertyNode* destination,
     bool& success) {
-  LocalToAncestorVisualRectInternal(source_state, destination_state,
-                                    mapping_rect, success);
-  // Success if destinationState is an ancestor state.
-  if (success)
-    return;
+  DCHECK(source && destination);
+  DEFINE_STATIC_LOCAL(TransformationMatrix, identity, (TransformationMatrix()));
+  DEFINE_STATIC_LOCAL(TransformationMatrix, temp, (TransformationMatrix()));
 
-  // Otherwise first map to the lowest common ancestor, then map to destination.
-  const TransformPaintPropertyNode* lca_transform = LowestCommonAncestor(
-      source_state.Transform(), destination_state.Transform());
-  DCHECK(lca_transform);
+  if (source == destination) {
+    success = true;
+    return identity;
+  }
 
-  // Assume that the clip of destinationState is an ancestor of the clip of
-  // sourceState and is under the space of lcaTransform. Otherwise
-  // localToAncestorVisualRect() will fail.
-  PropertyTreeState lca_state = destination_state;
-  lca_state.SetTransform(lca_transform);
+  const GeometryMapperTransformCache& source_cache =
+      source->GetTransformCache();
+  const GeometryMapperTransformCache& destination_cache =
+      destination->GetTransformCache();
 
-  LocalToAncestorVisualRectInternal(source_state, lca_state, mapping_rect,
-                                    success);
-  if (!success)
-    return;
+  // Case 1: Check if source and destination are known to be coplanar.
+  // Even if destination may have invertible screen projection,
+  // this formula is likely to be numerically more stable.
+  if (source_cache.plane_root() == destination_cache.plane_root()) {
+    success = true;
+    if (source == destination_cache.plane_root())
+      return destination_cache.from_plane_root();
+    if (destination == source_cache.plane_root())
+      return source_cache.to_plane_root();
+    temp = destination_cache.from_plane_root();
+    temp.Multiply(source_cache.to_plane_root());
+    return temp;
+  }
 
-  AncestorToLocalRect(lca_transform, destination_state.Transform(),
-                      mapping_rect.Rect());
+  // Case 2: Check if we can fallback to the canonical definition of
+  // flatten(destination_to_screen)^-1 * flatten(source_to_screen)
+  // If flatten(destination_to_screen)^-1 is invalid, we are out of luck.
+  if (!destination_cache.projection_from_screen_is_valid()) {
+    success = false;
+    return identity;
+  }
+
+  // Case 3: Compute:
+  // flatten(destination_to_screen)^-1 * flatten(source_to_screen)
+  const auto* root = TransformPaintPropertyNode::Root();
+  success = true;
+  if (source == root)
+    return destination_cache.projection_from_screen();
+  if (destination == root) {
+    temp = source_cache.to_screen();
+  } else {
+    temp = destination_cache.projection_from_screen();
+    temp.Multiply(source_cache.to_screen());
+  }
+  temp.FlattenTo2d();
+  return temp;
 }
 
 void GeometryMapper::SourceToDestinationRect(
@@ -70,19 +121,11 @@
     const TransformPaintPropertyNode* destination_transform_node,
     FloatRect& mapping_rect) {
   bool success = false;
-  LocalToAncestorRectInternal(source_transform_node, destination_transform_node,
-                              mapping_rect, success);
-  // Success if destinationTransformNode is an ancestor of sourceTransformNode.
-  if (success)
-    return;
-
-  // Otherwise first map to the least common ancestor, then map to destination.
-  const TransformPaintPropertyNode* lca_transform =
-      LowestCommonAncestor(source_transform_node, destination_transform_node);
-  DCHECK(lca_transform);
-
-  LocalToAncestorRect(source_transform_node, lca_transform, mapping_rect);
-  AncestorToLocalRect(lca_transform, destination_transform_node, mapping_rect);
+  const TransformationMatrix& source_to_destination =
+      SourceToDestinationProjectionInternal(
+          source_transform_node, destination_transform_node, success);
+  mapping_rect =
+      success ? source_to_destination.MapRect(mapping_rect) : FloatRect();
 }
 
 void GeometryMapper::LocalToAncestorVisualRect(
@@ -111,18 +154,29 @@
     return;
   }
 
-  const auto& transform_matrix = LocalToAncestorMatrixInternal(
+  const auto& transform_matrix = SourceToDestinationProjectionInternal(
       local_state.Transform(), ancestor_state.Transform(), success);
   if (!success) {
+    // A failure implies either source-to-plane or destination-to-plane being
+    // singular. A notable example of singular source-to-plane from valid CSS:
+    // <div id="plane" style="transform:rotateY(180deg)">
+    //   <div style="overflow:overflow">
+    //     <div id="ancestor" style="opacity:0.5;">
+    //       <div id="local" style="position:absolute; transform:scaleX(0);">
+    //       </div>
+    //     </div>
+    //   </div>
+    // </div>
+    // Either way, the element won't be renderable thus returning empty rect.
+    success = true;
+    rect_to_map = FloatClipRect(FloatRect());
     return;
   }
-
   FloatRect mapped_rect = transform_matrix.MapRect(rect_to_map.Rect());
 
   const FloatClipRect& clip_rect =
       LocalToAncestorClipRectInternal(local_state.Clip(), ancestor_state.Clip(),
                                       ancestor_state.Transform(), success);
-
   if (success) {
     // This is where we propagate the rounded-ness of |clipRect| to
     // |rectToMap|.
@@ -155,11 +209,14 @@
 
     PropertyTreeState transform_and_clip_state(effect->LocalTransformSpace(),
                                                effect->OutputClip(), nullptr);
-    SourceToDestinationVisualRectInternal(last_transform_and_clip_state,
-                                          transform_and_clip_state,
-                                          mapping_rect, success);
-    if (!success)
+    LocalToAncestorVisualRectInternal(last_transform_and_clip_state,
+                                      transform_and_clip_state, mapping_rect,
+                                      success);
+    if (!success) {
+      success = true;
+      mapping_rect = FloatClipRect(FloatRect());
       return;
+    }
 
     mapping_rect.SetRect(effect->MapRect(mapping_rect.Rect()));
     last_transform_and_clip_state = transform_and_clip_state;
@@ -167,51 +224,9 @@
 
   PropertyTreeState final_transform_and_clip_state(
       ancestor_state.Transform(), ancestor_state.Clip(), nullptr);
-  SourceToDestinationVisualRectInternal(last_transform_and_clip_state,
-                                        final_transform_and_clip_state,
-                                        mapping_rect, success);
-}
-
-void GeometryMapper::LocalToAncestorRect(
-    const TransformPaintPropertyNode* local_transform_node,
-    const TransformPaintPropertyNode* ancestor_transform_node,
-    FloatRect& mapping_rect) {
-  bool success = false;
-  LocalToAncestorRectInternal(local_transform_node, ancestor_transform_node,
-                              mapping_rect, success);
-  DCHECK(success);
-}
-
-void GeometryMapper::LocalToAncestorRectInternal(
-    const TransformPaintPropertyNode* local_transform_node,
-    const TransformPaintPropertyNode* ancestor_transform_node,
-    FloatRect& mapping_rect,
-    bool& success) {
-  if (local_transform_node == ancestor_transform_node) {
-    success = true;
-    return;
-  }
-
-  const auto& transform_matrix = LocalToAncestorMatrixInternal(
-      local_transform_node, ancestor_transform_node, success);
-  if (!success)
-    return;
-  mapping_rect = transform_matrix.MapRect(mapping_rect);
-}
-
-void GeometryMapper::AncestorToLocalRect(
-    const TransformPaintPropertyNode* ancestor_transform_node,
-    const TransformPaintPropertyNode* local_transform_node,
-    FloatRect& rect) {
-  if (local_transform_node == ancestor_transform_node)
-    return;
-
-  const auto& transform_matrix =
-      LocalToAncestorMatrix(local_transform_node, ancestor_transform_node);
-  DCHECK(transform_matrix.IsInvertible());
-
-  // TODO(chrishtr): Cache the inverse?
-  rect = transform_matrix.Inverse().MapRect(rect);
+  LocalToAncestorVisualRectInternal(last_transform_and_clip_state,
+                                    final_transform_and_clip_state,
+                                    mapping_rect, success);
 }
 
 const FloatClipRect& GeometryMapper::LocalToAncestorClipRect(
@@ -227,75 +242,18 @@
   return result;
 }
 
-const FloatClipRect& GeometryMapper::SourceToDestinationClipRect(
-    const PropertyTreeState& source_state,
-    const PropertyTreeState& destination_state) {
-  bool success = false;
-  const FloatClipRect& result = SourceToDestinationClipRectInternal(
-      source_state, destination_state, success);
-  DCHECK(success);
-
-  return result;
-}
-
-const FloatClipRect& GeometryMapper::SourceToDestinationClipRectInternal(
-    const PropertyTreeState& source_state,
-    const PropertyTreeState& destination_state,
-    bool& success) {
-  const FloatClipRect& result = LocalToAncestorClipRectInternal(
-      source_state.Clip(), destination_state.Clip(),
-      destination_state.Transform(), success);
-  // Success if destinationState is an ancestor state.
-  if (success)
-    return result;
-
-  // Otherwise first map to the lowest common ancestor, then map to
-  // destination.
-  const TransformPaintPropertyNode* lca_transform = LowestCommonAncestor(
-      source_state.Transform(), destination_state.Transform());
-  DCHECK(lca_transform);
-
-  // Assume that the clip of destinationState is an ancestor of the clip of
-  // sourceState and is under the space of lcaTransform. Otherwise
-  // localToAncestorClipRectInternal() will fail.
-  PropertyTreeState lca_state = destination_state;
-  lca_state.SetTransform(lca_transform);
-
-  const FloatClipRect& result2 = LocalToAncestorClipRectInternal(
-      source_state.Clip(), lca_state.Clip(), lca_state.Transform(), success);
-  if (!success) {
-    if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
-      // On SPv1 we may fail when the paint invalidation container creates an
-      // overflow clip (in ancestorState) which is not in localState of an
-      // out-of-flow positioned descendant. See crbug.com/513108 and layout
-      // test compositing/overflow/handle-non-ancestor-clip-parent.html (run
-      // with --enable-prefer-compositing-to-lcd-text) for details.
-      // Ignore it for SPv1 for now.
-      success = true;
-    }
-    return result2;
-  }
-  if (!result2.IsInfinite()) {
-    FloatRect rect = result2.Rect();
-    AncestorToLocalRect(lca_transform, destination_state.Transform(), rect);
-    FloatClipRect& temp = TempRect();
-    temp.SetRect(rect);
-    if (result2.HasRadius())
-      temp.SetHasRadius();
-    return temp;
-  }
-  return result2;
-}
-
 const FloatClipRect& GeometryMapper::LocalToAncestorClipRectInternal(
     const ClipPaintPropertyNode* descendant,
     const ClipPaintPropertyNode* ancestor_clip,
     const TransformPaintPropertyNode* ancestor_transform,
     bool& success) {
+  DEFINE_STATIC_LOCAL(FloatClipRect, infinite, (FloatClipRect()));
+  DEFINE_STATIC_LOCAL(FloatClipRect, empty, (FloatRect()));
+
   FloatClipRect clip;
   if (descendant == ancestor_clip) {
     success = true;
-    return InfiniteClip();
+    return infinite;
   }
 
   const ClipPaintPropertyNode* clip_node = descendant;
@@ -317,19 +275,29 @@
   }
   if (!clip_node) {
     success = false;
-    return InfiniteClip();
+    if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+      // On SPv1 we may fail when the paint invalidation container creates an
+      // overflow clip (in ancestorState) which is not in localState of an
+      // out-of-flow positioned descendant. See crbug.com/513108 and layout
+      // test compositing/overflow/handle-non-ancestor-clip-parent.html (run
+      // with --enable-prefer-compositing-to-lcd-text) for details.
+      // Ignore it for SPv1 for now.
+      success = true;
+    }
+    return infinite;
   }
 
   // Iterate down from the top intermediate node found in the previous loop,
   // computing and memoizing clip rects as we go.
   for (auto it = intermediate_nodes.rbegin(); it != intermediate_nodes.rend();
        ++it) {
-    success = false;
     const TransformationMatrix& transform_matrix =
-        LocalToAncestorMatrixInternal((*it)->LocalTransformSpace(),
-                                      ancestor_transform, success);
-    if (!success)
-      return InfiniteClip();
+        SourceToDestinationProjectionInternal((*it)->LocalTransformSpace(),
+                                              ancestor_transform, success);
+    if (!success) {
+      success = true;
+      return empty;
+    }
     FloatRect mapped_rect = transform_matrix.MapRect((*it)->ClipRect().Rect());
     clip.Intersect(mapped_rect);
     if ((*it)->ClipRect().IsRounded())
@@ -338,81 +306,13 @@
     (*it)->GetClipCache().SetCachedClip(clip_and_transform, clip);
   }
 
-  success = true;
-
   const FloatClipRect* cached_clip =
       descendant->GetClipCache().GetCachedClip(clip_and_transform);
   DCHECK(cached_clip);
   CHECK(clip.HasRadius() == cached_clip->HasRadius());
-  return *cached_clip;
-}
 
-const TransformationMatrix& GeometryMapper::LocalToAncestorMatrix(
-    const TransformPaintPropertyNode* local_transform_node,
-    const TransformPaintPropertyNode* ancestor_transform_node) {
-  bool success = false;
-  const auto& result = LocalToAncestorMatrixInternal(
-      local_transform_node, ancestor_transform_node, success);
-  DCHECK(success);
-  return result;
-}
-
-const TransformationMatrix& GeometryMapper::LocalToAncestorMatrixInternal(
-    const TransformPaintPropertyNode* local_transform_node,
-    const TransformPaintPropertyNode* ancestor_transform_node,
-    bool& success) {
-  if (local_transform_node == ancestor_transform_node) {
-    success = true;
-    return IdentityMatrix();
-  }
-
-  const TransformPaintPropertyNode* transform_node = local_transform_node;
-  Vector<const TransformPaintPropertyNode*> intermediate_nodes;
-  TransformationMatrix transform_matrix;
-
-  // Iterate over the path from localTransformNode to ancestorState.transform.
-  // Stop if we've found a memoized (precomputed) transform for any particular
-  // node.
-  while (transform_node && transform_node != ancestor_transform_node) {
-    if (const TransformationMatrix* cached_matrix =
-            transform_node->GetTransformCache().GetCachedTransform(
-                ancestor_transform_node)) {
-      transform_matrix = *cached_matrix;
-      break;
-    }
-
-    intermediate_nodes.push_back(transform_node);
-    transform_node = transform_node->Parent();
-  }
-  if (!transform_node) {
-    success = false;
-    return IdentityMatrix();
-  }
-
-  // Iterate down from the top intermediate node found in the previous loop,
-  // computing and memoizing transforms as we go.
-  for (auto it = intermediate_nodes.rbegin(); it != intermediate_nodes.rend();
-       it++) {
-    TransformationMatrix local_transform_matrix = (*it)->Matrix();
-    local_transform_matrix.ApplyTransformOrigin((*it)->Origin());
-
-    // Flattening Lemma: flatten(A * flatten(B)) = flatten(flatten(A) * B).
-    // goo.gl/DNKyOc. Thus we can flatten transformMatrix rather than
-    // localTransformMatrix, because GeometryMapper only supports transforms
-    // into a flattened destination space.
-    if ((*it)->FlattensInheritedTransform())
-      transform_matrix.FlattenTo2d();
-
-    transform_matrix = transform_matrix * local_transform_matrix;
-    (*it)->GetTransformCache().SetCachedTransform(ancestor_transform_node,
-                                                  transform_matrix);
-  }
   success = true;
-  const TransformationMatrix* cached_matrix =
-      local_transform_node->GetTransformCache().GetCachedTransform(
-          ancestor_transform_node);
-  DCHECK(cached_matrix);
-  return *cached_matrix;
+  return *cached_clip;
 }
 
 void GeometryMapper::ClearCache() {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
index 559e131c..200ca82b 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.h
@@ -7,11 +7,12 @@
 
 #include "platform/graphics/paint/FloatClipRect.h"
 #include "platform/graphics/paint/PropertyTreeState.h"
-#include "platform/transforms/TransformationMatrix.h"
 #include "platform/wtf/HashMap.h"
 
 namespace blink {
 
+class TransformationMatrix;
+
 // GeometryMapper is a helper class for fast computations of transformed and
 // visual rects in different PropertyTreeStates. The design document has a
 // number of details on use cases, algorithmic definitions, and running times.
@@ -31,34 +32,19 @@
   STATIC_ONLY(GeometryMapper);
 
  public:
-  // The runtime of m calls among localToAncestorVisualRect, localToAncestorRect
-  // or ancestorToLocalRect with the same |ancestorState| parameter is
-  // guaranteed to be O(n + m), where n is the number of transform and clip
-  // nodes in their respective property trees.
-
-  // If the clips and transforms of |sourceState| are equal to or descendants of
-  // those of |destinationState|, returns the same value as
-  // localToAncestorVisualRect. Otherwise, maps the input rect to the
-  // transform state which is the lowest common ancestor of
-  // |sourceState.transform| and |destinationState.transform|, then multiplies
-  // it by the the inverse transform mapping from the lowest common ancestor to
-  // |destinationState.transform|.
-  //
-  // DCHECK fails if the clip of |destinationState| is not an ancestor of the
-  // clip of |sourceState|, or the inverse transform is not invertible.
-  //
-  // |mappingRect| is both input and output.
-  //
-  // The output FloatClipRect may contain false positives for rounded-ness
-  // if a rounded clip is clipped out, and overly conservative results
-  // in the presences of transforms.
-  //
-  // TODO(chrishtr): we should provide a variant of these methods that
-  // guarantees a tight result, or else signals an error. crbug.com/708741
-  static void SourceToDestinationVisualRect(
-      const PropertyTreeState& source_state,
-      const PropertyTreeState& destination_state,
-      FloatClipRect& mapping_rect);
+  // Returns the matrix that is suitable to map geometries on the source plane
+  // to some backing in the destination plane.
+  // Formal definition:
+  //   output = flatten(destination_to_screen)^-1 * flatten(source_to_screen)
+  // There are some cases that flatten(destination_to_screen) being
+  // singular yet we can still define a reasonable projection, for example:
+  // 1. Both nodes inherited a common singular flat ancestor:
+  // 2. Both nodes are co-planar to a common singular ancestor:
+  // Not every cases outlined above are supported!
+  // Read implementation comments for specific restrictions.
+  static const TransformationMatrix& SourceToDestinationProjection(
+      const TransformPaintPropertyNode* source,
+      const TransformPaintPropertyNode* destination);
 
   // Same as sourceToDestinationVisualRect() except that only transforms are
   // applied.
@@ -69,6 +55,16 @@
       const TransformPaintPropertyNode* destination_transform_node,
       FloatRect& mapping_rect);
 
+  // Returns the "clip visual rect" between |localTransformState| and
+  // |ancestorState|. See above for the definition of "clip visual rect".
+  //
+  // The output FloatClipRect may contain false positives for rounded-ness
+  // if a rounded clip is clipped out, and overly conservative results
+  // in the presences of transforms.
+  static const FloatClipRect& LocalToAncestorClipRect(
+      const PropertyTreeState& local_transform_state,
+      const PropertyTreeState& ancestor_state);
+
   // Maps from a rect in |localTransformSpace| to its visual rect in
   // |ancestorState|. This is computed by multiplying the rect by its combined
   // transform between |localTransformSpace| and |ancestorSpace|, then
@@ -87,71 +83,14 @@
   // The output FloatClipRect may contain false positives for rounded-ness
   // if a rounded clip is clipped out, and overly conservative results
   // in the presences of transforms.
+  //
+  // TODO(chrishtr): we should provide a variant of these methods that
+  // guarantees a tight result, or else signals an error. crbug.com/708741
   static void LocalToAncestorVisualRect(
       const PropertyTreeState& local_transform_state,
       const PropertyTreeState& ancestor_state,
       FloatClipRect& mapping_rect);
 
-  // Maps from a rect in |localTransformNode| space to its transformed rect in
-  // |ancestorTransformNode| space. This is computed by multiplying the rect by
-  // the combined transform between |localTransformNode| and
-  // |ancestorTransformNode|, then flattening into 2D space.
-  //
-  // DCHECK fails if |localTransformNode| is not equal to or a descendant of
-  // |ancestorTransformNode|.
-  //
-  //|mappingRect| is both input and output.
-  static void LocalToAncestorRect(
-      const TransformPaintPropertyNode* local_transform_node,
-      const TransformPaintPropertyNode* ancestor_transform_node,
-      FloatRect& mapping_rect);
-
-  // Maps from a rect in |ancestorTransformNode| space to its transformed rect
-  // in |localTransformNode| space. This is computed by multiplying the rect by
-  // the inverse combined transform between |localTransformNode| and
-  // |ancestorTransformNode|, if the transform is invertible.
-  //
-  // DCHECK fails if the combined transform is not invertible, or
-  // |localTransformNode| is not equal to or a descendant of
-  // |ancestorTransformNode|.
-  //
-  // |mappingRect| is both input and output.
-  static void AncestorToLocalRect(
-      const TransformPaintPropertyNode* ancestor_transform_node,
-      const TransformPaintPropertyNode* local_transform_node,
-      FloatRect& mapping_rect);
-
-  // Returns the matrix used in |LocalToAncestorRect|. DCHECK fails iff
-  // |localTransformNode| is not equal to or a descendant of
-  // |ancestorTransformNode|.
-  // This matrix may not be flattened. Since GeometryMapper only supports
-  // flattened ancestor spaces, the returned matrix must be flattened to have
-  // the correct semantics (calling mapRect() on it implicitly applies
-  // flattening to the input; flattenTo2d() does it explicitly to tme matrix).
-  static const TransformationMatrix& LocalToAncestorMatrix(
-      const TransformPaintPropertyNode* local_transform_node,
-      const TransformPaintPropertyNode* ancestor_transform_node);
-
-  // Returns the "clip visual rect" between |localTransformState| and
-  // |ancestorState|. See above for the definition of "clip visual rect".
-  //
-  // The output FloatClipRect may contain false positives for rounded-ness
-  // if a rounded clip is clipped out, and overly conservative results
-  // in the presences of transforms.
-  static const FloatClipRect& LocalToAncestorClipRect(
-      const PropertyTreeState& local_transform_state,
-      const PropertyTreeState& ancestor_state);
-
-  // Like localToAncestorClipRect, except it can handle destination transform
-  // spaces which are not direct ancestors of the source transform space.
-  //
-  // The output FloatClipRect may contain false positives for rounded-ness
-  // if a rounded clip is clipped out, and overly conservative results
-  // in the presences of transforms.
-  static const FloatClipRect& SourceToDestinationClipRect(
-      const PropertyTreeState& source_state,
-      const PropertyTreeState& destination_state);
-
   // Returns the lowest common ancestor in the paint property tree.
   template <typename NodeType>
   static PLATFORM_EXPORT const NodeType* LowestCommonAncestor(const NodeType*,
@@ -165,27 +104,9 @@
   // successful on return. See comments of the public functions for failure
   // conditions.
 
-  static void SourceToDestinationVisualRectInternal(
-      const PropertyTreeState& source_state,
-      const PropertyTreeState& destination_state,
-      FloatClipRect& mapping_rect,
-      bool& success);
-
-  static void LocalToAncestorVisualRectInternal(
-      const PropertyTreeState& local_transform_state,
-      const PropertyTreeState& ancestor_state,
-      FloatClipRect& mapping_rect,
-      bool& success);
-
-  static void LocalToAncestorRectInternal(
-      const TransformPaintPropertyNode* local_transform_node,
-      const TransformPaintPropertyNode* ancestor_transform_node,
-      FloatRect&,
-      bool& success);
-
-  static const TransformationMatrix& LocalToAncestorMatrixInternal(
-      const TransformPaintPropertyNode* local_transform_node,
-      const TransformPaintPropertyNode* ancestor_transform_node,
+  static const TransformationMatrix& SourceToDestinationProjectionInternal(
+      const TransformPaintPropertyNode* source,
+      const TransformPaintPropertyNode* destination,
       bool& success);
 
   static const FloatClipRect& LocalToAncestorClipRectInternal(
@@ -194,9 +115,10 @@
       const TransformPaintPropertyNode* ancestor_transform,
       bool& success);
 
-  static const FloatClipRect& SourceToDestinationClipRectInternal(
-      const PropertyTreeState& source_state,
-      const PropertyTreeState& destination_state,
+  static void LocalToAncestorVisualRectInternal(
+      const PropertyTreeState& local_transform_state,
+      const PropertyTreeState& ancestor_state,
+      FloatClipRect& mapping_rect,
       bool& success);
 
   static void SlowLocalToAncestorVisualRectWithEffects(
@@ -205,10 +127,6 @@
       FloatClipRect& mapping_rect,
       bool& success);
 
-  static const TransformationMatrix& IdentityMatrix();
-  static const FloatClipRect& InfiniteClip();
-  static FloatClipRect& TempRect();
-
   friend class GeometryMapperTest;
   friend class PaintLayerClipperTest;
 };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
index 9649b49..d809cb7 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTest.cpp
@@ -34,30 +34,12 @@
     return descendant_clip->GetClipCache().GetCachedClip(clip_and_transform);
   }
 
-  const TransformationMatrix* GetTransform(
-      const TransformPaintPropertyNode* descendant_transform,
-      const TransformPaintPropertyNode* ancestor_transform) {
-    return descendant_transform->GetTransformCache().GetCachedTransform(
-        ancestor_transform);
-  }
-
   const TransformPaintPropertyNode* LowestCommonAncestor(
       const TransformPaintPropertyNode* a,
       const TransformPaintPropertyNode* b) {
     return GeometryMapper::LowestCommonAncestor(a, b);
   }
 
-  void SourceToDestinationVisualRectInternal(
-      const PropertyTreeState& source_state,
-      const PropertyTreeState& destination_state,
-      FloatRect& mapping_rect,
-      bool& success) {
-    FloatClipRect float_clip_rect(mapping_rect);
-    GeometryMapper::LocalToAncestorVisualRectInternal(
-        source_state, destination_state, float_clip_rect, success);
-    mapping_rect = float_clip_rect.Rect();
-  }
-
   void LocalToAncestorVisualRectInternal(
       const PropertyTreeState& local_state,
       const PropertyTreeState& ancestor_state,
@@ -69,15 +51,6 @@
     mapping_rect = float_clip_rect.Rect();
   }
 
-  void LocalToAncestorRectInternal(
-      const TransformPaintPropertyNode* local_transform_node,
-      const TransformPaintPropertyNode* ancestor_transform_node,
-      FloatRect& rect,
-      bool& success) {
-    GeometryMapper::LocalToAncestorRectInternal(
-        local_transform_node, ancestor_transform_node, rect, success);
-  }
-
  private:
 };
 
@@ -129,14 +102,14 @@
     EXPECT_EQ(has_radius, float_clip_rect.HasRadius());                        \
     EXPECT_CLIP_RECT_EQ(expectedClipInAncestorSpace, float_clip_rect);         \
     float_rect.SetRect(inputRect);                                             \
-    GeometryMapper::SourceToDestinationVisualRect(                             \
+    GeometryMapper::LocalToAncestorVisualRect(                                 \
         localPropertyTreeState, ancestorPropertyTreeState, float_rect);        \
     EXPECT_RECT_EQ(expectedVisualRect, float_rect.Rect());                     \
     EXPECT_EQ(has_radius, float_rect.HasRadius());                             \
     FloatRect test_mapped_rect = inputRect;                                    \
-    GeometryMapper::LocalToAncestorRect(localPropertyTreeState.Transform(),    \
-                                        ancestorPropertyTreeState.Transform(), \
-                                        test_mapped_rect);                     \
+    GeometryMapper::SourceToDestinationRect(                                   \
+        localPropertyTreeState.Transform(),                                    \
+        ancestorPropertyTreeState.Transform(), test_mapped_rect);              \
     EXPECT_RECT_EQ(expectedTransformedRect, test_mapped_rect);                 \
     test_mapped_rect = inputRect;                                              \
     GeometryMapper::SourceToDestinationRect(                                   \
@@ -145,11 +118,11 @@
     EXPECT_RECT_EQ(expectedTransformedRect, test_mapped_rect);                 \
     if (ancestorPropertyTreeState.Transform() !=                               \
         localPropertyTreeState.Transform()) {                                  \
-      const TransformationMatrix* transform_for_testing =                      \
-          GetTransform(localPropertyTreeState.Transform(),                     \
-                       ancestorPropertyTreeState.Transform());                 \
-      CHECK(transform_for_testing);                                            \
-      EXPECT_EQ(expectedTransformToAncestor, *transform_for_testing);          \
+      const TransformationMatrix& transform_for_testing =                      \
+          GeometryMapper::SourceToDestinationProjection(                       \
+              localPropertyTreeState.Transform(),                              \
+              ancestorPropertyTreeState.Transform());                          \
+      EXPECT_EQ(expectedTransformToAncestor, transform_for_testing);           \
     }                                                                          \
     if (ancestorPropertyTreeState.Clip() != localPropertyTreeState.Clip()) {   \
       const FloatClipRect* output_clip_for_testing =                           \
@@ -204,8 +177,8 @@
   CHECK_MAPPINGS(input, output, output, transform->Matrix(), FloatClipRect(),
                  local_state, PropertyTreeState::Root());
 
-  GeometryMapper::AncestorToLocalRect(TransformPaintPropertyNode::Root(),
-                                      local_state.Transform(), output);
+  GeometryMapper::SourceToDestinationRect(TransformPaintPropertyNode::Root(),
+                                          local_state.Transform(), output);
   EXPECT_RECT_EQ(input, output);
 }
 
@@ -271,11 +244,6 @@
   bool has_radius = false;
   CHECK_MAPPINGS(input, output, output, final, FloatClipRect(), local_state,
                  PropertyTreeState::Root());
-
-  // Check the cached matrix for the intermediate transform.
-  EXPECT_EQ(
-      rotate_transform,
-      *GetTransform(transform1.Get(), TransformPaintPropertyNode::Root()));
 }
 
 TEST_P(GeometryMapperTest, NestedTransformsFlattening) {
@@ -297,10 +265,11 @@
 
   FloatRect input(0, 0, 100, 100);
   rotate_transform.FlattenTo2d();
-  TransformationMatrix final = rotate_transform * inverse_rotate_transform;
-  FloatRect output = final.MapRect(input);
+  TransformationMatrix combined = rotate_transform * inverse_rotate_transform;
+  combined.FlattenTo2d();
+  FloatRect output = combined.MapRect(input);
   bool has_radius = false;
-  CHECK_MAPPINGS(input, output, output, final, FloatClipRect(), local_state,
+  CHECK_MAPPINGS(input, output, output, combined, FloatClipRect(), local_state,
                  PropertyTreeState::Root());
 }
 
@@ -329,10 +298,6 @@
   bool has_radius = false;
   CHECK_MAPPINGS(input, output, output, final, FloatClipRect(), local_state,
                  PropertyTreeState::Root());
-
-  // Check the cached matrix for the intermediate transform.
-  EXPECT_EQ(scale_transform, *GetTransform(transform1.Get(),
-                                           TransformPaintPropertyNode::Root()));
 }
 
 TEST_P(GeometryMapperTest, NestedTransformsIntermediateDestination) {
@@ -650,49 +615,26 @@
   PropertyTreeState transform2_state = PropertyTreeState::Root();
   transform2_state.SetTransform(transform2.Get());
 
-  bool success;
   FloatRect input(0, 0, 100, 100);
+  FloatClipRect result_clip(input);
+  GeometryMapper::LocalToAncestorVisualRect(transform1_state, transform2_state,
+                                            result_clip);
+  EXPECT_RECT_EQ(FloatRect(-100, 0, 100, 100), result_clip.Rect());
+
   FloatRect result = input;
-  LocalToAncestorVisualRectInternal(transform1_state, transform2_state, result,
-                                    success);
-  // Fails, because the transform2state is not an ancestor of transform1State.
-  EXPECT_FALSE(success);
-  EXPECT_RECT_EQ(input, result);
-
-  result = input;
-  LocalToAncestorRectInternal(transform1.Get(), transform2.Get(), result,
-                              success);
-  // Fails, because the transform2state is not an ancestor of transform1State.
-  EXPECT_FALSE(success);
-  EXPECT_RECT_EQ(input, result);
-
-  result = input;
-  LocalToAncestorVisualRectInternal(transform2_state, transform1_state, result,
-                                    success);
-  // Fails, because the transform1state is not an ancestor of transform2State.
-  EXPECT_FALSE(success);
-  EXPECT_RECT_EQ(input, result);
-
-  result = input;
-  LocalToAncestorRectInternal(transform2.Get(), transform1.Get(), result,
-                              success);
-  // Fails, because the transform1state is not an ancestor of transform2State.
-  EXPECT_FALSE(success);
-  EXPECT_RECT_EQ(input, result);
-
-  FloatRect expected =
-      rotate_transform2.Inverse().MapRect(rotate_transform1.MapRect(input));
-  result = input;
-  FloatClipRect float_clip_rect(result);
-  GeometryMapper::SourceToDestinationVisualRect(
-      transform1_state, transform2_state, float_clip_rect);
-  result = float_clip_rect.Rect();
-  EXPECT_RECT_EQ(expected, result);
-
-  result = input;
   GeometryMapper::SourceToDestinationRect(transform1.Get(), transform2.Get(),
                                           result);
-  EXPECT_RECT_EQ(expected, result);
+  EXPECT_RECT_EQ(FloatRect(-100, 0, 100, 100), result);
+
+  result_clip = FloatClipRect(input);
+  GeometryMapper::LocalToAncestorVisualRect(transform2_state, transform1_state,
+                                            result_clip);
+  EXPECT_RECT_EQ(FloatRect(0, -100, 100, 100), result_clip.Rect());
+
+  result = input;
+  GeometryMapper::SourceToDestinationRect(transform2.Get(), transform1.Get(),
+                                          result);
+  EXPECT_RECT_EQ(FloatRect(0, -100, 100, 100), result);
 }
 
 TEST_P(GeometryMapperTest, SiblingTransformsWithClip) {
@@ -712,7 +654,7 @@
 
   RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create(
       ClipPaintPropertyNode::Root(), transform2.Get(),
-      FloatRoundedRect(10, 10, 70, 70));
+      FloatRoundedRect(10, 20, 30, 40));
 
   PropertyTreeState transform1_state = PropertyTreeState::Root();
   transform1_state.SetTransform(transform1.Get());
@@ -722,46 +664,23 @@
 
   bool success;
   FloatRect input(0, 0, 100, 100);
-
-  // Test map from transform1State to transform2AndClipState.
-  FloatRect expected =
-      rotate_transform2.Inverse().MapRect(rotate_transform1.MapRect(input));
-
-  // sourceToDestinationVisualRect ignores clip from the common ancestor to
-  // destination.
   FloatRect result = input;
-  SourceToDestinationVisualRectInternal(
-      transform1_state, transform2_and_clip_state, result, success);
+  LocalToAncestorVisualRectInternal(transform1_state, transform2_and_clip_state,
+                                    result, success);
   // Fails, because the clip of the destination state is not an ancestor of the
-  // clip of the source state.
-  EXPECT_FALSE(success);
+  // clip of the source state. A known bug in SPv1 would make such query,
+  // in such case, no clips are applied.
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+    EXPECT_FALSE(success);
+  } else {
+    EXPECT_TRUE(success);
+    EXPECT_EQ(FloatRect(-100, 0, 100, 100), result);
+  }
 
-  // sourceToDestinationRect applies transforms only.
-  result = input;
-  GeometryMapper::SourceToDestinationRect(transform1.Get(), transform2.Get(),
-                                          result);
-  EXPECT_RECT_EQ(expected, result);
-
-  // Test map from transform2AndClipState to transform1State.
-  FloatRect expected_unclipped =
-      rotate_transform1.Inverse().MapRect(rotate_transform2.MapRect(input));
-  FloatRect expected_clipped = rotate_transform1.Inverse().MapRect(
-      rotate_transform2.MapRect(FloatRect(10, 10, 70, 70)));
-
-  // sourceToDestinationVisualRect ignores clip from the common ancestor to
-  // destination.
-  result = input;
-  FloatClipRect float_clip_rect(result);
-  GeometryMapper::SourceToDestinationVisualRect(
-      transform2_and_clip_state, transform1_state, float_clip_rect);
-  result = float_clip_rect.Rect();
-  EXPECT_RECT_EQ(expected_clipped, result);
-
-  // sourceToDestinationRect applies transforms only.
-  result = input;
-  GeometryMapper::SourceToDestinationRect(transform2.Get(), transform1.Get(),
-                                          result);
-  EXPECT_RECT_EQ(expected_unclipped, result);
+  FloatClipRect float_clip_rect(input);
+  GeometryMapper::LocalToAncestorVisualRect(transform2_and_clip_state,
+                                            transform1_state, float_clip_rect);
+  EXPECT_RECT_EQ(FloatRect(20, -40, 40, 30), float_clip_rect.Rect());
 }
 
 TEST_P(GeometryMapperTest, LowestCommonAncestor) {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.cpp b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.cpp
index c94c50a5..1634d58 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.cpp
@@ -4,49 +4,70 @@
 
 #include "platform/graphics/paint/GeometryMapperTransformCache.h"
 
+#include "platform/graphics/paint/TransformPaintPropertyNode.h"
+
 namespace blink {
 
 // All transform caches invalidate themselves by tracking a local cache
 // generation, and invalidating their cache if their cache generation disagrees
-// with s_transformCacheGeneration.
-static unsigned g_transform_cache_generation = 0;
-
-GeometryMapperTransformCache::GeometryMapperTransformCache()
-    : cache_generation_(g_transform_cache_generation) {}
+// with s_global_generation.
+unsigned GeometryMapperTransformCache::s_global_generation;
 
 void GeometryMapperTransformCache::ClearCache() {
-  g_transform_cache_generation++;
+  s_global_generation++;
 }
 
-void GeometryMapperTransformCache::InvalidateCacheIfNeeded() {
-  if (cache_generation_ != g_transform_cache_generation) {
-    transform_cache_.clear();
-    cache_generation_ = g_transform_cache_generation;
-  }
+// Computes flatten(m) ^ -1, return true if the inversion succeeded.
+static bool InverseProjection(TransformationMatrix m,
+                              TransformationMatrix& out) {
+  m.FlattenTo2d();
+  if (!m.IsInvertible())
+    return false;
+  out = m.Inverse();
+  return true;
 }
 
-const TransformationMatrix* GeometryMapperTransformCache::GetCachedTransform(
-    const TransformPaintPropertyNode* ancestor_transform) {
-  InvalidateCacheIfNeeded();
-  for (const auto& entry : transform_cache_) {
-    if (entry.ancestor_node == ancestor_transform) {
-      return &entry.to_ancestor;
-    }
-  }
-  return nullptr;
-}
+void GeometryMapperTransformCache::Update(
+    const TransformPaintPropertyNode& node) {
+  DCHECK_NE(cache_generation_, s_global_generation);
+  cache_generation_ = s_global_generation;
 
-void GeometryMapperTransformCache::SetCachedTransform(
-    const TransformPaintPropertyNode* ancestor_transform,
-    const TransformationMatrix& matrix) {
-  InvalidateCacheIfNeeded();
-#if DCHECK_IS_ON()
-  for (const auto& entry : transform_cache_) {
-    if (entry.ancestor_node == ancestor_transform)
-      DCHECK(false);  // There should be no existing entry.
+  if (!node.Parent()) {
+    to_screen_.MakeIdentity();
+    to_screen_is_invertible_ = true;
+    projection_from_screen_.MakeIdentity();
+    projection_from_screen_is_valid_ = true;
+    plane_root_ = &node;
+    to_plane_root_.MakeIdentity();
+    from_plane_root_.MakeIdentity();
+    return;
   }
-#endif
-  transform_cache_.push_back(TransformCacheEntry(ancestor_transform, matrix));
+
+  const GeometryMapperTransformCache& parent =
+      node.Parent()->GetTransformCache();
+
+  TransformationMatrix local = node.Matrix();
+  local.ApplyTransformOrigin(node.Origin());
+
+  to_screen_ = parent.to_screen_;
+  if (node.FlattensInheritedTransform())
+    to_screen_.FlattenTo2d();
+  to_screen_.Multiply(local);
+  to_screen_is_invertible_ = to_screen_.IsInvertible();
+  projection_from_screen_is_valid_ =
+      InverseProjection(to_screen_, projection_from_screen_);
+
+  if (!local.IsFlat() || !local.IsInvertible()) {
+    plane_root_ = &node;
+    to_plane_root_.MakeIdentity();
+    from_plane_root_.MakeIdentity();
+  } else {  // (local.IsFlat() && local.IsInvertible())
+    plane_root_ = parent.plane_root_;
+    to_plane_root_ = parent.to_plane_root_;
+    to_plane_root_.Multiply(local);
+    from_plane_root_ = local.Inverse();
+    from_plane_root_.Multiply(parent.from_plane_root_);
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.h b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.h
index 398fc0e..af40d94b 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/GeometryMapperTransformCache.h
@@ -14,44 +14,108 @@
 
 class TransformPaintPropertyNode;
 
-// A GeometryMapperTransformCache hangs off a TransformPaintPropertyNode. It
-// stores cached "transformed rects" (See GeometryMapper.h) from that node in
-// ancestor spaces.
+// A GeometryMapperTransformCache hangs off a TransformPaintPropertyNode.
+// It stores useful intermediate results such as screen matrix for geometry
+// queries.
 class PLATFORM_EXPORT GeometryMapperTransformCache {
   USING_FAST_MALLOC(GeometryMapperTransformCache);
-
  public:
-  GeometryMapperTransformCache();
-
-  // Returns the transformed rect (see GeometryMapper.h) of |this| in the
-  // space of |ancestorTransform|, if there is one cached. Otherwise returns
-  // null.
-  //
-  // These transforms are not flattened to 2d.
-  const TransformationMatrix* GetCachedTransform(
-      const TransformPaintPropertyNode* ancestor_transform);
-
-  // Stores the "transformed rect" of |this| in the space of |ancestors|,
-  // into a local cache.
-  void SetCachedTransform(const TransformPaintPropertyNode* ancestor_transform,
-                          const TransformationMatrix& to_ancestor);
+  GeometryMapperTransformCache() = default;
 
   static void ClearCache();
 
+  void UpdateIfNeeded(const TransformPaintPropertyNode& node) {
+    if (cache_generation_ != s_global_generation)
+      Update(node);
+    DCHECK_EQ(cache_generation_, s_global_generation);
+  }
+
+  const TransformationMatrix& to_screen() const { return to_screen_; }
+  bool to_screen_is_invertible() const { return to_screen_is_invertible_; }
+
+  const TransformationMatrix& projection_from_screen() const {
+    return projection_from_screen_;
+  }
+  bool projection_from_screen_is_valid() const {
+    return projection_from_screen_is_valid_;
+  }
+
+  const TransformationMatrix& to_plane_root() const { return to_plane_root_; }
+  const TransformationMatrix& from_plane_root() const {
+    return from_plane_root_;
+  }
+  const TransformPaintPropertyNode* plane_root() const { return plane_root_; }
+
  private:
-  struct TransformCacheEntry {
-    const TransformPaintPropertyNode* ancestor_node;
-    TransformationMatrix to_ancestor;
-    TransformCacheEntry(const TransformPaintPropertyNode* ancestor_node_arg,
-                        const TransformationMatrix& to_ancestor_arg)
-        : ancestor_node(ancestor_node_arg), to_ancestor(to_ancestor_arg) {}
-  };
+  void Update(const TransformPaintPropertyNode&);
 
-  void InvalidateCacheIfNeeded();
+  static unsigned s_global_generation;
 
-  Vector<TransformCacheEntry> transform_cache_;
-  unsigned cache_generation_;
-
+  // The cached values here can be categorized in two logical groups:
+  //
+  // [ Screen Transform ]
+  // to_screen : The screen matrix of the node, as defined by:
+  //   to_screen = (flattens_inherited_transform ?
+  //       flatten(parent.to_screen) : parent.to_screen) * local
+  // to_screen_is_invertible : Whether to_screen is invertible.
+  // projection_from_screen : Back projection from screen.
+  //   projection_from_screen = flatten(to_screen) ^ -1
+  //   Undefined if the inverse projection doesn't exist.
+  //   Guaranteed to be flat.
+  // projection_from_screen_is_valid : Whether projection_from_screen
+  //   is defined.
+  //
+  // [ Plane Root Transform ]
+  // plane_root : The oldest ancestor node such that every intermediate node
+  //   in the ancestor chain has a flat and invertible local matrix. In other
+  //   words, a node inherits its parent's plane_root if its local matrix is
+  //   flat and invertible. Otherwise, it becomes its own plane root.
+  //   For example:
+  //   <xfrm id="A" matrix="rotateY(10deg)">
+  //     <xfrm id="B" flatten_inherited matrix="translateX(10px)"/>
+  //     <xfrm id="C" matrix="scaleX(0)">
+  //       <xfrm id="D" matrix="scaleX(2)"/>
+  //       <xfrm id="E" matrix="rotate(30deg)"/>
+  //     </xfrm>
+  //     <xfrm id="F" matrix="scaleZ(0)"/>
+  //   </xfrm>
+  //   A is the plane root of itself because its local matrix is 3D.
+  //   B's plane root is A because its local matrix is flat.
+  //   C is the plane root of itself because its local matrix is non-invertible.
+  //   D and E's plane root is C because their local matrix is flat.
+  //   F is the plane root of itself because its local matrix is 3D and
+  //     non-invertible.
+  // to_plane_root : The accumulated matrix between this node and plane_root.
+  //   to_plane_root = (plane_root == this) ? I : parent.to_plane_root * local
+  //   Guaranteed to be flat.
+  // from_plane_root :
+  //   from_plane_root = to_plane_root ^ -1
+  //   Guaranteed to exist because each local matrices are invertible.
+  //   Guaranteed to be flat.
+  // An important invariant is that
+  //   flatten(to_screen) = flatten(plane_root.to_screen) * to_plane_root
+  //   Proof by induction:
+  //   If plane_root == this,
+  //     flatten(plane_root.to_screen) * to_plane_root = flatten(to_screen) * I
+  //     = flatten(to_screen)
+  //   Otherwise,
+  //     flatten(to_screen) = flatten((flattens_inherited_transform ?
+  //         flatten(parent.to_screen) : parent.to_screen) * local)
+  //     Because local is known to be flat,
+  //     = flatten((flattens_inherited_transform ?
+  //         flatten(parent.to_screen) : parent.to_screen) * flatten(local))
+  //     Then by flatten lemma (https://goo.gl/DNKyOc),
+  //     = flatten(parent.to_screen) * local
+  //     = flatten(parent.plane_root.to_screen) * parent.to_plane_root * local
+  //     = flatten(plane_root.to_screen) * to_plane_root
+  TransformationMatrix to_screen_;
+  TransformationMatrix projection_from_screen_;
+  TransformationMatrix to_plane_root_;
+  TransformationMatrix from_plane_root_;
+  const TransformPaintPropertyNode* plane_root_ = nullptr;
+  unsigned cache_generation_ = s_global_generation - 1;
+  unsigned to_screen_is_invertible_ : 1;
+  unsigned projection_from_screen_is_valid_ : 1;
   DISALLOW_COPY_AND_ASSIGN(GeometryMapperTransformCache);
 };
 
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
index 3ac42f2..5b39615 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -215,16 +215,13 @@
   // For access to getTransformCache() and setCachedTransform.
   friend class GeometryMapper;
   friend class GeometryMapperTest;
+  friend class GeometryMapperTransformCache;
 
-  GeometryMapperTransformCache& GetTransformCache() const {
-    return const_cast<TransformPaintPropertyNode*>(this)->GetTransformCache();
-  }
-
-  GeometryMapperTransformCache& GetTransformCache() {
-    if (!geometry_mapper_transform_cache_)
-      geometry_mapper_transform_cache_.reset(
-          new GeometryMapperTransformCache());
-    return *geometry_mapper_transform_cache_.get();
+  const GeometryMapperTransformCache& GetTransformCache() const {
+    if (!transform_cache_)
+      transform_cache_.reset(new GeometryMapperTransformCache);
+    transform_cache_->UpdateIfNeeded(*this);
+    return *transform_cache_;
   }
 
   RefPtr<const TransformPaintPropertyNode> parent_;
@@ -236,8 +233,7 @@
   CompositorElementId compositor_element_id_;
   RefPtr<ScrollPaintPropertyNode> scroll_;
 
-  std::unique_ptr<GeometryMapperTransformCache>
-      geometry_mapper_transform_cache_;
+  mutable std::unique_ptr<GeometryMapperTransformCache> transform_cache_;
 };
 
 // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.cpp b/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.cpp
index f88d1247..fa6bd56 100644
--- a/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.cpp
+++ b/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.cpp
@@ -26,4 +26,8 @@
   return provider_.ConsumeBool();
 }
 
+int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) {
+  return provider_.ConsumeInt32InRange(min, max);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.h b/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.h
index 5570538..0993e92 100644
--- a/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.h
+++ b/third_party/WebKit/Source/platform/testing/FuzzedDataProvider.h
@@ -30,6 +30,12 @@
   // Returns a bool, or false when no data remains.
   bool ConsumeBool();
 
+  // Returns a number in the range [min, max] by consuming bytes from the input
+  // data. The value might not be uniformly distributed in the given range. If
+  // there's no input data left, always returns |min|. |min| must be less than
+  // or equal to |max|.
+  int ConsumeInt32InRange(int min, int max);
+
   // Returns a value from |array|, consuming as many bytes as needed to do so.
   // |array| must be a fixed-size array.
   template <typename Type, size_t size>
diff --git a/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h b/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h
index 6e8e2b94..8975c7c 100644
--- a/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h
+++ b/third_party/WebKit/Source/platform/transforms/TransformationMatrix.h
@@ -439,6 +439,12 @@
     return result;
   }
 
+  bool IsFlat() const {
+    return matrix_[0][2] == 0.f && matrix_[1][2] == 0.f &&
+           matrix_[2][0] == 0.f && matrix_[2][1] == 0.f &&
+           matrix_[2][2] == 1.f && matrix_[2][3] == 0.f && matrix_[3][2] == 0.f;
+  }
+
   bool IsIdentityOrTranslation() const {
     return matrix_[0][0] == 1 && matrix_[0][1] == 0 && matrix_[0][2] == 0 &&
            matrix_[0][3] == 0 && matrix_[1][0] == 0 && matrix_[1][1] == 1 &&
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot_mock.py
index 159af39d..bb96fba 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot_mock.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot_mock.py
@@ -28,18 +28,21 @@
 
 from webkitpy.common.net.buildbot import BuildBot
 
-
+# TODO(qyearsley): To be consistent with other fake ("mock") classes, this
+# could be changed so it's not a subclass of BuildBot.
 class MockBuildBot(BuildBot):
 
     def __init__(self):
         super(MockBuildBot, self).__init__()
         self._canned_results = {}
         self._canned_retry_summary_json = {}
+        self.fetched_builds = []
 
     def set_results(self, build, results):
         self._canned_results[build] = results
 
     def fetch_results(self, build):
+        self.fetched_builds.append(build)
         return self._canned_results.get(build)
 
     def set_retry_sumary_json(self, build, content):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index 8fd5e53b..2dc24f5 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -728,7 +728,7 @@
             else:
                 path_in_wpt = filename
             return self._wpt_manifest().is_test_file(path_in_wpt)
-        if 'inspector-unit' in dirname:
+        if 'inspector-unit' in dirname or 'devtools-js' in dirname:
             return filesystem.splitext(filename)[1] == '.js'
         return Port._has_supported_extension(
             filesystem, filename) and not Port.is_reference_html_file(filesystem, dirname, filename)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
index 2d7e7404..19eb1f3 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater.py
@@ -31,6 +31,7 @@
         self.port = self.host.port_factory.get()
         self.finder = PathFinder(self.host.filesystem)
         self.ports_with_no_results = set()
+        self.ports_with_all_pass = set()
 
     def run(self, args=None):
         """Downloads text new baselines and adds test expectations lines."""
@@ -46,9 +47,9 @@
             _log.error('No issue on current branch.')
             return 1
 
-        builds = self.get_latest_try_jobs()
-        _log.debug('Latest try jobs: %r', builds)
-        if not builds:
+        build_to_status = self.get_latest_try_jobs()
+        _log.debug('Latest try jobs: %r', build_to_status)
+        if not build_to_status:
             _log.error('No try job information was collected.')
             return 1
 
@@ -57,7 +58,11 @@
 
         # Here we build up a dict of failing test results for all platforms.
         test_expectations = {}
-        for build in builds:
+        for build, job_status in build_to_status.iteritems():
+            if job_status.result == 'SUCCESS':
+                self.ports_with_all_pass.add(self.port_name(build))
+
+
             port_results = self.get_failing_results_dict(build)
             test_expectations = self.merge_dicts(test_expectations, port_results)
 
@@ -91,24 +96,32 @@
 
         Returns:
             A dictionary with the structure: {
-                'full-port-name': {
-                    'expected': 'TIMEOUT',
-                    'actual': 'CRASH',
-                    'bug': 'crbug.com/11111'
+                test-with-failing-result: {
+                    'full-port-name': {
+                        'expected': 'TIMEOUT',
+                        'actual': 'CRASH',
+                        'bug': 'crbug.com/11111'
+                    }
                 }
             }
-            If there are no failing results or no results could be fetched,
+            If results could be fetched but none are failing,
             this will return an empty dictionary.
         """
+        port_name = self.port_name(build)
+        if port_name in self.ports_with_all_pass:
+            # All tests passed, so there should be no failing results.
+            return {}
         layout_test_results = self.host.buildbot.fetch_results(build)
-        port_name = self.host.builders.port_name_for_builder_name(build.builder_name)
         if layout_test_results is None:
             _log.warning('No results for build %s', build)
-            self.ports_with_no_results.add(port_name)
+            self.ports_with_no_results.add(self.port_name(build))
             return {}
         test_results = [result for result in layout_test_results.didnt_run_as_expected_results() if not result.did_pass()]
-        failing_results_dict = self.generate_results_dict(port_name, test_results)
-        return failing_results_dict
+        return self.generate_results_dict(self.port_name(build), test_results)
+
+    @memoized
+    def port_name(self, build):
+        return self.host.builders.port_name_for_builder_name(build.builder_name)
 
     def generate_results_dict(self, full_port_name, test_results):
         """Makes a dict with results for one platform.
@@ -139,9 +152,10 @@
         Args:
             target: First dictionary, which is updated based on source.
             source: Second dictionary, not modified.
+            path: A list of keys, only used for making error messages.
 
         Returns:
-            An updated target dictionary.
+            The updated target dictionary.
         """
         path = path or []
         for key in source:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
index 7d50715..a7ae8218a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_expectations_updater_unittest.py
@@ -8,6 +8,7 @@
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.buildbot_mock import MockBuildBot
+from webkitpy.common.net.git_cl import TryJobStatus
 from webkitpy.common.net.layout_test_results import LayoutTestResult, LayoutTestResults
 from webkitpy.common.system.log_testing import LoggingTestCase
 from webkitpy.layout_tests.builder_list import BuilderList
@@ -18,9 +19,11 @@
 class WPTExpectationsUpdaterTest(LoggingTestCase):
 
     def mock_host(self):
-        super(WPTExpectationsUpdaterTest, self).setUp()
+        """Returns a mock host with fake values set up for testing."""
         host = MockHost()
         host.port_factory = MockPortFactory(host)
+
+        # Set up a fake list of try builders.
         host.builders = BuilderList({
             'MOCK Try Mac10.10': {
                 'port_name': 'test-mac-mac10.10',
@@ -54,6 +57,7 @@
             },
         })
 
+        # Write a dummy manifest file, describing what tests exist.
         host.filesystem.write_text_file(
             host.port_factory.get().layout_tests_dir() + '/external/wpt/MANIFEST.json',
             json.dumps({
@@ -75,11 +79,61 @@
 
         return host
 
+    def test_run_single_platform_failure(self):
+        """Tests the main run method in a case where one test fails on one platform."""
+        host = self.mock_host()
+
+        # Fill in an initial value for TestExpectations
+        expectations_path = host.port_factory.get().path_to_generic_test_expectations_file()
+        host.filesystem.write_text_file(expectations_path, MARKER_COMMENT + '\n')
+
+        # Set up fake try job results.
+        updater = WPTExpectationsUpdater(host)
+        updater.get_latest_try_jobs = lambda: {
+            Build('MOCK Try Mac10.10', 333): TryJobStatus('COMPLETED', 'FAILURE'),
+            Build('MOCK Try Mac10.11', 111): TryJobStatus('COMPLETED', 'SUCCESS'),
+            Build('MOCK Try Trusty', 222): TryJobStatus('COMPLETED', 'SUCCESS'),
+            Build('MOCK Try Precise', 333): TryJobStatus('COMPLETED', 'SUCCESS'),
+            Build('MOCK Try Win10', 444): TryJobStatus('COMPLETED', 'SUCCESS'),
+            Build('MOCK Try Win7', 555): TryJobStatus('COMPLETED', 'SUCCESS'),
+        }
+
+        # Set up failing results for one try bot. It shouldn't matter what
+        # results are for the other builders since we shouldn't need to even
+        # fetch results, since the try job status already tells us that all
+        # of the tests passed.
+        host.buildbot.set_results(
+            Build('MOCK Try Mac10.10', 333),
+            LayoutTestResults({
+                'tests': {
+                    'external': {
+                        'wpt': {
+                            'test': {
+                                'path.html': {
+                                    'expected': 'PASS',
+                                    'actual': 'TIMEOUT',
+                                    'is_unexpected': True,
+                                }
+                            }
+                        }
+                    }
+                }
+            }))
+        self.assertEqual(0, updater.run(args=[]))
+
+        # Results are only fetched for failing builds.
+        self.assertEqual(host.buildbot.fetched_builds, [Build('MOCK Try Mac10.10', 333)])
+
+        self.assertEqual(
+            host.filesystem.read_text_file(expectations_path),
+            '# ====== New tests from wpt-importer added here ======\n'
+            'crbug.com/626703 [ Mac10.10 ] external/wpt/test/path.html [ Timeout ]\n')
+
     def test_get_failing_results_dict_only_passing_results(self):
         host = self.mock_host()
         host.buildbot.set_results(Build('MOCK Try Mac10.10', 123), LayoutTestResults({
             'tests': {
-                'x': {
+                'test': {
                     'passing-test.html': {
                         'expected': 'PASS',
                         'actual': 'PASS',
@@ -335,7 +389,6 @@
 
     def test_write_to_test_expectations_with_marker_comment(self):
         host = self.mock_host()
-
         expectations_path = host.port_factory.get().path_to_generic_test_expectations_file()
         host.filesystem.write_text_file(
             expectations_path,
@@ -343,7 +396,7 @@
         updater = WPTExpectationsUpdater(host)
         line_list = ['crbug.com/123 [ Trusty ] fake/file/path.html [ Pass ]']
         updater.write_to_test_expectations(line_list)
-        value = updater.host.filesystem.read_text_file(expectations_path)
+        value = host.filesystem.read_text_file(expectations_path)
         self.assertMultiLineEqual(
             value,
             (MARKER_COMMENT + '\n'
@@ -392,7 +445,7 @@
             MARKER_COMMENT + '\n' + 'crbug.com/123 [ Trusty ] fake/file/path.html [ Pass ]\n')
         updater = WPTExpectationsUpdater(host)
         updater.write_to_test_expectations([])
-        value = updater.host.filesystem.read_text_file(expectations_path)
+        value = host.filesystem.read_text_file(expectations_path)
         self.assertMultiLineEqual(
             value,
             MARKER_COMMENT + '\n' + 'crbug.com/123 [ Trusty ] fake/file/path.html [ Pass ]\n')
diff --git a/third_party/WebKit/public/platform/WebMediaPlayer.h b/third_party/WebKit/public/platform/WebMediaPlayer.h
index 4920bad..7fe82d2 100644
--- a/third_party/WebKit/public/platform/WebMediaPlayer.h
+++ b/third_party/WebKit/public/platform/WebMediaPlayer.h
@@ -289,6 +289,16 @@
   // This method is not used to say express if the native controls are visible
   // but if the element is using them.
   virtual void OnHasNativeControlsChanged(bool) {}
+
+  enum class DisplayType {
+    kInline,
+    kFullscreen,
+    kPictureInPicture,
+  };
+
+  // Callback called whenever the media element display type changes. By
+  // default, the display type is `kInline`.
+  virtual void OnDisplayTypeChanged(DisplayType) {}
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebMediaPlayerClient.h b/third_party/WebKit/public/platform/WebMediaPlayerClient.h
index ac143a51..bacb135 100644
--- a/third_party/WebKit/public/platform/WebMediaPlayerClient.h
+++ b/third_party/WebKit/public/platform/WebMediaPlayerClient.h
@@ -121,8 +121,11 @@
   // that the controls are currently visible.
   virtual bool HasNativeControls() = 0;
 
+  // Returns the current display type of the media element.
+  virtual WebMediaPlayer::DisplayType DisplayType() const = 0;
+
  protected:
-  ~WebMediaPlayerClient() {}
+  ~WebMediaPlayerClient() = default;
 };
 
 }  // namespace blink
diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn
index 41d15e88..1b2342f 100644
--- a/third_party/libwebp/BUILD.gn
+++ b/third_party/libwebp/BUILD.gn
@@ -372,3 +372,146 @@
     deps += [ ":libwebp_dsp_neon" ]
   }
 }
+
+###############################################################################
+# Executables
+
+if (current_toolchain == host_toolchain) {
+  source_set("example_util") {
+    sources = [
+      "examples/example_util.c",
+      "examples/example_util.h",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+
+    deps = [
+      ":libwebp_webp",
+    ]
+    configs += [ ":libwebp_config" ]
+    visibility = [ ":*" ]
+  }
+
+  source_set("imageio_util") {
+    sources = [
+      "imageio/imageio_util.c",
+      "imageio/imageio_util.h",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+
+    deps = [
+      ":libwebp_webp",
+    ]
+    configs += [ ":libwebp_config" ]
+    visibility = [ ":*" ]
+  }
+
+  source_set("imagedec") {
+    sources = [
+      "imageio/image_dec.c",
+      "imageio/image_dec.h",
+      "imageio/jpegdec.c",
+      "imageio/jpegdec.h",
+      "imageio/metadata.c",
+      "imageio/metadata.h",
+      "imageio/pngdec.c",
+      "imageio/pngdec.h",
+      "imageio/tiffdec.c",
+      "imageio/tiffdec.h",
+      "imageio/webpdec.c",
+      "imageio/webpdec.h",
+      "imageio/wicdec.c",
+      "imageio/wicdec.h",
+    ]
+    defines = [ "WEBP_HAVE_PNG" ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+
+    deps = [
+      ":libwebp_webp",
+      "//third_party/libpng",
+      "//third_party/zlib",
+    ]
+    configs += [ ":libwebp_config" ]
+    visibility = [ ":*" ]
+  }
+
+  source_set("imageenc") {
+    sources = [
+      "imageio/image_enc.c",
+      "imageio/image_enc.h",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+
+    deps = [
+      ":libwebp_webp",
+    ]
+    configs += [ ":libwebp_config" ]
+    visibility = [ ":*" ]
+  }
+
+  executable("cwebp") {
+    sources = [
+      "examples/cwebp.c",
+      "examples/stopwatch.h",
+    ]
+
+    deps = [
+      ":example_util",
+      ":imagedec",
+      ":imageio_util",
+      ":libwebp",
+      "//base",
+      "//build/config:exe_and_shlib_deps",
+      "//build/win:default_exe_manifest",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+  }
+
+  executable("dwebp") {
+    sources = [
+      "examples/dwebp.c",
+      "examples/stopwatch.h",
+    ]
+
+    deps = [
+      ":example_util",
+      ":imagedec",
+      ":imageenc",
+      ":imageio_util",
+      ":libwebp",
+      "//base",
+      "//build/config:exe_and_shlib_deps",
+      "//build/win:default_exe_manifest",
+    ]
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+    if (set_opt_level) {
+      configs -= [ "//build/config/compiler:default_optimization" ]
+      configs += [ "//build/config/compiler:optimize_max" ]
+    }
+  }
+}
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 46bf07b7..23972014 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -1062,6 +1062,7 @@
     asan = 'is_asan=true' in vals['gn_args']
     msan = 'is_msan=true' in vals['gn_args']
     tsan = 'is_tsan=true' in vals['gn_args']
+    cfi_diag = 'use_cfi_diag=true' in vals['gn_args']
 
     test_type = isolate_map[target]['type']
 
@@ -1096,6 +1097,7 @@
         '--asan=%d' % asan,
         '--msan=%d' % msan,
         '--tsan=%d' % tsan,
+        '--cfi-diag=%d' % cfi_diag,
       ]
     elif test_type in ('windowed_test_launcher', 'console_test_launcher'):
       extra_files = [
@@ -1109,6 +1111,7 @@
           '--asan=%d' % asan,
           '--msan=%d' % msan,
           '--tsan=%d' % tsan,
+          '--cfi-diag=%d' % cfi_diag,
       ]
     elif test_type == 'script':
       extra_files = [
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index baa2d11..7b311cf 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -530,7 +530,7 @@
       'linux_chromium_archive_rel_ng': 'release_bot',
       'linux_chromium_asan_rel_ng': 'asan_lsan_release_trybot',
       'linux_chromium_browser_side_navigation_rel': 'release_trybot',
-      'linux_chromium_cfi_rel_ng': 'cfi_full_release_static_dcheck_always_on',
+      'linux_chromium_cfi_rel_ng': 'cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on',
       'linux_chromium_chromeos_asan_rel_ng': 'asan_lsan_chromeos_release_trybot',
       'linux_chromium_chromeos_compile_dbg_ng': 'chromeos_with_codecs_debug_trybot',
       'linux_chromium_chromeos_compile_rel_ng': 'chromeos_with_codecs_release_trybot',
@@ -992,8 +992,8 @@
       'cfi_full', 'clang_tot', 'release', 'static',
     ],
 
-    'cfi_full_release_static_dcheck_always_on': [
-      'cfi_full', 'release', 'static', 'dcheck_always_on',
+    'cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on': [
+      'cfi_full', 'cfi_diag', 'thin_lto', 'release', 'static', 'dcheck_always_on',
     ],
 
     'cfi_release_static': [
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 78a757d..c9896b2 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -46527,6 +46527,15 @@
   <summary>Result of servicing requests that may contain offline page.</summary>
 </histogram>
 
+<histogram name="OfflinePages.ArchiveManager.ArchiveDirsCreationResult"
+    enum="PlatformFileError">
+  <owner>romax@chromium.org</owner>
+  <summary>
+    This is recorded every time the archive directory is being created. It
+    doesn't include the case which the archive directory exists.
+  </summary>
+</histogram>
+
 <histogram name="OfflinePages.Background.BackgroundLoadingFailedCode"
     enum="NetErrorCodes">
   <owner>chili@chromium.org</owner>
@@ -75642,6 +75651,14 @@
   </summary>
 </histogram>
 
+<histogram name="Sync.ModelTypeMemoryKB" units="KB">
+  <owner>pavely@chromium.org</owner>
+  <summary>
+    Estimated memory usage by sync datatype in kilobytes. Recorded after sync
+    configuration.
+  </summary>
+</histogram>
+
 <histogram name="Sync.ModelTypeStoreInitResult"
     enum="SyncModelTypeStoreInitResult">
   <owner>pavely@chromium.org</owner>
@@ -90193,6 +90210,15 @@
   <suffix name="AudioVideo.Battery"
       label="Watch time for all media with both an audio and video track on
              battery power."/>
+  <suffix name="AudioVideo.DisplayFullscreen"
+      label="Watch time for all media with both an audio and video track
+             displayed in fullscreen."/>
+  <suffix name="AudioVideo.DisplayInline"
+      label="Watch time for all media with both an audio and video track
+             displayed inline."/>
+  <suffix name="AudioVideo.DisplayPictureInPicture"
+      label="Watch time for all media with both an audio and video track
+             displayed in picture-in-picture."/>
   <suffix name="AudioVideo.MSE"
       label="Watch time for MSE media with both an audio and video track."/>
   <suffix name="AudioVideo.NativeControlsOff"
@@ -95666,6 +95692,7 @@
   <suffix name="USER_EVENT" label="USER_EVENT"/>
   <suffix name="WIFI_CREDENTIAL" label="WIFI_CREDENTIAL"/>
   <affected-histogram name="Sync.ModelTypeCount"/>
+  <affected-histogram name="Sync.ModelTypeMemoryKB"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="SyzygyStartupTime" separator="_">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 662f9a8..fe71c7e7 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -341,6 +341,9 @@
   <metric name="AudioVideo.Background.MSE"/>
   <metric name="AudioVideo.Background.SRC"/>
   <metric name="AudioVideo.Battery"/>
+  <metric name="AudioVideo.DisplayFullscreen"/>
+  <metric name="AudioVideo.DisplayInline"/>
+  <metric name="AudioVideo.DisplayPictureInPicture"/>
   <metric name="AudioVideo.EME"/>
   <metric name="AudioVideo.MSE"/>
   <metric name="AudioVideo.NativeControlsOff"/>
diff --git a/tools/perf/contrib/blink_perf_cmdline/blink_perf_cmdline.py b/tools/perf/contrib/blink_perf_cmdline/blink_perf_cmdline.py
index d146e16..cac63522 100644
--- a/tools/perf/contrib/blink_perf_cmdline/blink_perf_cmdline.py
+++ b/tools/perf/contrib/blink_perf_cmdline/blink_perf_cmdline.py
@@ -4,7 +4,7 @@
 import os
 
 from benchmarks import blink_perf
-
+from telemetry import story
 
 # pylint: disable=protected-access
 class BlinkPerfAll(blink_perf._BlinkPerfBenchmark):
@@ -30,3 +30,9 @@
     print
     print 'Running all tests in %s' % path
     return blink_perf.CreateStorySetFromPath(path, blink_perf.SKIPPED_FILE)
+
+  def GetExpectations(self):
+    class StoryExpectations(story.expectations.StoryExpectations):
+      def SetExpectations(self):
+        pass # Nothing disabled.
+    return StoryExpectations()
diff --git a/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py b/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py
index 8e60e3a1..da191a93 100644
--- a/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py
+++ b/tools/perf/contrib/cros_benchmarks/page_cycler_v2.py
@@ -58,6 +58,8 @@
         cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.Typical25StoryExpectations()
 
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
 class PageCyclerV2IntlArFaHe(_PageCyclerV2):
@@ -75,6 +77,9 @@
     return page_sets.IntlArFaHePageSet(cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.IntlArFaHeStoryExpectations()
+
 
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
 class PageCyclerV2IntlEsFrPtBr(_PageCyclerV2):
@@ -92,6 +97,9 @@
     return page_sets.IntlEsFrPtBrPageSet(cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.IntlEsFrPtBrStoryExpectations()
+
 
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
 class PageCyclerV2IntlHiRu(_PageCyclerV2):
@@ -109,6 +117,9 @@
     return page_sets.IntlHiRuPageSet(cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.IntlHiRuStoryExpectations()
+
 
 @benchmark.Disabled('android')  # crbug.com/666898
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
@@ -126,6 +137,9 @@
     return page_sets.IntlJaZhPageSet(cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.IntlJaZhStoryExpectations()
+
 
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
 class PageCyclerV2IntlKoThVi(_PageCyclerV2):
@@ -143,6 +157,9 @@
     return page_sets.IntlKoThViPageSet(cache_temperatures=[
           cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
 
+  def GetExpectations(self):
+    return page_sets.IntlKoThViStoryExpectations()
+
 
 @benchmark.Enabled('android')
 @benchmark.Owner(emails=['kouhei@chromium.org', 'ksakamoto@chromium.org'])
@@ -159,3 +176,6 @@
   def CreateStorySet(self, options):
     return page_sets.Top10MobilePageSet(cache_temperatures=[
         cache_temperature.PCV1_COLD, cache_temperature.PCV1_WARM])
+
+  def GetExpectations(self):
+    return page_sets.Top10MobileStoryExpectations()
diff --git a/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py b/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
index b750c2e..e09eeeea 100644
--- a/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
+++ b/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
@@ -52,3 +52,9 @@
   @classmethod
   def Name(cls):
     return 'cros_tab_switching.typical_24'
+
+  def GetExpectations(self):
+    class StoryExpectations(story.expectations.StoryExpectations):
+      def SetExpectations(self):
+        pass # No tests disabled.
+    return StoryExpectations()
diff --git a/tools/perf/contrib/oilpan/oilpan_benchmarks.py b/tools/perf/contrib/oilpan/oilpan_benchmarks.py
index 5830ca0d..8bf9ae82 100644
--- a/tools/perf/contrib/oilpan/oilpan_benchmarks.py
+++ b/tools/perf/contrib/oilpan/oilpan_benchmarks.py
@@ -10,6 +10,7 @@
 from benchmarks import silk_flags
 
 from telemetry import benchmark
+from telemetry import story
 
 import page_sets
 
@@ -28,6 +29,12 @@
     path = os.path.join(blink_perf.BLINK_PERF_BASE_DIR, 'BlinkGC')
     return blink_perf.CreateStorySetFromPath(path, blink_perf.SKIPPED_FILE)
 
+  def GetExpectations(self):
+    class StoryExpectations(story.expectations.StoryExpectations):
+      def SetExpectations(self):
+        pass # No tests disabled.
+    return StoryExpectations()
+
 
 @benchmark.Owner(emails=['peria@chromium.org'])
 class OilpanGCTimesSmoothnessAnimation(perf_benchmark.PerfBenchmark):
@@ -38,6 +45,9 @@
   def Name(cls):
     return 'oilpan_gc_times.tough_animation_cases'
 
+  def GetExpectations(self):
+    return page_sets.ToughAnimationCasesStoryExpectations()
+
 
 @benchmark.Enabled('android')
 class OilpanGCTimesKeySilkCases(perf_benchmark.PerfBenchmark):
@@ -48,6 +58,8 @@
   def Name(cls):
     return 'oilpan_gc_times.key_silk_cases'
 
+  def GetExpectations(self):
+    return page_sets.KeySilkCasesStoryExpectations()
 
 @benchmark.Enabled('android')
 class OilpanGCTimesSyncScrollKeyMobileSites(perf_benchmark.PerfBenchmark):
@@ -61,3 +73,6 @@
   @classmethod
   def Name(cls):
     return 'oilpan_gc_times.sync_scroll.key_mobile_sites_smooth'
+
+  def GetExpectations(self):
+    return page_sets.KeyMobileSitesSmoothStoryExpectations()
diff --git a/tools/perf/page_sets/intl_ar_fa_he.py b/tools/perf/page_sets/intl_ar_fa_he.py
index 0f2f727..0444365 100644
--- a/tools/perf/page_sets/intl_ar_fa_he.py
+++ b/tools/perf/page_sets/intl_ar_fa_he.py
@@ -44,3 +44,8 @@
     for url in urls_list:
       for temp in cache_temperatures:
         self.AddStory(IntlArFaHePage(url, self, cache_temperature=temp))
+
+
+class IntlArFaHeStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/intl_es_fr_pt-BR.py b/tools/perf/page_sets/intl_es_fr_pt-BR.py
index 416108e..b8be098ae 100644
--- a/tools/perf/page_sets/intl_es_fr_pt-BR.py
+++ b/tools/perf/page_sets/intl_es_fr_pt-BR.py
@@ -52,3 +52,8 @@
     for url in urls_list:
       for temp in cache_temperatures:
         self.AddStory(IntlEsFrPtBrPage(url, self, cache_temperature=temp))
+
+
+class IntlEsFrPtBrStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/intl_hi_ru.py b/tools/perf/page_sets/intl_hi_ru.py
index 4bf42c09..efe66cb 100644
--- a/tools/perf/page_sets/intl_hi_ru.py
+++ b/tools/perf/page_sets/intl_hi_ru.py
@@ -53,3 +53,7 @@
     for url in urls_list:
       for temp in cache_temperatures:
         self.AddStory(IntlHiRuPage(url, self, cache_temperature=temp))
+
+class IntlHiRuStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/intl_ja_zh.py b/tools/perf/page_sets/intl_ja_zh.py
index b5439795..fb1fdaeb 100644
--- a/tools/perf/page_sets/intl_ja_zh.py
+++ b/tools/perf/page_sets/intl_ja_zh.py
@@ -63,3 +63,8 @@
     for url in urls_list:
       for temp in cache_temperatures:
         self.AddStory(IntlJaZhPage(url, self, cache_temperature=temp))
+
+
+class IntlJaZhStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/intl_ko_th_vi.py b/tools/perf/page_sets/intl_ko_th_vi.py
index 928b7245c..c5b33f65 100644
--- a/tools/perf/page_sets/intl_ko_th_vi.py
+++ b/tools/perf/page_sets/intl_ko_th_vi.py
@@ -57,3 +57,8 @@
     for url in urls_list:
       for temp in cache_temperatures:
         self.AddStory(IntlKoThViPage(url, self, cache_temperature=temp))
+
+
+class IntlKoThViStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/key_mobile_sites_smooth.py b/tools/perf/page_sets/key_mobile_sites_smooth.py
index fd2b15d..306cc48 100644
--- a/tools/perf/page_sets/key_mobile_sites_smooth.py
+++ b/tools/perf/page_sets/key_mobile_sites_smooth.py
@@ -282,3 +282,9 @@
 
     for url in urls_list:
       self.AddStory(KeyMobileSitesSmoothPage(url, self))
+
+
+class KeyMobileSitesSmoothStoryExpectations(
+    story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass # No tests disabled.
diff --git a/tools/perf/page_sets/system_health/expectations.py b/tools/perf/page_sets/system_health/expectations.py
index 247c2c7..d2b5f25 100644
--- a/tools/perf/page_sets/system_health/expectations.py
+++ b/tools/perf/page_sets/system_health/expectations.py
@@ -145,11 +145,36 @@
 # Should only include browse:*:* stories.
 class V8BrowsingDesktopExpecations(expectations.StoryExpectations):
   def SetExpectations(self):
-    self.DisableStory('browse:news:hackernews',
-                      [expectations.ALL_WIN, expectations.ALL_MAC],
-                      'crbug.com/676336')
-    self.DisableStory('browse:search:google', [expectations.ALL_WIN],
+    self.DisableStory('browse:media:imgur',
+                      [expectations.ALL_LINUX, expectations.ALL_WIN],
                       'crbug.com/673775')
+    self.DisableStory('browse:media:pinterest',
+                      [expectations.ALL_LINUX],
+                      'crbug.com/735173')
+    self.DisableStory('browse:media:youtube',
+                      [expectations.ALL_LINUX],
+                      'crbug.com/735173')
+    self.DisableStory('browse:news:cnn',
+                      [expectations.ALL_DESKTOP],
+                      'crbug.com/735173')
+    self.DisableStory('browse:news:flipboard',
+                      [expectations.ALL_DESKTOP],
+                      'crbug.com/735173')
+    self.DisableStory('browse:news:hackernews',
+                      [expectations.ALL_DESKTOP],
+                      'crbug.com/735173')
+    self.DisableStory('browse:news:nytimes',
+                      [expectations.ALL_LINUX, expectations.ALL_WIN],
+                      'crbug.com/735173')
+    self.DisableStory('browse:news:reddit',
+                      [expectations.ALL_LINUX, expectations.ALL_WIN],
+                      'crbug.com/735173')
+    self.DisableStory('browse:search:google',
+                      [expectations.ALL_LINUX, expectations.ALL_WIN],
+                      'crbug.com/735173')
+    self.DisableStory('browse:search:google_india',
+                      [expectations.ALL_LINUX],
+                      'crbug.com/735173')
     self.DisableStory('browse:tools:maps', [expectations.ALL],
                       'crbug.com/712694')
     self.DisableStory('browse:tools:earth', [expectations.ALL],
@@ -157,8 +182,12 @@
     self.DisableStory('browse:tech:discourse_infinite_scroll',
                       [expectations.ALL_WIN, expectations.ALL_LINUX],
                       'crbug.com/728152')
-    self.DisableStory('browse:news:cnn',
-                      [expectations.ALL_MAC], 'crbug.com/728576')
+    self.DisableStory('browse:social:facebook_infinite_scroll',
+                      [expectations.ALL_LINUX],
+                      'crbug.com/735173')
+    self.DisableStory('browse:social:twitter',
+                      [expectations.ALL_LINUX],
+                      'crbug.com/735173')
     self.DisableStory('browse:social:twitter_infinite_scroll',
                       [expectations.ALL], 'crbug.com/728464')
     self.DisableStory('browse:media:flickr_infinite_scroll',
diff --git a/tools/perf/page_sets/top_10_mobile.py b/tools/perf/page_sets/top_10_mobile.py
index 863973b..40b6a319a 100644
--- a/tools/perf/page_sets/top_10_mobile.py
+++ b/tools/perf/page_sets/top_10_mobile.py
@@ -65,3 +65,8 @@
     for url in URL_LIST:
       for temp in cache_temperatures:
         self.AddStory(Top10MobilePage(url, self, cache_temperature=temp))
+
+
+class Top10MobileStoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/tools/perf/page_sets/tough_animation_cases.py b/tools/perf/page_sets/tough_animation_cases.py
index da5cbf9..51e6516 100644
--- a/tools/perf/page_sets/tough_animation_cases.py
+++ b/tools/perf/page_sets/tough_animation_cases.py
@@ -273,3 +273,8 @@
     for url in urls_list_two:
       self.AddStory(ToughAnimationCasesPage(url, self,
                                            need_measurement_ready=False))
+
+class ToughAnimationCasesStoryExpectations(
+    story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass # No tests disabled.
diff --git a/tools/perf/page_sets/typical_25.py b/tools/perf/page_sets/typical_25.py
index fbee296..4822b31 100644
--- a/tools/perf/page_sets/typical_25.py
+++ b/tools/perf/page_sets/typical_25.py
@@ -83,3 +83,8 @@
       for temp in cache_temperatures:
         self.AddStory(page_class(
           url, self, run_no_page_interactions, cache_temperature=temp))
+
+
+class Typical25StoryExpectations(story.expectations.StoryExpectations):
+  def SetExpectations(self):
+    pass
diff --git a/ui/display/manager/chromeos/display_change_observer.cc b/ui/display/manager/chromeos/display_change_observer.cc
index 8934783..3925980 100644
--- a/ui/display/manager/chromeos/display_change_observer.cc
+++ b/ui/display/manager/chromeos/display_change_observer.cc
@@ -37,9 +37,9 @@
   float device_scale_factor;
 };
 
-const DeviceScaleFactorDPIThreshold kThresholdTable[] = {
+const DeviceScaleFactorDPIThreshold kThresholdTableForInternal[] = {
     {220.0f, 2.0f},
-    {180.0f, 1.5f},
+    {200.0f, 1.6f},
     {150.0f, 1.25f},
     {0.0f, 1.0f},
 };
@@ -290,9 +290,9 @@
 
 // static
 float DisplayChangeObserver::FindDeviceScaleFactor(float dpi) {
-  for (size_t i = 0; i < arraysize(kThresholdTable); ++i) {
-    if (dpi > kThresholdTable[i].dpi)
-      return kThresholdTable[i].device_scale_factor;
+  for (size_t i = 0; i < arraysize(kThresholdTableForInternal); ++i) {
+    if (dpi > kThresholdTableForInternal[i].dpi)
+      return kThresholdTableForInternal[i].device_scale_factor;
   }
   return 1.0f;
 }
diff --git a/ui/display/manager/chromeos/display_change_observer_unittest.cc b/ui/display/manager/chromeos/display_change_observer_unittest.cc
index 754d9c8..cf74f78 100644
--- a/ui/display/manager/chromeos/display_change_observer_unittest.cc
+++ b/ui/display/manager/chromeos/display_change_observer_unittest.cc
@@ -337,7 +337,10 @@
   EXPECT_EQ(1.25f, ComputeDeviceScaleFactor(14.0f, gfx::Rect(1920, 1080)));
 
   // 11.6" 1920x1080
-  EXPECT_EQ(1.5f, ComputeDeviceScaleFactor(11.6f, gfx::Rect(1920, 1080)));
+  EXPECT_EQ(1.25f, ComputeDeviceScaleFactor(11.6f, gfx::Rect(1920, 1080)));
+
+  // 12.02" 2160x1440
+  EXPECT_EQ(1.6f, ComputeDeviceScaleFactor(12.02f, gfx::Rect(2160, 1440)));
 
   // 12.85" 2560x1700
   EXPECT_EQ(2.0f, ComputeDeviceScaleFactor(12.85f, gfx::Rect(2560, 1700)));
diff --git a/ui/display/manager/display_manager_utilities.cc b/ui/display/manager/display_manager_utilities.cc
index c84c106..7f5737c 100644
--- a/ui/display/manager/display_manager_utilities.cc
+++ b/ui/display/manager/display_manager_utilities.cc
@@ -23,14 +23,19 @@
 constexpr float kUIScalesFor2x[] = {0.5f,   0.625f, 0.8f, 1.0f,
                                     1.125f, 1.25f,  1.5f, 2.0f};
 constexpr float kUIScalesFor1_25x[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f};
+constexpr float kUIScalesFor1_6x[] = {0.5f, 0.8f, 1.0f, 1.2f, 1.6f};
+
 constexpr float kUIScalesFor1280[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.125f};
 constexpr float kUIScalesFor1366[] = {0.5f, 0.6f, 0.75f, 1.0f, 1.125f};
+constexpr float kUIScalesForFHD[] = {0.5f, 0.625f, 0.8f, 1.0f, 1.25f};
 
 // The default UI scales for the above display densities.
 constexpr float kDefaultUIScaleFor2x = 1.0f;
 constexpr float kDefaultUIScaleFor1_25x = 0.8f;
+constexpr float kDefaultUIScaleFor1_6x = 1.0f;
 constexpr float kDefaultUIScaleFor1280 = 1.0f;
 constexpr float kDefaultUIScaleFor1366 = 1.0f;
+constexpr float kDefaultUIScaleForFHD = 1.0f;
 
 // Encapsulates the list of UI scales and the default one.
 struct DisplayUIScales {
@@ -51,6 +56,10 @@
     ASSIGN_ARRAY(ret.scales, kUIScalesFor1_25x);
     ret.default_scale = kDefaultUIScaleFor1_25x;
     return ret;
+  } else if (native_mode->device_scale_factor() == 1.6f) {
+    ASSIGN_ARRAY(ret.scales, kUIScalesFor1_6x);
+    ret.default_scale = kDefaultUIScaleFor1_6x;
+    return ret;
   }
   switch (native_mode->size().width()) {
     case 1280:
@@ -61,6 +70,10 @@
       ASSIGN_ARRAY(ret.scales, kUIScalesFor1366);
       ret.default_scale = kDefaultUIScaleFor1366;
       break;
+    case 1980:
+      ASSIGN_ARRAY(ret.scales, kUIScalesForFHD);
+      ret.default_scale = kDefaultUIScaleForFHD;
+      break;
     default:
       ASSIGN_ARRAY(ret.scales, kUIScalesFor1280);
       ret.default_scale = kDefaultUIScaleFor1280;
diff --git a/ui/display/manager/managed_display_info.cc b/ui/display/manager/managed_display_info.cc
index 4ed44db6..c1fc554 100644
--- a/ui/display/manager/managed_display_info.cc
+++ b/ui/display/manager/managed_display_info.cc
@@ -33,7 +33,6 @@
 int64_t synthesized_display_id = kSynthesizedDisplayIdStart;
 
 const float kDpi96 = 96.0;
-bool use_125_dsf_for_ui_scaling = true;
 
 // Check the content of |spec| and fill |bounds| and |device_scale_factor|.
 // Returns true when |bounds| is found.
@@ -146,8 +145,7 @@
   size_dip.Scale(ui_scale_);
   // DSF=1.25 is special on internal display. The screen is drawn with DSF=1.25
   // but it doesn't affect the screen size computation.
-  if (use_125_dsf_for_ui_scaling && is_internal &&
-      device_scale_factor_ == 1.25f)
+  if (is_internal && device_scale_factor_ == 1.25f)
     return gfx::ToFlooredSize(size_dip);
   size_dip.Scale(1.0f / device_scale_factor_);
   return gfx::ToFlooredSize(size_dip);
@@ -294,11 +292,6 @@
   return display_info;
 }
 
-// static
-void ManagedDisplayInfo::SetUse125DSFForUIScalingForTest(bool enable) {
-  use_125_dsf_for_ui_scaling = enable;
-}
-
 ManagedDisplayInfo::ManagedDisplayInfo()
     : id_(kInvalidDisplayId),
       has_overscan_(false),
@@ -511,7 +504,7 @@
 }
 
 bool ManagedDisplayInfo::Use125DSFForUIScaling() const {
-  return use_125_dsf_for_ui_scaling && Display::IsInternalDisplayId(id_);
+  return Display::IsInternalDisplayId(id_);
 }
 
 void ManagedDisplayInfo::AddInputDevice(int id) {
diff --git a/ui/display/manager/managed_display_info.h b/ui/display/manager/managed_display_info.h
index c40b3c8..0a2863a 100644
--- a/ui/display/manager/managed_display_info.h
+++ b/ui/display/manager/managed_display_info.h
@@ -153,11 +153,6 @@
   static ManagedDisplayInfo CreateFromSpecWithID(const std::string& spec,
                                                  int64_t id);
 
-  // When this is set to true on the device whose internal display has
-  // 1.25 dsf, Chrome uses 1.0f as a default scale factor, and uses
-  // dsf 1.25 when UI scaling is set to 0.8f.
-  static void SetUse125DSFForUIScalingForTest(bool enable);
-
   ManagedDisplayInfo();
   ManagedDisplayInfo(int64_t id, const std::string& name, bool has_overscan);
   ManagedDisplayInfo(const ManagedDisplayInfo& other);
diff --git a/ui/display/test/display_manager_test_api.cc b/ui/display/test/display_manager_test_api.cc
index 0a8078b4e..e57b142 100644
--- a/ui/display/test/display_manager_test_api.cc
+++ b/ui/display/test/display_manager_test_api.cc
@@ -147,14 +147,6 @@
       ->set_touch_support(touch_support);
 }
 
-ScopedDisable125DSFForUIScaling::ScopedDisable125DSFForUIScaling() {
-  ManagedDisplayInfo::SetUse125DSFForUIScalingForTest(false);
-}
-
-ScopedDisable125DSFForUIScaling::~ScopedDisable125DSFForUIScaling() {
-  ManagedDisplayInfo::SetUse125DSFForUIScalingForTest(true);
-}
-
 ScopedSetInternalDisplayId::ScopedSetInternalDisplayId(
     DisplayManager* display_manager,
     int64_t id) {
diff --git a/ui/display/test/display_manager_test_api.h b/ui/display/test/display_manager_test_api.h
index 429a2b2..89bcb5b 100644
--- a/ui/display/test/display_manager_test_api.h
+++ b/ui/display/test/display_manager_test_api.h
@@ -71,15 +71,6 @@
   DISALLOW_COPY_AND_ASSIGN(DisplayManagerTestApi);
 };
 
-class DISPLAY_EXPORT ScopedDisable125DSFForUIScaling {
- public:
-  ScopedDisable125DSFForUIScaling();
-  ~ScopedDisable125DSFForUIScaling();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedDisable125DSFForUIScaling);
-};
-
 class DISPLAY_EXPORT ScopedSetInternalDisplayId {
  public:
   ScopedSetInternalDisplayId(DisplayManager* test_api, int64_t id);
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc
index 06263a1..ca5b04b6 100644
--- a/ui/gl/init/gl_factory_win.cc
+++ b/ui/gl/init/gl_factory_win.cc
@@ -117,8 +117,13 @@
           new GLSurfaceOSMesa(format, size), format);
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-      return InitializeGLSurfaceWithFormat(
-          new PbufferGLSurfaceEGL(size), format);
+      if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
+          size.width() == 0 && size.height() == 0) {
+        return InitializeGLSurfaceWithFormat(new SurfacelessEGL(size), format);
+      } else {
+        return InitializeGLSurfaceWithFormat(new PbufferGLSurfaceEGL(size),
+                                             format);
+      }
     case kGLImplementationDesktopGL:
       return InitializeGLSurfaceWithFormat(
           new PbufferGLSurfaceWGL(size), format);
diff --git a/ui/gl/init/gl_factory_x11.cc b/ui/gl/init/gl_factory_x11.cc
index 38a4d221..9b0f481 100644
--- a/ui/gl/init/gl_factory_x11.cc
+++ b/ui/gl/init/gl_factory_x11.cc
@@ -108,8 +108,13 @@
           new UnmappedNativeViewGLSurfaceGLX(size), format);
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-      return InitializeGLSurfaceWithFormat(
-          new PbufferGLSurfaceEGL(size), format);
+      if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
+          size.width() == 0 && size.height() == 0) {
+        return InitializeGLSurfaceWithFormat(new SurfacelessEGL(size), format);
+      } else {
+        return InitializeGLSurfaceWithFormat(new PbufferGLSurfaceEGL(size),
+                                             format);
+      }
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
       return new GLSurfaceStub;
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index 069ee13c..4dbe12a0 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -348,13 +348,9 @@
         code,
         dom_code,
         modifiers);
-    if (input_method) {
-      input_method->DispatchKeyEvent(&event);
-    } else {
-      ui::EventDispatchDetails details =
-          host->event_sink()->OnEventFromSource(&event);
-      CHECK(!details.dispatcher_destroyed);
-    }
+    ui::EventDispatchDetails details =
+        host->event_sink()->OnEventFromSource(&event);
+    CHECK(!details.dispatcher_destroyed);
   }
   return true;
 }
diff --git a/ui/login/account_picker/md_screen_account_picker.js b/ui/login/account_picker/md_screen_account_picker.js
index 56420401..32ea93ca8 100644
--- a/ui/login/account_picker/md_screen_account_picker.js
+++ b/ui/login/account_picker/md_screen_account_picker.js
@@ -128,6 +128,10 @@
      */
     onBeforeShow: function(data) {
       this.showing_ = true;
+
+      this.ownerDocument.addEventListener('click',
+          this.handleOwnerDocClick_.bind(this));
+
       chrome.send('loginUIStateChanged', ['account-picker', true]);
       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.ACCOUNT_PICKER;
       // Header bar should be always visible on Account Picker screen.
@@ -492,11 +496,6 @@
 
       this.lockScreenAppsState_ = state;
       $('login-header-bar').lockScreenAppsState = state;
-      // When an lock screen app window is in background - i.e. visible behind
-      // the lock screen UI - dim the lock screen background, so it's more
-      // noticeable that the app widow in background is not actionable.
-      $('background').classList.toggle(
-          'dimmed-background', state == LOCK_SCREEN_APPS_STATE.BACKGROUND);
     },
 
     /**
@@ -507,8 +506,9 @@
      * @param {Event} event The click event.
      */
     handleOwnerDocClick_: function(event) {
-      if (this.lockScreenAppsState_  != LOCK_SCREEN_APPS_STATE.BACKGROUND ||
-          event.target != $('outer-container')) {
+      if (this.lockScreenAppsState_ != LOCK_SCREEN_APPS_STATE.BACKGROUND ||
+          (event.target != $('account-picker') &&
+           event.target != $('version'))) {
         return;
       }
       chrome.send('setLockScreenAppsState',
diff --git a/ui/login/account_picker/md_user_pod_row.css b/ui/login/account_picker/md_user_pod_row.css
index 869f6f7d..2f6bd48 100644
--- a/ui/login/account_picker/md_user_pod_row.css
+++ b/ui/login/account_picker/md_user_pod_row.css
@@ -213,6 +213,7 @@
 
 .input-line {
   display: none;
+  height: 1px;
   opacity: 0.34;
   position: absolute;
   stroke: #FFFFFF;