diff --git a/BUILD.gn b/BUILD.gn
index 1b299db..529d1fdb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -401,7 +401,6 @@
       "//base:base_junit_tests",
       "//base/android/linker:chromium_android_linker",
       "//build/android/gyp/test:hello_world",
-      "//build/android/rezip",
       "//chrome/android/webapk/shell_apk:webapk",
       "//components/invalidation/impl:components_invalidation_impl_junit_tests",
       "//components/policy/android:components_policy_junit_tests",
diff --git a/DEPS b/DEPS
index c2f85f8..d4a0285 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'db52cf3b040d0360a70432d11d404712f0733c28',
+  'skia_revision': 'a5494f117086d712855e4b6289c58c92d1549bcf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '8ba45f77c14f019f1d61565371a89e635db15151',
+  'v8_revision': 'd1d93c3a0e8f6eb84756b5ad56b33e300e327bdc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '44bc1f818dd791c2a5a81103be3853093fd934b3',
+  'pdfium_revision': '8fa82794ffc2763e9fa1fc9d401c8e9a14d7c67f',
   # 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': '8b10e7828ad23b4aed04259a870ab11d2f323a23',
+  'catapult_revision': '7863f77ca84edad4dc03fcb17c790e3c549c9f8e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -192,13 +192,13 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '046d1f6892ba08de4b9f58d59a50794034f286e7',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '06ad9fd073271d958ae63fbc9ef924e5f824589f',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'f27276f44fa3a66c07a2a92a381f31aaf8371add',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '5b1a8ca5e846f838062becaec9ed6b5ecef306e5',
 
   'src/third_party/ffmpeg':
     Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'f309edd7828e3ea500c2891187d15926690ddd27',
diff --git a/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java b/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java
deleted file mode 100644
index 6e360e29..0000000
--- a/android_webview/java/generated_src/org/chromium/base/library_loader/NativeLibraries.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.base.library_loader;
-
-/**
- * This class defines the native libraries and loader options required by webview
- */
-public class NativeLibraries {
-    // Set to true to use the chromium linker. Only useful to save memory
-    // on multi-process content-based projects. Always disabled for the Android Webview.
-    public static boolean sUseLinker = false;
-
-    // Set to true to directly load the library from the zip file using the
-    // chromium linker. Always disabled for Android Webview.
-    public static boolean sUseLibraryInZipFile = false;
-
-    // Set to true to enable chromium linker test support. NEVER enable this for the
-    // Android webview.
-    public static boolean sEnableLinkerTests = false;
-
-    // This is the list of native libraries to load. In the normal chromium build, this would be
-    // automatically generated.
-    // TODO(torne, cjhopman): Use a generated file for this.
-    static final String[] LIBRARIES = { "webviewchromium" };
-    // This should match the version name string returned by the native library.
-    // TODO(aberent) The Webview native library currently returns an empty string; change this
-    // to a string generated at compile time, and incorporate that string in a generated
-    // replacement for this file.
-    static String sVersionNumber = "";
-}
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni
index 8b37716..90bdc7f5 100644
--- a/android_webview/system_webview_apk_tmpl.gni
+++ b/android_webview/system_webview_apk_tmpl.gni
@@ -4,6 +4,7 @@
 
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
+import("//build/config/locales.gni")
 
 template("system_webview_apk_tmpl") {
   android_apk(target_name) {
@@ -27,6 +28,7 @@
     if (build_apk_secondary_abi && android_64bit_target_cpu) {
       secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
     }
+    aapt_locale_whitelist = locales
 
     if (!is_java_debug) {
       proguard_enabled = true
diff --git a/android_webview/tools/apk_merger.py b/android_webview/tools/apk_merger.py
index 74eac37..713a58d 100755
--- a/android_webview/tools/apk_merger.py
+++ b/android_webview/tools/apk_merger.py
@@ -135,8 +135,7 @@
 
 
 def SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, zipalign_path,
-                    keystore_path, key_name, key_password,
-                    page_align_shared_libraries):
+                    keystore_path, key_name, key_password):
   try:
     finalize_apk.JarSigner(
         keystore_path,
@@ -149,7 +148,6 @@
 
   try:
     finalize_apk.AlignApk(zipalign_path,
-                          page_align_shared_libraries,
                           signed_tmp_apk,
                           new_apk)
   except build_utils.CalledProcessError as e:
@@ -224,7 +222,8 @@
   parser.add_argument('--key_name', required=True)
   parser.add_argument('--key_password', required=True)
   parser.add_argument('--shared_library')
-  parser.add_argument('--page-align-shared-libraries', action='store_true')
+  parser.add_argument('--page-align-shared-libraries', action='store_true',
+                      help='Obsolete, but remains for backwards compatibility')
   parser.add_argument('--uncompress-shared-libraries', action='store_true')
   parser.add_argument('--debug', action='store_true')
   # This option shall only used in debug build, see http://crbug.com/631494.
@@ -250,8 +249,7 @@
     MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64)
 
     SignAndAlignApk(tmp_apk, signed_tmp_apk, new_apk, args.zipalign_path,
-                    args.keystore_path, args.key_name, args.key_password,
-                    args.page_align_shared_libraries)
+                    args.keystore_path, args.key_name, args.key_password)
 
   except ApkMergeFailure as e:
     print e
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index e09087a..db31ff65 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1342,6 +1342,7 @@
     "//ash/public/cpp",
     "//ash/public/interfaces",
     "//ash/resources",
+    "//ash/resources/vector_icons",
     "//ash/test:ash_with_aura_test_support",
     "//ash/test:test_support_without_content",
     "//ash/touch_hud",
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.cc b/ash/common/frame/caption_buttons/frame_caption_button.cc
index d496f1b..74f1ef9 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button.cc
@@ -56,9 +56,10 @@
 
 void FrameCaptionButton::SetImage(CaptionButtonIcon icon,
                                   Animate animate,
-                                  gfx::VectorIconId icon_image_id) {
+                                  const gfx::VectorIcon& icon_definition) {
   gfx::ImageSkia new_icon_image = gfx::CreateVectorIcon(
-      icon_image_id, use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey);
+      icon_definition,
+      use_light_images_ ? SK_ColorWHITE : gfx::kChromeIconGrey);
 
   // The early return is dependent on |animate| because callers use SetImage()
   // with ANIMATE_NO to progress the crossfade animation to the end.
@@ -72,7 +73,7 @@
     crossfade_icon_image_ = icon_image_;
 
   icon_ = icon;
-  icon_image_id_ = icon_image_id;
+  icon_definition_ = &icon_definition;
   icon_image_ = new_icon_image;
 
   if (animate == ANIMATE_YES) {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button.h b/ash/common/frame/caption_buttons/frame_caption_button.h
index 3f80862..8b6df285 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button.h
+++ b/ash/common/frame/caption_buttons/frame_caption_button.h
@@ -15,7 +15,7 @@
 
 namespace gfx {
 class SlideAnimation;
-enum class VectorIconId;
+struct VectorIcon;
 }
 
 namespace ash {
@@ -32,12 +32,12 @@
   ~FrameCaptionButton() override;
 
   // Sets the image to use to paint the button. If |animate| is ANIMATE_YES,
-  // the button crossfades to the new visuals. If the image id matches the one
+  // the button crossfades to the new visuals. If the image matches the one
   // currently used by the button and |animate| is ANIMATE_NO, the crossfade
   // animation is progressed to the end.
   void SetImage(CaptionButtonIcon icon,
                 Animate animate,
-                gfx::VectorIconId icon_image_id);
+                const gfx::VectorIcon& icon_image);
 
   // Returns true if the button is crossfading to new visuals set in
   // SetImage().
@@ -59,8 +59,6 @@
 
   CaptionButtonIcon icon() const { return icon_; }
 
-  gfx::VectorIconId icon_image_id() const { return icon_image_id_; }
-
   void set_size(const gfx::Size& size) { size_ = size; }
 
  protected:
@@ -90,7 +88,7 @@
 
   // The image id (kept for the purposes of testing) and image used to paint the
   // button's icon.
-  gfx::VectorIconId icon_image_id_;
+  const gfx::VectorIcon* icon_definition_ = nullptr;
   gfx::ImageSkia icon_image_;
 
   // The icon image to crossfade from.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
index 77f8006..3539a04 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -19,7 +19,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/gfx/vector_icons_public.h"
+#include "ui/gfx/vector_icon_types.h"
 #include "ui/strings/grit/ui_strings.h"  // Accessibility names
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -148,14 +148,15 @@
 
 void FrameCaptionButtonContainerView::SetButtonImage(
     CaptionButtonIcon icon,
-    gfx::VectorIconId icon_image_id) {
-  button_icon_id_map_[icon] = icon_image_id;
+    const gfx::VectorIcon& icon_definition) {
+  button_icon_map_[icon] = &icon_definition;
 
   FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
                                    close_button_};
   for (size_t i = 0; i < arraysize(buttons); ++i) {
     if (buttons[i]->icon() == icon)
-      buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO, icon_image_id);
+      buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO,
+                           icon_definition);
   }
 }
 
@@ -299,9 +300,9 @@
   FrameCaptionButton::Animate fcb_animate =
       (animate == ANIMATE_YES) ? FrameCaptionButton::ANIMATE_YES
                                : FrameCaptionButton::ANIMATE_NO;
-  auto it = button_icon_id_map_.find(icon);
-  if (it != button_icon_id_map_.end())
-    button->SetImage(icon, fcb_animate, it->second);
+  auto it = button_icon_map_.find(icon);
+  if (it != button_icon_map_.end())
+    button->SetImage(icon, fcb_animate, *it->second);
 }
 
 bool FrameCaptionButtonContainerView::ShouldSizeButtonBeVisible() const {
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
index 55fd39c..014071a 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view.h
@@ -16,7 +16,7 @@
 
 namespace gfx {
 class SlideAnimation;
-enum class VectorIconId;
+struct VectorIcon;
 }
 
 namespace views {
@@ -68,7 +68,8 @@
   // Sets the id of the vector image to paint the button for |icon|. The
   // FrameCaptionButtonContainerView will keep track of the image to use for
   // |icon| even if none of the buttons currently use |icon|.
-  void SetButtonImage(CaptionButtonIcon icon, gfx::VectorIconId icon_image_id);
+  void SetButtonImage(CaptionButtonIcon icon,
+                      const gfx::VectorIcon& icon_definition);
 
   // Sets whether the buttons should be painted as active. Does not schedule
   // a repaint.
@@ -141,9 +142,9 @@
   FrameCaptionButton* size_button_;
   FrameCaptionButton* close_button_;
 
-  // Mapping of the image ID needed to paint a button for each of the values of
+  // Mapping of the image needed to paint a button for each of the values of
   // CaptionButtonIcon.
-  std::map<CaptionButtonIcon, gfx::VectorIconId> button_icon_id_map_;
+  std::map<CaptionButtonIcon, const gfx::VectorIcon*> button_icon_map_;
 
   // Animation that affects the position of |minimize_button_| and the
   // visibility of |size_button_|.
diff --git a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 067e868..21fce7ca 100644
--- a/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/common/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -8,10 +8,10 @@
 #include "ash/common/frame/caption_buttons/frame_caption_button.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm_shell.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/test/ash_test_base.h"
 #include "grit/ash_resources.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -71,7 +71,7 @@
         GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
     for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
       container->SetButtonImage(static_cast<CaptionButtonIcon>(icon),
-                                gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+                                ash::kWindowControlCloseIcon);
     }
   }
 
diff --git a/ash/common/frame/default_header_painter.cc b/ash/common/frame/default_header_painter.cc
index f333bf1..4856f7e9 100644
--- a/ash/common/frame/default_header_painter.cc
+++ b/ash/common/frame/default_header_painter.cc
@@ -7,6 +7,7 @@
 #include "ash/common/ash_layout_constants.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/frame/header_painter_util.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"  // DCHECK
 #include "grit/ash_resources.h"
@@ -21,7 +22,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/native_widget_aura.h"
 #include "ui/views/widget/widget.h"
@@ -283,29 +283,27 @@
 
 void DefaultHeaderPainter::UpdateAllButtonImages() {
   caption_button_container_->SetUseLightImages(ShouldUseLightImages());
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_MINIMIZE, gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_MINIMIZE,
+                                            kWindowControlMinimizeIcon);
 
   UpdateSizeButtonImages();
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_CLOSE,
+                                            kWindowControlCloseIcon);
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_LEFT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_LEFT_SNAPPED,
+                                            kWindowControlLeftSnappedIcon);
 
-  caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED);
+  caption_button_container_->SetButtonImage(CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
+                                            kWindowControlRightSnappedIcon);
 }
 
 void DefaultHeaderPainter::UpdateSizeButtonImages() {
-  gfx::VectorIconId icon_id = frame_->IsMaximized() || frame_->IsFullscreen()
-                                  ? gfx::VectorIconId::WINDOW_CONTROL_RESTORE
-                                  : gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE;
+  const gfx::VectorIcon& icon = frame_->IsMaximized() || frame_->IsFullscreen()
+                                    ? kWindowControlRestoreIcon
+                                    : kWindowControlMaximizeIcon;
   caption_button_container_->SetButtonImage(
-      CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon_id);
+      CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, icon);
 }
 
 gfx::Rect DefaultHeaderPainter::GetLocalBounds() const {
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.cc b/ash/common/shelf/app_list_shelf_item_delegate.cc
index 53143be..af2dbb3 100644
--- a/ash/common/shelf/app_list_shelf_item_delegate.cc
+++ b/ash/common/shelf/app_list_shelf_item_delegate.cc
@@ -14,19 +14,18 @@
 namespace ash {
 
 // static
-void AppListShelfItemDelegate::CreateAppListItemAndDelegate(
-    ShelfModel* shelf_model) {
+void AppListShelfItemDelegate::CreateAppListItemAndDelegate(ShelfModel* model) {
   // Add the app list item to the shelf model.
-  ShelfItem app_list;
-  app_list.type = TYPE_APP_LIST;
-  int app_list_index = shelf_model->Add(app_list);
-  DCHECK_GE(app_list_index, 0);
+  ShelfItem item;
+  item.type = TYPE_APP_LIST;
+  item.title = l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE);
+  int index = model->Add(item);
+  DCHECK_GE(index, 0);
 
   // Create an AppListShelfItemDelegate for that item.
-  ShelfID app_list_id = shelf_model->items()[app_list_index].id;
-  DCHECK_GE(app_list_id, 0);
-  shelf_model->SetShelfItemDelegate(
-      app_list_id, base::MakeUnique<AppListShelfItemDelegate>());
+  ShelfID id = model->items()[index].id;
+  DCHECK_GE(id, 0);
+  model->SetShelfItemDelegate(id, base::MakeUnique<AppListShelfItemDelegate>());
 }
 
 AppListShelfItemDelegate::AppListShelfItemDelegate() {}
@@ -39,16 +38,6 @@
   return ShelfItemDelegate::kAppListMenuShown;
 }
 
-base::string16 AppListShelfItemDelegate::GetTitle() {
-  ShelfModel* model = WmShell::Get()->shelf_model();
-  DCHECK(model);
-  int title_id;
-  title_id = model->status() == ShelfModel::STATUS_LOADING
-                 ? IDS_ASH_SHELF_APP_LIST_LAUNCHER_SYNCING_TITLE
-                 : IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE;
-  return l10n_util::GetStringUTF16(title_id);
-}
-
 ShelfMenuModel* AppListShelfItemDelegate::CreateApplicationMenu(
     int event_flags) {
   // AppList does not show an application menu.
diff --git a/ash/common/shelf/app_list_shelf_item_delegate.h b/ash/common/shelf/app_list_shelf_item_delegate.h
index 3884052..82a122d 100644
--- a/ash/common/shelf/app_list_shelf_item_delegate.h
+++ b/ash/common/shelf/app_list_shelf_item_delegate.h
@@ -15,8 +15,8 @@
 class AppListShelfItemDelegate : public ShelfItemDelegate {
  public:
   // Initializes the app list item in the shelf data model and creates an
-  // AppListShelfItemDelegate which will be owned by |shelf_model|.
-  static void CreateAppListItemAndDelegate(ShelfModel* shelf_model);
+  // AppListShelfItemDelegate which will be owned by |model|.
+  static void CreateAppListItemAndDelegate(ShelfModel* model);
 
   AppListShelfItemDelegate();
   ~AppListShelfItemDelegate() override;
@@ -24,7 +24,6 @@
   // ShelfItemDelegate:
   ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/ash/common/shelf/shelf_controller.cc b/ash/common/shelf/shelf_controller.cc
index 78b0874..2cea707e4 100644
--- a/ash/common/shelf/shelf_controller.cc
+++ b/ash/common/shelf/shelf_controller.cc
@@ -60,7 +60,7 @@
     explicit ShelfMenuModelMus(ShelfItemDelegateMus* item_delegate)
         : ShelfMenuModel(this), item_delegate_(item_delegate) {
       AddSeparator(ui::SPACING_SEPARATOR);
-      AddItem(0, item_delegate_->GetTitle());
+      AddItem(0, item_delegate_->title());
       AddSeparator(ui::SPACING_SEPARATOR);
       for (const auto& window : item_delegate_->window_id_to_title())
         AddItem(window.first, window.second);
@@ -100,11 +100,6 @@
     return kNoAction;
   }
 
-  base::string16 GetTitle() override {
-    return window_id_to_title_.empty() ? title_
-                                       : window_id_to_title_.begin()->second;
-  }
-
   ShelfMenuModel* CreateApplicationMenu(int event_flags) override {
     return new ShelfMenuModelMus(this);
   }
@@ -232,13 +227,14 @@
   shelf_item.type = TYPE_APP_SHORTCUT;
   shelf_item.status = STATUS_CLOSED;
   shelf_item.image = GetShelfIconFromBitmap(item->image);
+  shelf_item.title = base::UTF8ToUTF16(item->app_title);
   model_.Add(shelf_item);
 
-  std::unique_ptr<ShelfItemDelegateMus> item_delegate(
-      new ShelfItemDelegateMus());
+  std::unique_ptr<ShelfItemDelegateMus> item_delegate =
+      base::MakeUnique<ShelfItemDelegateMus>();
   item_delegate->SetDelegate(std::move(delegate));
   item_delegate->set_pinned(true);
-  item_delegate->set_title(base::UTF8ToUTF16(item->app_title));
+  item_delegate->set_title(shelf_item.title);
   model_.SetShelfItemDelegate(shelf_id, std::move(item_delegate));
 }
 
diff --git a/ash/common/shelf/shelf_item_delegate.h b/ash/common/shelf/shelf_item_delegate.h
index 868e856..fbf76ef 100644
--- a/ash/common/shelf/shelf_item_delegate.h
+++ b/ash/common/shelf/shelf_item_delegate.h
@@ -44,9 +44,6 @@
   // Returns the action performed by selecting the item.
   virtual PerformedAction ItemSelected(const ui::Event& event) = 0;
 
-  // Returns the title to display.
-  virtual base::string16 GetTitle() = 0;
-
   // Returns the application menu model for the specified item. There are three
   // possible return values:
   //  - A return of NULL indicates that no menu is wanted for this item.
diff --git a/ash/common/shelf/shelf_item_types.h b/ash/common/shelf/shelf_item_types.h
index 998f33b..ea021bb 100644
--- a/ash/common/shelf/shelf_item_types.h
+++ b/ash/common/shelf/shelf_item_types.h
@@ -10,6 +10,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/common/shelf/shelf_constants.h"
+#include "base/strings/string16.h"
 #include "ui/gfx/image/image_skia.h"
 
 namespace ash {
@@ -73,6 +74,9 @@
   // The application id for this shelf item; only populated for some items.
   std::string app_id;
 
+  // The title to display for tooltips, etc.
+  base::string16 title;
+
   // Whether the tooltip should be shown on hover; generally true.
   bool shows_tooltip = true;
 
diff --git a/ash/common/shelf/shelf_model.cc b/ash/common/shelf/shelf_model.cc
index e5254194..a6844758 100644
--- a/ash/common/shelf/shelf_model.cc
+++ b/ash/common/shelf/shelf_model.cc
@@ -43,7 +43,7 @@
 
 }  // namespace
 
-ShelfModel::ShelfModel() : next_id_(1), status_(STATUS_NORMAL) {}
+ShelfModel::ShelfModel() : next_id_(1) {}
 
 ShelfModel::~ShelfModel() {}
 
diff --git a/ash/common/shelf/shelf_model.h b/ash/common/shelf/shelf_model.h
index 112f0b42..a5f61e80 100644
--- a/ash/common/shelf/shelf_model.h
+++ b/ash/common/shelf/shelf_model.h
@@ -18,16 +18,9 @@
 class ShelfItemDelegate;
 class ShelfModelObserver;
 
-// Model used for shelf items. Owns ShelfItemDelegates, but does not create
-// them.
+// Model used for shelf items. Owns ShelfItemDelegates but does not create them.
 class ASH_EXPORT ShelfModel {
  public:
-  enum Status {
-    STATUS_NORMAL,
-    // A status that indicates apps are syncing/loading.
-    STATUS_LOADING,
-  };
-
   ShelfModel();
   ~ShelfModel();
 
@@ -82,9 +75,6 @@
   const ShelfItems& items() const { return items_; }
   int item_count() const { return static_cast<int>(items_.size()); }
 
-  void set_status(Status status) { status_ = status; }
-  Status status() const { return status_; }
-
   // Set |item_delegate| for |id| and takes ownership.
   void SetShelfItemDelegate(ShelfID id,
                             std::unique_ptr<ShelfItemDelegate> item_delegate);
@@ -108,7 +98,6 @@
   ShelfID next_id_;
 
   ShelfItems items_;
-  Status status_;
   base::ObserverList<ShelfModelObserver> observers_;
 
   std::map<ShelfID, std::unique_ptr<ShelfItemDelegate>>
diff --git a/ash/common/shelf/shelf_view.cc b/ash/common/shelf/shelf_view.cc
index 5a6bfaa..48458db 100644
--- a/ash/common/shelf/shelf_view.cc
+++ b/ash/common/shelf/shelf_view.cc
@@ -527,9 +527,7 @@
 
 base::string16 ShelfView::GetTitleForView(const views::View* view) const {
   const ShelfItem* item = ShelfItemForView(view);
-  if (!item || !model_->GetShelfItemDelegate(item->id))
-    return base::string16();
-  return model_->GetShelfItemDelegate(item->id)->GetTitle();
+  return item ? item->title : base::string16();
 }
 
 gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
diff --git a/ash/common/shelf/shelf_window_watcher.cc b/ash/common/shelf/shelf_window_watcher.cc
index 0fd654b..accb7ce 100644
--- a/ash/common/shelf/shelf_window_watcher.cc
+++ b/ash/common/shelf/shelf_window_watcher.cc
@@ -39,6 +39,8 @@
   if (item->image.isNull())
     item->image = window->GetWindowIcon();
 
+  item->title = window->GetTitle();
+
   // Do not show tooltips for visible attached app panel windows.
   item->shows_tooltip =
       item->type != TYPE_APP_PANEL || !window->IsVisible() ||
@@ -109,6 +111,11 @@
   window_watcher_->OnUserWindowPropertyChanged(window);
 }
 
+void ShelfWindowWatcher::UserWindowObserver::OnWindowTitleChanged(
+    WmWindow* window) {
+  window_watcher_->OnUserWindowPropertyChanged(window);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 ShelfWindowWatcher::ShelfWindowWatcher(ShelfModel* model)
diff --git a/ash/common/shelf/shelf_window_watcher.h b/ash/common/shelf/shelf_window_watcher.h
index c523bf15..59564a1 100644
--- a/ash/common/shelf/shelf_window_watcher.h
+++ b/ash/common/shelf/shelf_window_watcher.h
@@ -61,6 +61,7 @@
                                  WmWindowProperty property) override;
     void OnWindowDestroying(WmWindow* window) override;
     void OnWindowVisibilityChanged(WmWindow* window, bool visible) override;
+    void OnWindowTitleChanged(WmWindow* window) override;
 
     ShelfWindowWatcher* window_watcher_;
 
diff --git a/ash/common/shelf/shelf_window_watcher_item_delegate.cc b/ash/common/shelf/shelf_window_watcher_item_delegate.cc
index 0738ce5..303ef6a 100644
--- a/ash/common/shelf/shelf_window_watcher_item_delegate.cc
+++ b/ash/common/shelf/shelf_window_watcher_item_delegate.cc
@@ -55,10 +55,6 @@
   return kExistingWindowActivated;
 }
 
-base::string16 ShelfWindowWatcherItemDelegate::GetTitle() {
-  return window_->GetTitle();
-}
-
 ShelfMenuModel* ShelfWindowWatcherItemDelegate::CreateApplicationMenu(
     int event_flags) {
   return nullptr;
diff --git a/ash/common/shelf/shelf_window_watcher_item_delegate.h b/ash/common/shelf/shelf_window_watcher_item_delegate.h
index 3dab83b3..0591a7dd 100644
--- a/ash/common/shelf/shelf_window_watcher_item_delegate.h
+++ b/ash/common/shelf/shelf_window_watcher_item_delegate.h
@@ -23,7 +23,6 @@
   // ShelfItemDelegate overrides:
   ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/ash/common/system/tray/tray_popup_header_button.cc b/ash/common/system/tray/tray_popup_header_button.cc
index 804fcb8..576ec92e 100644
--- a/ash/common/system/tray/tray_popup_header_button.cc
+++ b/ash/common/system/tray/tray_popup_header_button.cc
@@ -44,7 +44,7 @@
   SetToggledImage(views::Button::STATE_NORMAL,
                   bundle.GetImageNamed(disabled_resource_id).ToImageSkia());
   SetImage(views::Button::STATE_HOVERED,
-           bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia());
+           *bundle.GetImageNamed(enabled_resource_id_hover).ToImageSkia());
   SetToggledImage(
       views::Button::STATE_HOVERED,
       bundle.GetImageNamed(disabled_resource_id_hover).ToImageSkia());
@@ -74,7 +74,7 @@
 void TrayPopupHeaderButton::Initialize(const gfx::ImageSkia& icon,
                                        int accessible_name_id) {
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
-  SetImage(views::Button::STATE_NORMAL, &icon);
+  SetImage(views::Button::STATE_NORMAL, icon);
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   SetAccessibleName(bundle.GetLocalizedString(accessible_name_id));
diff --git a/ash/common/test/test_shelf_item_delegate.cc b/ash/common/test/test_shelf_item_delegate.cc
index f4ee11245..a9a6a96 100644
--- a/ash/common/test/test_shelf_item_delegate.cc
+++ b/ash/common/test/test_shelf_item_delegate.cc
@@ -26,10 +26,6 @@
   return kNoAction;
 }
 
-base::string16 TestShelfItemDelegate::GetTitle() {
-  return window_ ? window_->GetTitle() : base::string16();
-}
-
 ShelfMenuModel* TestShelfItemDelegate::CreateApplicationMenu(int event_flags) {
   return nullptr;
 }
diff --git a/ash/common/test/test_shelf_item_delegate.h b/ash/common/test/test_shelf_item_delegate.h
index e5c88339..9336aa79 100644
--- a/ash/common/test/test_shelf_item_delegate.h
+++ b/ash/common/test/test_shelf_item_delegate.h
@@ -24,7 +24,6 @@
   // ShelfItemDelegate:
   ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/ash/common/wm/overview/window_selector_item.cc b/ash/common/wm/overview/window_selector_item.cc
index 182beb5..647b739 100644
--- a/ash/common/wm/overview/window_selector_item.cc
+++ b/ash/common/wm/overview/window_selector_item.cc
@@ -23,6 +23,7 @@
 #include "ash/common/wm_window.h"
 #include "ash/common/wm_window_property.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/auto_reset.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -37,7 +38,6 @@
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/transform_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
@@ -130,9 +130,8 @@
 WindowSelectorItem::OverviewCloseButton::OverviewCloseButton(
     views::ButtonListener* listener)
     : views::ImageButton(listener) {
-  icon_image_ = gfx::CreateVectorIcon(gfx::VectorIconId::WINDOW_CONTROL_CLOSE,
-                                      kCloseButtonColor);
-  SetImage(views::CustomButton::STATE_NORMAL, &icon_image_);
+  SetImage(views::CustomButton::STATE_NORMAL,
+           gfx::CreateVectorIcon(kWindowControlCloseIcon, kCloseButtonColor));
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   SetMinimumImageSize(gfx::Size(kHeaderHeight, kHeaderHeight));
diff --git a/ash/common/wm/overview/window_selector_item.h b/ash/common/wm/overview/window_selector_item.h
index f2ff9df..65b4293 100644
--- a/ash/common/wm/overview/window_selector_item.h
+++ b/ash/common/wm/overview/window_selector_item.h
@@ -75,8 +75,6 @@
     void ResetListener() { listener_ = nullptr; }
 
    private:
-    gfx::ImageSkia icon_image_;
-
     DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton);
   };
 
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index 0de43d49..a14c83d6 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -8,6 +8,7 @@
 #include "ash/common/frame/caption_buttons/frame_caption_button.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/wm/window_state.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_state_aura.h"
@@ -18,7 +19,6 @@
 #include "ui/display/screen.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -65,8 +65,7 @@
           GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
       for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
         caption_button_container_->SetButtonImage(
-            static_cast<CaptionButtonIcon>(icon),
-            gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+            static_cast<CaptionButtonIcon>(icon), kWindowControlCloseIcon);
       }
 
       AddChildView(caption_button_container_);
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index 9eddf84..14b065bb 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -206,6 +206,20 @@
     "system_tray_update.icon",
     "system_tray_volume_mute.1x.icon",
     "system_tray_volume_mute.icon",
+    "window_control_back.1x.icon",
+    "window_control_back.icon",
+    "window_control_close.1x.icon",
+    "window_control_close.icon",
+    "window_control_left_snapped.1x.icon",
+    "window_control_left_snapped.icon",
+    "window_control_maximize.1x.icon",
+    "window_control_maximize.icon",
+    "window_control_minimize.1x.icon",
+    "window_control_minimize.icon",
+    "window_control_restore.1x.icon",
+    "window_control_restore.icon",
+    "window_control_right_snapped.1x.icon",
+    "window_control_right_snapped.icon",
   ]
 
   output_cc = "$target_gen_dir/vector_icons.cc"
diff --git a/ui/gfx/vector_icons/window_control_back.1x.icon b/ash/resources/vector_icons/window_control_back.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_back.1x.icon
rename to ash/resources/vector_icons/window_control_back.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_back.icon b/ash/resources/vector_icons/window_control_back.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_back.icon
rename to ash/resources/vector_icons/window_control_back.icon
diff --git a/ui/gfx/vector_icons/window_control_close.1x.icon b/ash/resources/vector_icons/window_control_close.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_close.1x.icon
rename to ash/resources/vector_icons/window_control_close.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_close.icon b/ash/resources/vector_icons/window_control_close.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_close.icon
rename to ash/resources/vector_icons/window_control_close.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.1x.icon b/ash/resources/vector_icons/window_control_left_snapped.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_left_snapped.1x.icon
rename to ash/resources/vector_icons/window_control_left_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_left_snapped.icon b/ash/resources/vector_icons/window_control_left_snapped.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_left_snapped.icon
rename to ash/resources/vector_icons/window_control_left_snapped.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.1x.icon b/ash/resources/vector_icons/window_control_maximize.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_maximize.1x.icon
rename to ash/resources/vector_icons/window_control_maximize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_maximize.icon b/ash/resources/vector_icons/window_control_maximize.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_maximize.icon
rename to ash/resources/vector_icons/window_control_maximize.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.1x.icon b/ash/resources/vector_icons/window_control_minimize.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_minimize.1x.icon
rename to ash/resources/vector_icons/window_control_minimize.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_minimize.icon b/ash/resources/vector_icons/window_control_minimize.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_minimize.icon
rename to ash/resources/vector_icons/window_control_minimize.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.1x.icon b/ash/resources/vector_icons/window_control_restore.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_restore.1x.icon
rename to ash/resources/vector_icons/window_control_restore.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_restore.icon b/ash/resources/vector_icons/window_control_restore.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_restore.icon
rename to ash/resources/vector_icons/window_control_restore.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.1x.icon b/ash/resources/vector_icons/window_control_right_snapped.1x.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_right_snapped.1x.icon
rename to ash/resources/vector_icons/window_control_right_snapped.1x.icon
diff --git a/ui/gfx/vector_icons/window_control_right_snapped.icon b/ash/resources/vector_icons/window_control_right_snapped.icon
similarity index 100%
rename from ui/gfx/vector_icons/window_control_right_snapped.icon
rename to ash/resources/vector_icons/window_control_right_snapped.icon
diff --git a/ash/shell/window_watcher.cc b/ash/shell/window_watcher.cc
index 1ca47e1..99ed48b 100644
--- a/ash/shell/window_watcher.cc
+++ b/ash/shell/window_watcher.cc
@@ -110,6 +110,7 @@
                         image_count == 1 ? 255 : 0, image_count == 2 ? 255 : 0);
   image_count = (image_count + 1) % 3;
   item.image = gfx::ImageSkia(gfx::ImageSkiaRep(icon_bitmap, 1.0f));
+  item.title = new_window->GetTitle();
 
   model->Add(item);
 
diff --git a/ash/shell/window_watcher_shelf_item_delegate.cc b/ash/shell/window_watcher_shelf_item_delegate.cc
index 6c45e097..d50371bb 100644
--- a/ash/shell/window_watcher_shelf_item_delegate.cc
+++ b/ash/shell/window_watcher_shelf_item_delegate.cc
@@ -31,10 +31,6 @@
   return kExistingWindowActivated;
 }
 
-base::string16 WindowWatcherShelfItemDelegate::GetTitle() {
-  return watcher_->GetWindowByID(id_)->GetTitle();
-}
-
 ShelfMenuModel* WindowWatcherShelfItemDelegate::CreateApplicationMenu(
     int event_flags) {
   return nullptr;
diff --git a/ash/shell/window_watcher_shelf_item_delegate.h b/ash/shell/window_watcher_shelf_item_delegate.h
index cff7ca2..51925b9 100644
--- a/ash/shell/window_watcher_shelf_item_delegate.h
+++ b/ash/shell/window_watcher_shelf_item_delegate.h
@@ -24,7 +24,6 @@
   // ShelfItemDelegate:
   ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java
index e0af2e267..2f51455 100644
--- a/base/android/java/src/org/chromium/base/LocaleUtils.java
+++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -31,6 +31,8 @@
     private static final Map<String, String> LANGUAGE_MAP_FOR_ANDROID;
 
     static {
+        // A variation of this mapping also exists in:
+        // build/android/gyp/package_resources.py
         HashMap<String, String> mapForChromium = new HashMap<>();
         mapForChromium.put("iw", "he"); // Hebrew
         mapForChromium.put("ji", "yi"); // Yiddish
diff --git a/base/test/ios/wait_util.h b/base/test/ios/wait_util.h
index d938bd9..99127930 100644
--- a/base/test/ios/wait_util.h
+++ b/base/test/ios/wait_util.h
@@ -9,9 +9,6 @@
 #include "base/time/time.h"
 
 namespace base {
-
-class MessageLoop;
-
 namespace test {
 namespace ios {
 
@@ -43,19 +40,6 @@
 // elapsed.
 void SpinRunLoopWithMinDelay(TimeDelta min_delay);
 
-// Deprecated.
-// TODO(fdoray): Remove this once call have been removed from ios_internal.
-TimeDelta TimeUntilCondition(ProceduralBlock action,
-                             ConditionBlock condition,
-                             MessageLoop* message_loop,
-                             TimeDelta timeout);
-
-// Deprecated.
-// TODO(fdoray): Remove this once call have been removed from ios_internal.
-void WaitUntilCondition(ConditionBlock condition,
-                        MessageLoop* message_loop,
-                        TimeDelta timeout);
-
 }  // namespace ios
 }  // namespace test
 }  // namespace base
diff --git a/base/test/ios/wait_util.mm b/base/test/ios/wait_util.mm
index 61bbb69..39a4115 100644
--- a/base/test/ios/wait_util.mm
+++ b/base/test/ios/wait_util.mm
@@ -48,7 +48,7 @@
 }
 
 void WaitUntilCondition(ConditionBlock condition) {
-  WaitUntilCondition(condition, nullptr, TimeDelta());
+  WaitUntilCondition(condition, false, TimeDelta());
 }
 
 void SpinRunLoopWithMaxDelay(TimeDelta max_delay) {
@@ -65,20 +65,6 @@
   }
 }
 
-TimeDelta TimeUntilCondition(ProceduralBlock action,
-                             ConditionBlock condition,
-                             MessageLoop* message_loop,
-                             TimeDelta timeout) {
-  return TimeUntilCondition(action, condition, message_loop != nullptr,
-                            timeout);
-}
-
-void WaitUntilCondition(ConditionBlock condition,
-                        MessageLoop* message_loop,
-                        TimeDelta timeout) {
-  WaitUntilCondition(condition, message_loop != nullptr, timeout);
-}
-
 }  // namespace ios
 }  // namespace test
 }  // namespace base
diff --git a/blimp/client/app/linux/blimp_main.cc b/blimp/client/app/linux/blimp_main.cc
index febfbb8..583db11 100644
--- a/blimp/client/app/linux/blimp_main.cc
+++ b/blimp/client/app/linux/blimp_main.cc
@@ -63,7 +63,7 @@
   return android_fonts_dir;
 }
 
-SkFontMgr* CreateAndroidFontMgr(std::string android_fonts_dir) {
+sk_sp<SkFontMgr> CreateAndroidFontMgr(std::string android_fonts_dir) {
   SkFontMgr_Android_CustomFonts custom;
   custom.fSystemFontUse =
       SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index 82ac496ed..162477c 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -161,14 +161,20 @@
 
 def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
   """Add native libraries to APK."""
+  has_crazy_linker = any('android_linker' in os.path.basename(p)
+                         for p in native_libs)
   for path in native_libs:
     basename = os.path.basename(path)
-    apk_path = 'lib/%s/%s' % (android_abi, basename)
 
     compress = None
-    if (uncompress and os.path.splitext(basename)[1] == '.so'):
+    if (uncompress and os.path.splitext(basename)[1] == '.so'
+        and 'android_linker' not in basename):
       compress = False
+      # Add prefix to prevent android install from extracting upon install.
+      if has_crazy_linker:
+        basename = 'crazy.' + basename
 
+    apk_path = 'lib/%s/%s' % (android_abi, basename)
     build_utils.AddToZipHermetic(out_apk,
                                  apk_path,
                                  src_path=path,
@@ -265,8 +271,9 @@
                               options.uncompress_shared_libraries)
 
         for name in sorted(options.native_lib_placeholders):
-          # Empty libs files are ignored by md5check, but rezip requires them
-          # to be empty in order to identify them as placeholders.
+          # Note: Empty libs files are ignored by md5check (can cause issues
+          # with stale builds when the only change is adding/removing
+          # placeholders).
           apk_path = 'lib/%s/%s' % (options.android_abi, name)
           build_utils.AddToZipHermetic(out_apk, apk_path, data='')
 
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py
index 532d001f..ecb5ebfe 100755
--- a/build/android/gyp/finalize_apk.py
+++ b/build/android/gyp/finalize_apk.py
@@ -21,32 +21,6 @@
 
 from util import build_utils
 
-def RenameInflateAndAddPageAlignment(
-    rezip_apk_jar_path, in_zip_file, out_zip_file):
-  rezip_apk_cmd = [
-      'java',
-      '-classpath',
-      rezip_apk_jar_path,
-      'RezipApk',
-      'renamealign',
-      in_zip_file,
-      out_zip_file,
-    ]
-  build_utils.CheckOutput(rezip_apk_cmd)
-
-
-def ReorderAndAlignApk(rezip_apk_jar_path, in_zip_file, out_zip_file):
-  rezip_apk_cmd = [
-      'java',
-      '-classpath',
-      rezip_apk_jar_path,
-      'RezipApk',
-      'reorder',
-      in_zip_file,
-      out_zip_file,
-    ]
-  build_utils.CheckOutput(rezip_apk_cmd)
-
 
 def JarSigner(key_path, key_name, key_passwd, unsigned_path, signed_path):
   shutil.copy(unsigned_path, signed_path)
@@ -62,14 +36,15 @@
   build_utils.CheckOutput(sign_cmd)
 
 
-def AlignApk(zipalign_path, package_align, unaligned_path, final_path):
+def AlignApk(zipalign_path, unaligned_path, final_path):
+  # Note -p will page align native libraries (files ending with .so), but
+  # only those that are stored uncompressed.
   align_cmd = [
       zipalign_path,
-      '-f'
+      '-p',
+      '-f',
       ]
 
-  if package_align:
-    align_cmd += ['-p']
 
   align_cmd += [
       '4',  # 4 bytes
@@ -85,23 +60,13 @@
   parser = optparse.OptionParser()
   build_utils.AddDepfileOption(parser)
 
-  parser.add_option('--rezip-apk-jar-path',
-                    help='Path to the RezipApk jar file.')
   parser.add_option('--zipalign-path', help='Path to the zipalign tool.')
-  parser.add_option('--page-align-shared-libraries',
-                    action='store_true',
-                    help='Page align shared libraries.')
   parser.add_option('--unsigned-apk-path', help='Path to input unsigned APK.')
   parser.add_option('--final-apk-path',
       help='Path to output signed and aligned APK.')
   parser.add_option('--key-path', help='Path to keystore for signing.')
   parser.add_option('--key-passwd', help='Keystore password')
   parser.add_option('--key-name', help='Keystore name')
-  parser.add_option('--stamp', help='Path to touch on success.')
-  parser.add_option('--load-library-from-zip', type='int',
-      help='If non-zero, build the APK such that the library can be loaded ' +
-           'directly from the zip file using the crazy linker. The library ' +
-           'will be renamed, uncompressed and page aligned.')
 
   options, _ = parser.parse_args()
 
@@ -110,14 +75,9 @@
     options.key_path,
   ]
 
-  if options.load_library_from_zip:
-    input_paths.append(options.rezip_apk_jar_path)
-
   input_strings = [
-    options.load_library_from_zip,
     options.key_name,
     options.key_passwd,
-    options.page_align_shared_libraries,
   ]
 
   build_utils.CallAndWriteDepfileIfStale(
@@ -129,57 +89,34 @@
       output_paths=[options.final_apk_path])
 
 
+def _NormalizeZip(path):
+  with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk:
+    with zipfile.ZipFile(path, 'r') as zi:
+      with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo:
+        for info in zi.infolist():
+          # Ignore 'extended local file headers'. Python doesn't write them
+          # properly (see https://bugs.python.org/issue1742205) which causes
+          # zipalign to miscalculate alignment. Since we don't use them except
+          # for alignment anyway, we write a stripped file here and let
+          # zipalign add them properly later. eLFHs are controlled by 'general
+          # purpose bit flag 03' (0x08) so we mask that out.
+          info.flag_bits = info.flag_bits & 0xF7
+
+          info.date_time = build_utils.HERMETIC_TIMESTAMP
+          zo.writestr(info, zi.read(info.filename))
+
+    shutil.copy(hermetic_signed_apk.name, path)
+
+
 def FinalizeApk(options):
-  with tempfile.NamedTemporaryFile() as signed_apk_path_tmp, \
-      tempfile.NamedTemporaryFile() as apk_to_sign_tmp:
-
-    if options.load_library_from_zip:
-      # We alter the name of the library so that the Android Package Manager
-      # does not extract it into a separate file. This must be done before
-      # signing, as the filename is part of the signed manifest. At the same
-      # time we uncompress the library, which is necessary so that it can be
-      # loaded directly from the APK.
-      # Move the library to a page boundary by adding a page alignment file.
-      apk_to_sign = apk_to_sign_tmp.name
-      RenameInflateAndAddPageAlignment(
-          options.rezip_apk_jar_path, options.unsigned_apk_path, apk_to_sign)
-    else:
-      apk_to_sign = options.unsigned_apk_path
-
+  with tempfile.NamedTemporaryFile() as signed_apk_path_tmp:
     signed_apk_path = signed_apk_path_tmp.name
     JarSigner(options.key_path, options.key_name, options.key_passwd,
-              apk_to_sign, signed_apk_path)
+              options.unsigned_apk_path, signed_apk_path)
+    # Make the newly added signing files hermetic.
+    _NormalizeZip(signed_apk_path)
 
-    # Make the signing files hermetic.
-    with tempfile.NamedTemporaryFile(suffix='.zip') as hermetic_signed_apk:
-      with zipfile.ZipFile(signed_apk_path, 'r') as zi:
-        with zipfile.ZipFile(hermetic_signed_apk, 'w') as zo:
-          for info in zi.infolist():
-            # Ignore 'extended local file headers'. Python doesn't write them
-            # properly (see https://bugs.python.org/issue1742205) which causes
-            # zipalign to miscalculate alignment. Since we don't use them except
-            # for alignment anyway, we write a stripped file here and let
-            # zipalign add them properly later. eLFHs are controlled by 'general
-            # purpose bit flag 03' (0x08) so we mask that out.
-            info.flag_bits = info.flag_bits & 0xF7
-
-            info.date_time = build_utils.HERMETIC_TIMESTAMP
-            zo.writestr(info, zi.read(info.filename))
-
-      shutil.copy(hermetic_signed_apk.name, signed_apk_path)
-
-    if options.load_library_from_zip:
-      # Reorder the contents of the APK. This re-establishes the canonical
-      # order which means the library will be back at its page aligned location.
-      # This step also aligns uncompressed items to 4 bytes.
-      ReorderAndAlignApk(
-          options.rezip_apk_jar_path, signed_apk_path, options.final_apk_path)
-    else:
-      # Align uncompressed items to 4 bytes
-      AlignApk(options.zipalign_path,
-               options.page_align_shared_libraries,
-               signed_apk_path,
-               options.final_apk_path)
+    AlignApk(options.zipalign_path, signed_apk_path, options.final_apk_path)
 
 
 if __name__ == '__main__':
diff --git a/build/android/gyp/package_resources.py b/build/android/gyp/package_resources.py
index 53ba92c..e5e91c9 100755
--- a/build/android/gyp/package_resources.py
+++ b/build/android/gyp/package_resources.py
@@ -23,6 +23,22 @@
 from util import build_utils
 
 
+# A variation of this lists also exists in:
+# //base/android/java/src/org/chromium/base/LocaleUtils.java
+_CHROME_TO_ANDROID_LOCALE_MAP = {
+    'en-GB': 'en-rGB',
+    'en-US': 'en-rUS',
+    'es-419': 'es-rUS',
+    'fin': 'tl',
+    'he': 'iw',
+    'id': 'in',
+    'pt-PT': 'pt-rPT',
+    'pt-BR': 'pt-rBR',
+    'yi': 'ji',
+    'zh-CN': 'zh-rCN',
+    'zh-TW': 'zh-rTW',
+}
+
 # List is generated from the chrome_apk.apk_intermediates.ap_ via:
 #     unzip -l $FILE_AP_ | cut -c31- | grep res/draw | cut -d'/' -f 2 | sort \
 #     | uniq | grep -- -tvdpi- | cut -c10-
@@ -113,7 +129,12 @@
       help='Enables density splits')
   parser.add_option('--language-splits',
                     default='[]',
-                    help='GYP list of languages to create splits for')
+                    help='GN list of languages to create splits for')
+  parser.add_option('--locale-whitelist',
+                    default='[]',
+                    help='GN list of languages to include. All other language '
+                         'configs will be stripped out. List may include '
+                         'a combination of Android locales or Chrome locales.')
 
   parser.add_option('--apk-path',
                     help='Path to output (partial) apk.')
@@ -132,9 +153,26 @@
 
   options.resource_zips = build_utils.ParseGnList(options.resource_zips)
   options.language_splits = build_utils.ParseGnList(options.language_splits)
+  options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
   return options
 
 
+def _ToAaptLocales(locale_whitelist):
+  """Converts the list of Chrome locales to aapt config locales."""
+  ret = set()
+  for locale in locale_whitelist:
+    locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale)
+    if locale is None or ('-' in locale and '-r' not in locale):
+      raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.'
+                      ' Found: %s' % locale)
+    ret.add(locale)
+    # Always keep non-regional fall-backs.
+    language = locale.split('-')[0]
+    ret.add(language)
+
+  return sorted(ret)
+
+
 def MoveImagesToNonMdpiFolders(res_root):
   """Move images from drawable-*-mdpi-* folders to drawable-* folders.
 
@@ -257,6 +295,10 @@
   if 'Debug' in options.configuration_name:
     package_command += ['--debug-mode']
 
+  if options.locale_whitelist:
+    aapt_locales = _ToAaptLocales(options.locale_whitelist)
+    package_command += ['-c', ','.join(aapt_locales)]
+
   return package_command
 
 
diff --git a/build/android/rezip/BUILD.gn b/build/android/rezip/BUILD.gn
deleted file mode 100644
index 1ace37c..0000000
--- a/build/android/rezip/BUILD.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/rules.gni")
-
-java_library("rezip") {
-  jar_path = "$root_build_dir/lib.java/rezip_apk.jar"
-  java_files = [ "RezipApk.java" ]
-}
diff --git a/build/android/rezip/RezipApk.java b/build/android/rezip/RezipApk.java
deleted file mode 100644
index 43d75447..0000000
--- a/build/android/rezip/RezipApk.java
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-
-/**
- * Command line tool used to build APKs which support loading the native code library
- * directly from the APK file. To construct the APK we rename the native library by
- * adding the prefix "crazy." to the filename. This is done to prevent the Android
- * Package Manager from extracting the library. The native code must be page aligned
- * and uncompressed. The page alignment is implemented by adding a zero filled file
- * in front of the the native code library. This tool is designed so that running
- * SignApk and/or zipalign on the resulting APK does not break the page alignment.
- * This is achieved by outputing the filenames in the same canonical order used
- * by SignApk and adding the same alignment fields added by zipalign.
- */
-class RezipApk {
-    // Alignment to use for non-compressed files (must match zipalign).
-    private static final int ALIGNMENT = 4;
-
-    // Alignment to use for non-compressed *.so files
-    private static final int LIBRARY_ALIGNMENT = 4096;
-
-    // Files matching this pattern are not copied to the output when adding alignment.
-    // When reordering and verifying the APK they are copied to the end of the file.
-    private static Pattern sMetaFilePattern =
-            Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|("
-                    + Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
-
-    // Pattern for matching a shared library in the APK
-    private static Pattern sLibraryPattern = Pattern.compile("^lib/[^/]*/lib.*[.]so$");
-    // Pattern for match the crazy linker in the APK
-    private static Pattern sCrazyLinkerPattern =
-            Pattern.compile("^lib/[^/]*/libchromium_android_linker.so$");
-    // Pattern for matching a crazy loaded shared library in the APK
-    private static Pattern sCrazyLibraryPattern = Pattern.compile("^lib/[^/]*/crazy.lib.*[.]so$");
-
-    private static boolean isLibraryFilename(String filename) {
-        return sLibraryPattern.matcher(filename).matches()
-                && !sCrazyLinkerPattern.matcher(filename).matches();
-    }
-
-    private static boolean isCrazyLibraryFilename(String filename) {
-        return sCrazyLibraryPattern.matcher(filename).matches();
-    }
-
-    private static String renameLibraryForCrazyLinker(String filename) {
-        int lastSlash = filename.lastIndexOf('/');
-        // We rename the library, so that the Android Package Manager
-        // no longer extracts the library.
-        return filename.substring(0, lastSlash + 1) + "crazy." + filename.substring(lastSlash + 1);
-    }
-
-    /**
-     * Wraps another output stream, counting the number of bytes written.
-     */
-    private static class CountingOutputStream extends OutputStream {
-        private long mCount = 0;
-        private OutputStream mOut;
-
-        public CountingOutputStream(OutputStream out) {
-            this.mOut = out;
-        }
-
-        /** Returns the number of bytes written. */
-        public long getCount() {
-            return mCount;
-        }
-
-        @Override public void write(byte[] b, int off, int len) throws IOException {
-            mOut.write(b, off, len);
-            mCount += len;
-        }
-
-        @Override public void write(int b) throws IOException {
-            mOut.write(b);
-            mCount++;
-        }
-
-        @Override public void close() throws IOException {
-            mOut.close();
-        }
-
-        @Override public void flush() throws IOException {
-            mOut.flush();
-        }
-    }
-
-    private static String outputName(JarEntry entry, boolean rename) {
-        String inName = entry.getName();
-        if (rename && entry.getSize() > 0 && isLibraryFilename(inName)) {
-            return renameLibraryForCrazyLinker(inName);
-        }
-        return inName;
-    }
-
-    /**
-     * Comparator used to sort jar entries from the input file.
-     * Sorting is done based on the output filename (which maybe renamed).
-     * Filenames are in natural string order, except that filenames matching
-     * the meta-file pattern are always after other files. This is so the manifest
-     * and signature are at the end of the file after any alignment file.
-     */
-    private static class EntryComparator implements Comparator<JarEntry> {
-        private boolean mRename;
-
-        public EntryComparator(boolean rename) {
-            mRename = rename;
-        }
-
-        @Override
-        public int compare(JarEntry j1, JarEntry j2) {
-            String o1 = outputName(j1, mRename);
-            String o2 = outputName(j2, mRename);
-            boolean o1Matches = sMetaFilePattern.matcher(o1).matches();
-            boolean o2Matches = sMetaFilePattern.matcher(o2).matches();
-            if (o1Matches != o2Matches) {
-                return o1Matches ? 1 : -1;
-            } else {
-                return o1.compareTo(o2);
-            }
-        }
-    }
-
-    // Build an ordered list of jar entries. The jar entries from the input are
-    // sorted based on the output filenames (which maybe renamed). If |omitMetaFiles|
-    // is true do not include the jar entries for the META-INF files.
-    // Entries are ordered in the deterministic order used by SignApk.
-    private static List<JarEntry> getOutputFileOrderEntries(
-            JarFile jar, boolean omitMetaFiles, boolean rename) {
-        List<JarEntry> entries = new ArrayList<JarEntry>();
-        for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
-            JarEntry entry = e.nextElement();
-            if (entry.isDirectory()) {
-                continue;
-            }
-            if (omitMetaFiles && sMetaFilePattern.matcher(entry.getName()).matches()) {
-                continue;
-            }
-            entries.add(entry);
-        }
-
-        // We sort the input entries by name. When present META-INF files
-        // are sorted to the end.
-        Collections.sort(entries, new EntryComparator(rename));
-        return entries;
-    }
-
-    /**
-     * Add a zero filled alignment file at this point in the zip file,
-     * The added file will be added before |name| and after |prevName|.
-     * The size of the alignment file is such that the location of the
-     * file |name| will be on a LIBRARY_ALIGNMENT boundary.
-     *
-     * Note this arrangement is devised so that running SignApk and/or zipalign on the resulting
-     * file will not alter the alignment.
-     *
-     * @param offset number of bytes into the output file at this point.
-     * @param timestamp time in millis since the epoch to include in the header.
-     * @param name the name of the library filename.
-     * @param prevName the name of the previous file in the archive (or null).
-     * @param out jar output stream to write the alignment file to.
-     *
-     * @throws IOException if the output file can not be written.
-     */
-    private static void addAlignmentFile(
-            long offset, long timestamp, String name, String prevName,
-            JarOutputStream out) throws IOException {
-
-        // Compute the start and alignment of the library, as if it was next.
-        int headerSize = JarFile.LOCHDR + name.length();
-        long libOffset = offset + headerSize;
-        int libNeeded = LIBRARY_ALIGNMENT - (int) (libOffset % LIBRARY_ALIGNMENT);
-        if (libNeeded == LIBRARY_ALIGNMENT) {
-            // Already aligned, no need to added alignment file.
-            return;
-        }
-
-        // Check that there is not another file between the library and the
-        // alignment file.
-        String alignName = name.substring(0, name.length() - 2) + "align";
-        if (prevName != null && prevName.compareTo(alignName) >= 0) {
-            throw new UnsupportedOperationException(
-                "Unable to insert alignment file, because there is "
-                + "another file in front of the file to be aligned. "
-                + "Other file: " + prevName + " Alignment file: " + alignName
-                + " file: " + name);
-        }
-
-        // Compute the size of the alignment file header.
-        headerSize = JarFile.LOCHDR + alignName.length();
-        // We are going to add an alignment file of type STORED. This file
-        // will itself induce a zipalign alignment adjustment.
-        int extraNeeded =
-                (ALIGNMENT - (int) ((offset + headerSize) % ALIGNMENT)) % ALIGNMENT;
-        headerSize += extraNeeded;
-
-        if (libNeeded < headerSize + 1) {
-            // The header was bigger than the alignment that we need, add another page.
-            libNeeded += LIBRARY_ALIGNMENT;
-        }
-        // Compute the size of the alignment file.
-        libNeeded -= headerSize;
-
-        // Build the header for the alignment file.
-        byte[] zeroBuffer = new byte[libNeeded];
-        JarEntry alignEntry = new JarEntry(alignName);
-        alignEntry.setMethod(JarEntry.STORED);
-        alignEntry.setSize(libNeeded);
-        alignEntry.setTime(timestamp);
-        CRC32 crc = new CRC32();
-        crc.update(zeroBuffer);
-        alignEntry.setCrc(crc.getValue());
-
-        if (extraNeeded != 0) {
-            alignEntry.setExtra(new byte[extraNeeded]);
-        }
-
-        // Output the alignment file.
-        out.putNextEntry(alignEntry);
-        out.write(zeroBuffer);
-        out.closeEntry();
-        out.flush();
-    }
-
-    // Make a JarEntry for the output file which corresponds to the input
-    // file. The output file will be called |name|. The output file will always
-    // be uncompressed (STORED). If the input is not STORED it is necessary to inflate
-    // it to compute the CRC and size of the output entry.
-    private static JarEntry makeStoredEntry(String name, JarEntry inEntry, JarFile in)
-            throws IOException {
-        JarEntry outEntry = new JarEntry(name);
-        outEntry.setMethod(JarEntry.STORED);
-
-        if (inEntry.getMethod() == JarEntry.STORED) {
-            outEntry.setCrc(inEntry.getCrc());
-            outEntry.setSize(inEntry.getSize());
-        } else {
-            // We are inflating the file. We need to compute the CRC and size.
-            byte[] buffer = new byte[4096];
-            CRC32 crc = new CRC32();
-            int size = 0;
-            int num;
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                crc.update(buffer, 0, num);
-                size += num;
-            }
-            data.close();
-            outEntry.setCrc(crc.getValue());
-            outEntry.setSize(size);
-        }
-        return outEntry;
-    }
-
-    /**
-     * Copy the contents of the input APK file to the output APK file. If |rename| is
-     * true then non-empty libraries (*.so) in the input will be renamed by prefixing
-     * "crazy.". This is done to prevent the Android Package Manager extracting the
-     * library. Note the crazy linker itself is not renamed, for bootstrapping reasons.
-     * Empty libraries are not renamed (they are in the APK to workaround a bug where
-     * the Android Package Manager fails to delete old versions when upgrading).
-     * There must be exactly one "crazy" library in the output stream. The "crazy"
-     * library will be uncompressed and page aligned in the output stream. Page
-     * alignment is implemented by adding a zero filled file, regular alignment is
-     * implemented by adding a zero filled extra field to the zip file header. If
-     * |addAlignment| is true a page alignment file is added, otherwise the "crazy"
-     * library must already be page aligned. Care is taken so that the output is generated
-     * in the same way as SignApk. This is important so that running SignApk and
-     * zipalign on the output does not break the page alignment. The archive may not
-     * contain a "*.apk" as SignApk has special nested signing logic that we do not
-     * support.
-     *
-     * @param in The input APK File.
-     * @param out The output APK stream.
-     * @param countOut Counting output stream (to measure the current offset).
-     * @param addAlignment Whether to add the alignment file or just check.
-     * @param rename Whether to rename libraries to be "crazy".
-     *
-     * @throws IOException if the output file can not be written.
-     */
-    private static void rezip(
-            JarFile in, JarOutputStream out, CountingOutputStream countOut,
-            boolean addAlignment, boolean rename) throws IOException {
-
-        List<JarEntry> entries = getOutputFileOrderEntries(in, addAlignment, rename);
-        long timestamp = System.currentTimeMillis();
-        byte[] buffer = new byte[4096];
-        boolean firstEntry = true;
-        String prevName = null;
-        int numCrazy = 0;
-        for (JarEntry inEntry : entries) {
-            // Rename files, if specied.
-            String name = outputName(inEntry, rename);
-            if (name.endsWith(".apk")) {
-                throw new UnsupportedOperationException(
-                        "Nested APKs are not supported: " + name);
-            }
-
-            // Build the header.
-            JarEntry outEntry = null;
-            boolean isCrazy = isCrazyLibraryFilename(name);
-            if (isCrazy) {
-                // "crazy" libraries are alway output uncompressed (STORED).
-                outEntry = makeStoredEntry(name, inEntry, in);
-                numCrazy++;
-                if (numCrazy > 1) {
-                    throw new UnsupportedOperationException(
-                            "Found more than one library\n"
-                            + "Multiple libraries are not supported for APKs that use "
-                            + "'load_library_from_zip'.\n"
-                            + "See crbug/388223.\n"
-                            + "Note, check that your build is clean.\n"
-                            + "An unclean build can incorrectly incorporate old "
-                            + "libraries in the APK.");
-                }
-            } else if (inEntry.getMethod() == JarEntry.STORED) {
-                // Preserve the STORED method of the input entry.
-                outEntry = new JarEntry(inEntry);
-                outEntry.setExtra(null);
-            } else {
-                // Create a new entry so that the compressed len is recomputed.
-                outEntry = new JarEntry(name);
-            }
-            outEntry.setTime(timestamp);
-
-            // Compute and add alignment
-            long offset = countOut.getCount();
-            if (firstEntry) {
-                // The first entry in a jar file has an extra field of
-                // four bytes that you can't get rid of; any extra
-                // data you specify in the JarEntry is appended to
-                // these forced four bytes.  This is JAR_MAGIC in
-                // JarOutputStream; the bytes are 0xfeca0000.
-                firstEntry = false;
-                offset += 4;
-            }
-            if (outEntry.getMethod() == JarEntry.STORED) {
-                if (isCrazy) {
-                    if (addAlignment) {
-                        addAlignmentFile(offset, timestamp, name, prevName, out);
-                    }
-                    // We check that we did indeed get to a page boundary.
-                    offset = countOut.getCount() + JarFile.LOCHDR + name.length();
-                    if ((offset % LIBRARY_ALIGNMENT) != 0) {
-                        throw new AssertionError(
-                                "Library was not page aligned when verifying page alignment. "
-                                + "Library name: " + name + " Expected alignment: "
-                                + LIBRARY_ALIGNMENT + "Offset: " + offset + " Error: "
-                                + (offset % LIBRARY_ALIGNMENT));
-                    }
-                } else {
-                    // This is equivalent to zipalign.
-                    offset += JarFile.LOCHDR + name.length();
-                    int needed = (ALIGNMENT - (int) (offset % ALIGNMENT)) % ALIGNMENT;
-                    if (needed != 0) {
-                        outEntry.setExtra(new byte[needed]);
-                    }
-                }
-            }
-            out.putNextEntry(outEntry);
-
-            // Copy the data from the input to the output
-            int num;
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                out.write(buffer, 0, num);
-            }
-            data.close();
-            out.closeEntry();
-            out.flush();
-            prevName = name;
-        }
-        if (numCrazy == 0) {
-            throw new AssertionError("There was no crazy library in the archive");
-        }
-    }
-
-    private static void usage() {
-        System.err.println("Usage: prealignapk (addalignment|reorder) input.apk output.apk");
-        System.err.println("\"crazy\" libraries are always inflated in the output");
-        System.err.println(
-                "  renamealign  - rename libraries with \"crazy.\" prefix and add alignment file");
-        System.err.println("  align        - add alignment file");
-        System.err.println("  reorder      - re-creates canonical ordering and checks alignment");
-        System.exit(2);
-    }
-
-    public static void main(String[] args) throws IOException {
-        if (args.length != 3) usage();
-
-        boolean addAlignment = false;
-        boolean rename = false;
-        if (args[0].equals("renamealign")) {
-            // Normal case. Before signing we rename the library and add an alignment file.
-            addAlignment = true;
-            rename = true;
-        } else if (args[0].equals("align")) {
-            // LGPL compliance case. Before signing, we add an alignment file to a
-            // reconstructed APK which already contains the "crazy" library.
-            addAlignment = true;
-            rename = false;
-        } else if (args[0].equals("reorder")) {
-            // Normal case. After jarsigning we write the file in the canonical order and check.
-            addAlignment = false;
-        } else {
-            usage();
-        }
-
-        String inputFilename = args[1];
-        String outputFilename = args[2];
-
-        JarFile inputJar = null;
-        FileOutputStream outputFile = null;
-
-        try {
-            inputJar = new JarFile(new File(inputFilename), true);
-            outputFile = new FileOutputStream(outputFilename);
-
-            CountingOutputStream outCount = new CountingOutputStream(outputFile);
-            JarOutputStream outputJar = new JarOutputStream(outCount);
-
-            // Match the compression level used by SignApk.
-            outputJar.setLevel(9);
-
-            rezip(inputJar, outputJar, outCount, addAlignment, rename);
-            outputJar.close();
-        } finally {
-            if (inputJar != null) inputJar.close();
-            if (outputFile != null) outputFile.close();
-        }
-    }
-}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index b7a42d3..9b50a705 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -32,7 +32,6 @@
 
   # TODO(agrieve): Rename targets below to match above patterns.
   "*android_webview/glue:glue",
-  "//build/android/rezip:rezip",
   "//chrome/test/android/cast_emulator:cast_emulator",
 ]
 
@@ -1393,7 +1392,6 @@
   #   keystore_path: Path to keystore to use for signing.
   #   keystore_name: Key alias to use.
   #   keystore_password: Keystore password.
-  #   rezip_apk: Whether to add crazy-linker alignment.
   template("finalize_apk") {
     action(target_name) {
       deps = []
@@ -1436,20 +1434,6 @@
         "--key-passwd",
         invoker.keystore_password,
       ]
-      if (defined(invoker.rezip_apk) && invoker.rezip_apk) {
-        deps += [ "//build/android/rezip" ]
-        _rezip_jar_path = "$root_build_dir/lib.java/rezip_apk.jar"
-        args += [
-          "--load-library-from-zip=1",
-          "--rezip-apk-jar-path",
-          rebase_path(_rezip_jar_path, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.page_align_shared_libraries) &&
-          invoker.page_align_shared_libraries) {
-        args += [ "--page-align-shared-libraries" ]
-      }
     }
   }
 
@@ -1608,6 +1592,9 @@
             outputs += [ "${invoker.resource_packaged_apk_path}_${_language}" ]
           }
         }
+        if (defined(invoker.aapt_locale_whitelist)) {
+          args += [ "--locale-whitelist=${invoker.aapt_locale_whitelist}" ]
+        }
         if (defined(invoker.extensions_to_not_compress)) {
           args += [
             "--no-compress",
@@ -1621,6 +1608,7 @@
     package_resources_helper(_package_resources_target_name) {
       forward_variables_from(invoker,
                              [
+                               "aapt_locale_whitelist",
                                "alternative_android_sdk_jar",
                                "android_aapt_path",
                                "extensions_to_not_compress",
@@ -1669,6 +1657,7 @@
     package_resources_helper(_incremental_package_resources_target_name) {
       forward_variables_from(invoker,
                              [
+                               "aapt_locale_whitelist",
                                "alternative_android_sdk_jar",
                                "android_aapt_path",
                                "extensions_to_not_compress",
@@ -1692,6 +1681,9 @@
                                "uncompress_shared_libraries",
                                "write_asset_list",
                              ])
+      if (!defined(uncompress_shared_libraries)) {
+        uncompress_shared_libraries = _load_library_from_apk
+      }
       deps = _deps + [ ":${_package_resources_target_name}" ]
       native_libs = _native_libs + _native_libs_even_when_incremental
 
@@ -1712,6 +1704,9 @@
                                "secondary_native_libs",
                                "uncompress_shared_libraries",
                              ])
+      if (!defined(uncompress_shared_libraries)) {
+        uncompress_shared_libraries = _load_library_from_apk
+      }
       _dex_target = "//build/android/incremental_install:bootstrap_java__dex"
       deps = _incremental_deps + [
                ":${_incremental_package_resources_target_name}",
@@ -1738,14 +1733,11 @@
 
     _finalize_apk_rule_name = "${target_name}__finalize"
     finalize_apk(_finalize_apk_rule_name) {
-      forward_variables_from(invoker, [ "page_align_shared_libraries" ])
-
       input_apk_path = _packaged_apk_path
       output_apk_path = _final_apk_path
       keystore_path = _keystore_path
       keystore_name = _keystore_name
       keystore_password = _keystore_password
-      rezip_apk = _load_library_from_apk
 
       public_deps = [
         # Generator of the _packaged_apk_path this target takes as input.
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 2a45db4..075c8a77 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1406,6 +1406,8 @@
   #   proguard_jar_path: The path to proguard.jar you wish to use. If undefined,
   #     the proguard used will be the checked in one in //third_party/proguard.
   #   never_incremental: If true, |incremental_apk_by_default| will be ignored.
+  #   aapt_locale_whitelist: If set, all locales not in this list will be
+  #     stripped from resources.arsc.
   #
   # Example
   #   android_apk("foo_apk") {
@@ -2007,15 +2009,7 @@
     _extra_native_libs_deps = []
     assert(_extra_native_libs_deps == [])  # Mark as used.
     _extra_native_libs_even_when_incremental = []
-    _extra_native_libs_even_when_incremental_deps = []
-    assert(_extra_native_libs_even_when_incremental_deps == [])  # Mark as used.
     if (_native_libs_deps != []) {
-      # zipalign can't align gdb_server, don't pack gdbserver temporarily.
-      if (is_debug && (!defined(invoker.page_align_shared_libraries) ||
-                       !invoker.page_align_shared_libraries)) {
-        _extra_native_libs_even_when_incremental = [ android_gdbserver ]
-      }
-
       if (_use_chromium_linker) {
         _extra_native_libs =
             [ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ]
@@ -2031,13 +2025,13 @@
     create_apk("${_template_name}__create") {
       forward_variables_from(invoker,
                              [
+                               "aapt_locale_whitelist",
                                "alternative_android_sdk_jar",
                                "android_aapt_path",
                                "app_as_shared_lib",
                                "deps",
                                "extensions_to_not_compress",
                                "language_splits",
-                               "page_align_shared_libraries",
                                "public_deps",
                                "secondary_native_libs",
                                "shared_resources",
@@ -2087,7 +2081,6 @@
            _extra_native_libs_even_when_incremental != []) &&
           !_create_abi_split) {
         deps += _native_libs_deps + _extra_native_libs_deps +
-                _extra_native_libs_even_when_incremental_deps +
                 [ _native_libs_file_arg_dep ]
         native_libs_filearg = _native_libs_file_arg
         native_libs = _extra_native_libs
@@ -2148,9 +2141,7 @@
                                  "public_deps",
                                ])
 
-        incremental_deps =
-            deps + _extra_native_libs_even_when_incremental_deps +
-            [ ":$_manifest_rule" ]
+        incremental_deps = deps + [ ":$_manifest_rule" ]
         deps = []
         deps = incremental_deps + _native_libs_deps + _extra_native_libs_deps +
                [ _native_libs_file_arg_dep ]
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index 7dad6aa..8611e5a4 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -997,15 +997,53 @@
   _has_public_headers =
       defined(invoker.public_headers) && invoker.public_headers != []
 
+  # Public configs are not propagated across toolchain (see crbug.com/675224)
+  # so some configs have to be defined for both default_toolchain and all others
+  # toolchains when performing a fat build. Use "get_label_info" to construct
+  # the path since they need to be relative to the default_toolchain.
+
+  _default_toolchain_root_out_dir =
+      get_label_info("$_target_name($default_toolchain)", "root_out_dir")
+  _default_toolchain_target_gen_dir =
+      get_label_info("$_target_name($default_toolchain)", "target_gen_dir")
+
   if (_has_public_headers) {
     _framework_headers_target = _target_name + "_framework_headers"
     _framework_headers_config = _target_name + "_framework_headers_config"
+    config(_framework_headers_config) {
+      # The link settings are inherited from the framework_bundle config.
+      cflags = [
+        "-F",
+        rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir),
+      ]
+    }
+
     _headers_map_config = _target_name + "_headers_map"
+    _header_map_filename =
+        "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap"
+    config(_headers_map_config) {
+      visibility = [ ":$_target_name" ]
+      include_dirs = [ _header_map_filename ]
+    }
   }
 
   _arch_shared_library_source = _target_name + "_arch_shared_library_sources"
   _arch_shared_library_target = _target_name + "_arch_shared_library"
   _lipo_shared_library_target = _target_name + "_shared_library"
+  _link_target_name = _target_name + "+link"
+
+  _framework_public_config = _target_name + "_public_config"
+  config(_framework_public_config) {
+    # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs
+    # and include_dirs to avoid duplicate values on the command-line.
+    visibility = [ ":$_target_name" ]
+    ldflags = [
+      "-F",
+      rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir),
+    ]
+    lib_dirs = [ root_out_dir ]
+    libs = [ "$_output_name.framework" ]
+  }
 
   source_set(_arch_shared_library_source) {
     forward_variables_from(invoker,
@@ -1025,8 +1063,8 @@
 
     if (_has_public_headers) {
       configs += [
-        ":$_framework_headers_config($default_toolchain)",
-        ":$_headers_map_config($default_toolchain)",
+        ":$_framework_headers_config",
+        ":$_headers_map_config",
       ]
 
       if (!defined(deps)) {
@@ -1097,15 +1135,24 @@
       ]
     }
 
-    group(_target_name + "+link") {
+    group(_link_target_name) {
       forward_variables_from(invoker,
                              [
+                               "public_configs",
                                "visibility",
                                "testonly",
                              ])
       public_deps = [
-        ":$_target_name+link($default_toolchain)",
+        ":$_link_target_name($default_toolchain)",
       ]
+
+      if (!defined(public_configs)) {
+        public_configs = []
+      }
+      public_configs += [ ":$_framework_public_config" ]
+      if (_has_public_headers) {
+        public_configs += [ ":$_framework_headers_config" ]
+      }
     }
 
     if (defined(invoker.bundle_deps)) {
@@ -1116,8 +1163,6 @@
       _public_headers = invoker.public_headers
       _framework_root = "$root_out_dir/$_output_name.framework"
 
-      _header_map_filename = "$target_gen_dir/$_output_name.headers.hmap"
-
       _compile_headers_map_target = _target_name + "_compile_headers_map"
       action(_compile_headers_map_target) {
         visibility = [ ":$_framework_headers_target" ]
@@ -1165,11 +1210,6 @@
         ]
       }
 
-      config(_headers_map_config) {
-        visibility = [ ":$_target_name" ]
-        include_dirs = [ _header_map_filename ]
-      }
-
       group(_framework_headers_target) {
         deps = [
           ":$_compile_headers_map_target",
@@ -1177,14 +1217,6 @@
           ":$_create_module_map_target",
         ]
       }
-
-      config(_framework_headers_config) {
-        # The link settings are inherited from the framework_bundle config.
-        cflags = [
-          "-F",
-          rebase_path("$root_out_dir/.", root_build_dir),
-        ]
-      }
     }
 
     lipo_binary(_lipo_shared_library_target) {
@@ -1200,19 +1232,6 @@
       arch_binary_output = _output_name
     }
 
-    _framework_public_config = _target_name + "_public_config"
-    config(_framework_public_config) {
-      # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs
-      # and include_dirs to avoid duplicate values on the command-line.
-      visibility = [ ":$_target_name" ]
-      ldflags = [
-        "-F",
-        rebase_path("$root_out_dir/.", root_build_dir),
-      ]
-      lib_dirs = [ root_out_dir ]
-      libs = [ "$_output_name.framework" ]
-    }
-
     _info_plist_target = _target_name + "_info_plist"
     _info_plist_bundle = _target_name + "_info_plist_bundle"
     ios_info_plist(_info_plist_target) {
@@ -1265,11 +1284,11 @@
       deps += [ ":$_info_plist_bundle" ]
     }
 
-    group(_target_name + "+link") {
+    group(_link_target_name) {
       forward_variables_from(invoker,
                              [
-                               "public_deps",
                                "public_configs",
+                               "public_deps",
                                "testonly",
                                "visibility",
                              ])
@@ -1277,11 +1296,11 @@
         public_deps = []
       }
       public_deps += [ ":$_target_name" ]
+
       if (!defined(public_configs)) {
         public_configs = []
       }
       public_configs += [ ":$_framework_public_config" ]
-
       if (_has_public_headers) {
         public_configs += [ ":$_framework_headers_config" ]
       }
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index d964493..0252503c 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -55,7 +55,7 @@
   #
   # TODO(pcc): Remove this flag if/when CFI is enabled in all official builds.
   is_cfi = target_os == "linux" && !is_chromeos && target_cpu == "x64" &&
-           is_chrome_branded && is_official_build && allow_posix_link_time_opt
+           is_official_build && allow_posix_link_time_opt
 
   # Enable checks for bad casts: derived cast and unrelated cast.
   # TODO(krasin): remove this, when we're ready to add these checks by default.
diff --git a/build/linux/sysroot_scripts/packagelist.precise.amd64 b/build/linux/sysroot_scripts/packagelist.precise.amd64
index ccb2973..9bf1deb 100644
--- a/build/linux/sysroot_scripts/packagelist.precise.amd64
+++ b/build/linux/sysroot_scripts/packagelist.precise.amd64
@@ -125,7 +125,7 @@
 main/libx/libxtst/libxtst6_1.2.0-4ubuntu0.1_amd64.deb
 main/libx/libxtst/libxtst-dev_1.2.0-4ubuntu0.1_amd64.deb
 main/libx/libxxf86vm/libxxf86vm1_1.1.1-2ubuntu0.1_amd64.deb
-main/l/linux/linux-libc-dev_3.2.0-119.162_amd64.deb
+main/l/linux/linux-libc-dev_3.2.0-120.163_amd64.deb
 main/m/mesa/libegl1-mesa_8.0.4-0ubuntu0.7_amd64.deb
 main/m/mesa/libegl1-mesa-dev_8.0.4-0ubuntu0.7_amd64.deb
 main/m/mesa/libegl1-mesa-drivers_8.0.4-0ubuntu0.7_amd64.deb
@@ -135,8 +135,8 @@
 main/m/mesa/mesa-common-dev_8.0.4-0ubuntu0.7_amd64.deb
 main/n/nspr/libnspr4_4.12-0ubuntu0.12.04.1_amd64.deb
 main/n/nspr/libnspr4-dev_4.12-0ubuntu0.12.04.1_amd64.deb
-main/n/nss/libnss3_3.23-0ubuntu0.12.04.1_amd64.deb
-main/n/nss/libnss3-dev_3.23-0ubuntu0.12.04.1_amd64.deb
+main/n/nss/libnss3_3.26.2-0ubuntu0.12.04.1_amd64.deb
+main/n/nss/libnss3-dev_3.26.2-0ubuntu0.12.04.1_amd64.deb
 main/o/openssl/libssl1.0.0_1.0.1-4ubuntu5.38_amd64.deb
 main/o/openssl/libssl-dev_1.0.1-4ubuntu5.38_amd64.deb
 main/o/orbit2/liborbit2_2.14.19-0.1ubuntu1_amd64.deb
diff --git a/build/linux/sysroot_scripts/packagelist.trusty.arm b/build/linux/sysroot_scripts/packagelist.trusty.arm
index 7cb20277..1f74a07 100644
--- a/build/linux/sysroot_scripts/packagelist.trusty.arm
+++ b/build/linux/sysroot_scripts/packagelist.trusty.arm
@@ -113,15 +113,15 @@
 main/libx/libxtst/libxtst6_1.2.2-1_armhf.deb
 main/libx/libxtst/libxtst-dev_1.2.2-1_armhf.deb
 main/libx/libxxf86vm/libxxf86vm1_1.1.3-1_armhf.deb
-main/l/linux/linux-libc-dev_3.13.0-106.153_armhf.deb
+main/l/linux/linux-libc-dev_3.13.0-107.154_armhf.deb
 main/m/mesa/libgl1-mesa-dev_10.1.3-0ubuntu0.6_armhf.deb
 main/m/mesa/libgl1-mesa-glx_10.1.3-0ubuntu0.6_armhf.deb
 main/m/mesa/libglapi-mesa_10.1.3-0ubuntu0.6_armhf.deb
 main/m/mesa/mesa-common-dev_10.1.3-0ubuntu0.6_armhf.deb
 main/n/nspr/libnspr4_4.12-0ubuntu0.14.04.1_armhf.deb
 main/n/nspr/libnspr4-dev_4.12-0ubuntu0.14.04.1_armhf.deb
-main/n/nss/libnss3_3.23-0ubuntu0.14.04.1_armhf.deb
-main/n/nss/libnss3-dev_3.23-0ubuntu0.14.04.1_armhf.deb
+main/n/nss/libnss3_3.26.2-0ubuntu0.14.04.3_armhf.deb
+main/n/nss/libnss3-dev_3.26.2-0ubuntu0.14.04.3_armhf.deb
 main/o/openssl/libssl1.0.0_1.0.1f-1ubuntu2.21_armhf.deb
 main/o/openssl/libssl-dev_1.0.1f-1ubuntu2.21_armhf.deb
 main/o/orbit2/liborbit2_2.14.19-0.3_armhf.deb
diff --git a/build/linux/sysroot_scripts/sysroots.json b/build/linux/sysroot_scripts/sysroots.json
index 336fdca..71abb95 100644
--- a/build/linux/sysroot_scripts/sysroots.json
+++ b/build/linux/sysroot_scripts/sysroots.json
@@ -1,67 +1,67 @@
 {
     "jessie_amd64": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "cc59aa719e061602e73a4868aad0ca160844b7fe",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "bae4459dbc24b86e92fba57b42e4ae9d540dd556",
         "SysrootDir": "debian_jessie_amd64-sysroot",
         "Tarball": "debian_jessie_amd64_sysroot.tgz"
     },
     "jessie_arm": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "96f6f81439955d0c9db49419ff5e4a38d1825b90",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "35a4b9eebbe6e495c1c10c668af091e3eded072f",
         "SysrootDir": "debian_jessie_arm-sysroot",
         "Tarball": "debian_jessie_arm_sysroot.tgz"
     },
     "jessie_arm64": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "4a9d0ea988e6d816d6abc59b2674f6769b535012",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "a28b37b47654cd02c07d0f47f1748c2b5b4b9586",
         "SysrootDir": "debian_jessie_arm64-sysroot",
         "Tarball": "debian_jessie_arm64_sysroot.tgz"
     },
     "jessie_i386": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "34b122c9ca411beb957d157d5a6696c9fa93e1db",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "c188bab82a303350e8182e289ea4f229f391a8b9",
         "SysrootDir": "debian_jessie_i386-sysroot",
         "Tarball": "debian_jessie_i386_sysroot.tgz"
     },
     "jessie_mips": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "25e8df7da22f97f900765094228f77cb72bebd87",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "70618d0f516f72ecc3b3eea2ae0a7151a519c0ff",
         "SysrootDir": "debian_jessie_mips-sysroot",
         "Tarball": "debian_jessie_mips_sysroot.tgz"
     },
     "precise_amd64": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "42223d9e127dda8d1512160ee96de312ec533556",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "6ea6b7f057c8a6d931ed12b1b37a4d5b4155c18e",
         "SysrootDir": "ubuntu_precise_amd64-sysroot",
         "Tarball": "ubuntu_precise_amd64_sysroot.tgz"
     },
     "trusty_arm": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "418e471ed3a90ad731ef4c1e7a1ef76518a0f8ac",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "0c18bacd8f629d0015dc3eba08509a81b35441d9",
         "SysrootDir": "ubuntu_trusty_arm-sysroot",
         "Tarball": "ubuntu_trusty_arm_sysroot.tgz"
     },
     "wheezy_amd64": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "762e8a060f3c3f9e14f76db5ce982a232b55bcbd",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "0c2fc59cc7d4dedc66e4467f1872ad3f54789bb6",
         "SysrootDir": "debian_wheezy_amd64-sysroot",
         "Tarball": "debian_wheezy_amd64_sysroot.tgz"
     },
     "wheezy_arm": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "2d356d060bf5017cc29d10bef4e09e4e9f65b0f0",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "e9e0f4b016ef2f662a0937ee8e3a877f34274d1b",
         "SysrootDir": "debian_wheezy_arm-sysroot",
         "Tarball": "debian_wheezy_arm_sysroot.tgz"
     },
     "wheezy_i386": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "9db92d45167d1b1cc78a338f49a84929ee3b1928",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "fd53c411577759949e28905fe9c6003458dcafa0",
         "SysrootDir": "debian_wheezy_i386-sysroot",
         "Tarball": "debian_wheezy_i386_sysroot.tgz"
     },
     "wheezy_mips": {
-        "Revision": "165d7c5a152048a7ca8f55c44e0c2efae90d93dd",
-        "Sha1Sum": "1ed22cdb5b560e8c1581ab2c2b4593b4bcb620f3",
+        "Revision": "08b780f0ee9b1c60724ad8c8024bd84cc8a6d928",
+        "Sha1Sum": "e6b283b52892cb8304394a49b6528d1d309880cc",
         "SysrootDir": "debian_wheezy_mips-sysroot",
         "Tarball": "debian_wheezy_mips_sysroot.tgz"
     }
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index baa4387..b89733b1 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -13,9 +13,8 @@
   # faster, but linking is up to 5-20x slower).
   # Note: use target_os == "linux" rather than is_linux so that it does not
   # apply to host_toolchain when target_os="android".
-  allow_posix_link_time_opt =
-      target_os == "linux" && !is_chromeos && target_cpu == "x64" &&
-      is_chrome_branded && is_official_build
+  allow_posix_link_time_opt = target_os == "linux" && !is_chromeos &&
+                              target_cpu == "x64" && is_official_build
 
   # Set to true to use lld, the LLVM linker. This flag may be used on Windows
   # with the shipped LLVM toolchain, or on Linux with a self-built top-of-tree
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc
index 8041d8d..61a7ae3 100644
--- a/cc/resources/resource_pool.cc
+++ b/cc/resources/resource_pool.cc
@@ -410,7 +410,10 @@
   EvictResourcesNotUsedSince(current_time - resource_expiration_delay_);
 
   if (unused_resources_.empty() && busy_resources_.empty()) {
-    // Nothing is evictable.
+    // If nothing is evictable, we have deleted one (and possibly more)
+    // resources without any new activity. Flush to ensure these deletions are
+    // processed.
+    resource_provider_->FlushPendingDeletions();
     return;
   }
 
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 6547109d..6b057143 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -847,6 +847,11 @@
   resources_.erase(it);
 }
 
+void ResourceProvider::FlushPendingDeletions() const {
+  if (auto* gl = ContextGL())
+    gl->ShallowFlushCHROMIUM();
+}
+
 ResourceProvider::ResourceType ResourceProvider::GetResourceType(
     ResourceId id) {
   return GetResource(id)->type;
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index a9834cac..7f265b7 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -150,6 +150,10 @@
       bool read_lock_fences_enabled);
 
   void DeleteResource(ResourceId id);
+  // In the case of GPU resources, we may need to flush the GL context to ensure
+  // that texture deletions are seen in a timely fashion. This function should
+  // be called after texture deletions that may happen during an idle state.
+  void FlushPendingDeletions() const;
 
   // Update pixels from image, copying source_rect (in image) to dest_offset (in
   // the resource).
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 2758476..d7559a11 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1448,8 +1448,10 @@
     const ReturnedResourceArray& resources) {
   // TODO(piman): We may need to do some validation on this ack before
   // processing it.
-  if (resource_provider_)
-    resource_provider_->ReceiveReturnsFromParent(resources);
+  if (!resource_provider_)
+    return;
+
+  resource_provider_->ReceiveReturnsFromParent(resources);
 
   // In OOM, we now might be able to release more resources that were held
   // because they were exported.
@@ -1472,11 +1474,8 @@
   // If we're not visible, we likely released resources, so we want to
   // aggressively flush here to make sure those DeleteTextures make it to the
   // GPU process to free up the memory.
-  if (compositor_frame_sink_->context_provider() && !visible_) {
-    compositor_frame_sink_->context_provider()
-        ->ContextGL()
-        ->ShallowFlushCHROMIUM();
-  }
+  if (!visible_)
+    resource_provider_->FlushPendingDeletions();
 }
 
 void LayerTreeHostImpl::OnDraw(const gfx::Transform& transform,
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 6646b59..01d5f66a 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -4,6 +4,7 @@
 
 import("//base/android/linker/config.gni")
 import("//build/config/android/rules.gni")
+import("//build/config/locales.gni")
 import("//chrome/common/features.gni")
 import("//third_party/leakcanary/config.gni")
 import("channel.gni")
@@ -41,6 +42,9 @@
         rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir)
     native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)"
     native_lib_version_rule = "//build/util:chrome_version_json"
+    if (!defined(aapt_locale_whitelist)) {
+      aapt_locale_whitelist = locales - android_chrome_omitted_locales
+    }
 
     if (is_java_debug) {
       enable_multidex = true
@@ -99,12 +103,14 @@
     enable_relocation_packing = true
     extensions_to_not_compress = ".lpak,.pak,.bin,.dat"
 
+    # Webview supports all locales (has no omitted ones).
+    aapt_locale_whitelist = locales
+
     # Incremental install doesn't work for monochrome. See crbug.com/663492.
     never_incremental = true
 
     # Configrations to make android load shared library from APK.
     uncompress_shared_libraries = true
-    page_align_shared_libraries = true
 
     forward_variables_from(invoker, "*")
 
diff --git a/chrome/android/java/res/layout/fre_tosanduma.xml b/chrome/android/java/res/layout/fre_tosanduma.xml
index 1067829..ba81160 100644
--- a/chrome/android/java/res/layout/fre_tosanduma.xml
+++ b/chrome/android/java/res/layout/fre_tosanduma.xml
@@ -93,4 +93,13 @@
         android:textSize="@dimen/fre_button_text_size"
         chrome:buttonColor="@color/light_active_color"
         chrome:buttonRaised="false"/>
-</org.chromium.chrome.browser.firstrun.FirstRunView>
\ No newline at end of file
+
+    <!-- Same location as the button; marginButtom is adjusted for the different size. -->
+    <ProgressBar
+        android:id="@+id/progress_spinner"
+        style="@style/Widget.AppCompat.ProgressBar"
+        android:layout_marginBottom="22dp"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_width="24dp"
+        android:layout_height="24dp" />
+</org.chromium.chrome.browser.firstrun.FirstRunView>
diff --git a/chrome/android/java/res/layout/multiline_spinner_item.xml b/chrome/android/java/res/layout/multiline_spinner_item.xml
index 1fecc30..26801622 100644
--- a/chrome/android/java/res/layout/multiline_spinner_item.xml
+++ b/chrome/android/java/res/layout/multiline_spinner_item.xml
@@ -10,5 +10,4 @@
     android:singleLine="false"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingEnd="24dp"
     android:textAlignment="inherit" />
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml
index 9d87b740..963d4b4 100644
--- a/chrome/android/java/res/menu/main_menu.xml
+++ b/chrome/android/java/res/menu/main_menu.xml
@@ -71,8 +71,7 @@
         <item android:id="@+id/enter_vr_id"
             android:title="@string/enter_vr" />
         <item android:id="@+id/content_suggestions_standalone_ui"
-            android:title="@null"
-            android:visible="false" />
+            android:title="@null" />
     </group>
 
     <!-- Items shown only in the tab switcher -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
index 6f574fce..1c1b9cbf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -192,11 +192,10 @@
 
             // Only display the standalone content suggestions UI if the corresponding feature
             // is enabled.
-            if (ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SUGGESTIONS_STANDALONE_UI)) {
-                MenuItem item = menu.findItem(R.id.content_suggestions_standalone_ui);
-                item.setTitle("🔰🆕👌");
-                item.setVisible(true);
-            }
+            MenuItem item = menu.findItem(R.id.content_suggestions_standalone_ui);
+            item.setTitle("🔰🆕👌");
+            item.setVisible(
+                    ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SUGGESTIONS_STANDALONE_UI));
         }
 
         if (isOverviewMenu) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
index 3dbf0792..75fcea60 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -26,6 +26,7 @@
 import org.chromium.content_public.browser.DownloadState;
 
 import java.util.List;
+import java.util.Set;
 
 /** Bridges the user's download history and the UI used to display it. */
 public class DownloadHistoryAdapter extends DateDividedAdapter implements DownloadUiObserver {
@@ -248,12 +249,21 @@
         DownloadHistoryItemWrapper existingWrapper = list.get(index);
         boolean isUpdated = existingWrapper.replaceItem(item);
 
+        // Re-add the file mapping once it finishes downloading. This accounts for the backend
+        // creating DownloadItems with a null file path, then updating it after the download starts.
+        // Doing it once after completion instead of at every update is a compromise that prevents
+        // us from rapidly and repeatedly updating the map with the same info.
+        if (item.getDownloadInfo().state() == DownloadState.COMPLETE) {
+            mFilePathsToItemsMap.addItem(existingWrapper);
+        }
+
         if (item.getDownloadInfo().state() == DownloadState.CANCELLED) {
             // The old one is being removed.
             filter(mFilter);
         } else if (existingWrapper.isVisibleToUser(mFilter)) {
             if (existingWrapper.getPosition() == TimedItem.INVALID_POSITION) {
                 filter(mFilter);
+                for (TestObserver observer : mObservers) observer.onDownloadItemUpdated(item);
             } else if (isUpdated) {
                 notifyItemChanged(existingWrapper.getPosition());
                 for (TestObserver observer : mObservers) observer.onDownloadItemUpdated(item);
@@ -307,7 +317,7 @@
      * @param filePath The file path used to retrieve items.
      * @return DownloadHistoryItemWrappers associated with filePath.
      */
-    List<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) {
+    Set<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) {
         return mFilePathsToItemsMap.getItemsForFilePath(filePath);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
index afb387ec..0821b57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -428,7 +428,7 @@
 
         for (DownloadHistoryItemWrapper item : selectedItems) {
             if (!filePathsToRemove.contains(item.getFilePath())) {
-                List<DownloadHistoryItemWrapper> itemsForFilePath =
+                Set<DownloadHistoryItemWrapper> itemsForFilePath =
                         mHistoryAdapter.getItemsForFilePath(item.getFilePath());
                 if (itemsForFilePath != null) {
                     itemsToRemove.addAll(itemsForFilePath);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java
index 31f755ebe..9c851ab3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilePathsToDownloadItemsMap.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.browser.download.ui;
 
-import java.util.ArrayList;
+import android.text.TextUtils;
+
 import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Multiple download items may reference the same location on disk. This class maintains a mapping
@@ -15,16 +17,17 @@
  * TODO(twellington): remove this class after the backend handles duplicate removal.
  */
 class FilePathsToDownloadItemsMap {
-    private final Map<String, ArrayList<DownloadHistoryItemWrapper>> mMap = new HashMap<>();
+    private final Map<String, Set<DownloadHistoryItemWrapper>> mMap = new HashMap<>();
 
     /**
-     * Adds a DownloadHistoryItemWrapper to the map. This method does not check whether the item
-     * already exists in the map.
+     * Adds a DownloadHistoryItemWrapper to the map if it has a valid path.
      * @param wrapper The item to add to the map.
      */
     void addItem(DownloadHistoryItemWrapper wrapper) {
+        if (TextUtils.isEmpty(wrapper.getFilePath())) return;
+
         if (!mMap.containsKey(wrapper.getFilePath())) {
-            mMap.put(wrapper.getFilePath(), new ArrayList<DownloadHistoryItemWrapper>());
+            mMap.put(wrapper.getFilePath(), new HashSet<DownloadHistoryItemWrapper>());
         }
         mMap.get(wrapper.getFilePath()).add(wrapper);
     }
@@ -35,21 +38,15 @@
      * @param wrapper The item to remove from the map.
      */
     void removeItem(DownloadHistoryItemWrapper wrapper) {
-        ArrayList<DownloadHistoryItemWrapper> matchingItems = mMap.get(wrapper.getFilePath());
-        if (matchingItems == null) return;
+        Set<DownloadHistoryItemWrapper> matchingItems = mMap.get(wrapper.getFilePath());
+        if (matchingItems == null || !matchingItems.contains(wrapper)) return;
 
-        for (int i = 0; i < matchingItems.size(); i++) {
-            if (!matchingItems.get(i).equals(wrapper)) continue;
-
+        if (matchingItems.size() == 1) {
             // If this is the only DownloadHistoryItemWrapper that references the file path,
             // remove the file path from the map.
-            if (matchingItems.size() == 1) {
-                mMap.remove(wrapper.getFilePath());
-            } else {
-                matchingItems.remove(i);
-            }
-
-            return;
+            mMap.remove(wrapper.getFilePath());
+        } else {
+            matchingItems.remove(wrapper);
         }
     }
 
@@ -58,7 +55,7 @@
      * @param filePath The file path used to retrieve items.
      * @return DownloadHistoryItemWrappers associated with filePath.
      */
-    List<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) {
+    Set<DownloadHistoryItemWrapper> getItemsForFilePath(String filePath) {
         return mMap.get(filePath);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 96908cc..7a1c764 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -10,21 +10,18 @@
 import android.app.PendingIntent.CanceledException;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
 import android.text.TextUtils;
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
-import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
-import org.chromium.chrome.browser.init.EmptyBrowserParts;
+import org.chromium.chrome.browser.init.AsyncInitializationActivity;
 import org.chromium.chrome.browser.metrics.UmaUtils;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoUtils;
@@ -35,7 +32,9 @@
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Constructor;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Callable;
 
 /**
@@ -46,7 +45,7 @@
  *   [Sign-in page]
  * The activity might be run more than once, e.g. 1) for ToS and sign-in, and 2) for intro.
  */
-public class FirstRunActivity extends AppCompatActivity implements FirstRunPageDelegate {
+public class FirstRunActivity extends AsyncInitializationActivity implements FirstRunPageDelegate {
     protected static final String TAG = "FirstRunActivity";
 
     // Incoming parameters:
@@ -103,6 +102,8 @@
 
     private boolean mPostNativePageSequenceCreated;
     private boolean mNativeSideIsInitialized;
+    private Set<FirstRunPage> mPagesToNotifyOfNativeInit;
+    private boolean mDeferredCompleteFRE;
 
     private ProfileDataCache mProfileDataCache;
     private FirstRunViewPager mPager;
@@ -131,12 +132,10 @@
         if (mShowWelcomePage) {
             mPages.add(pageOf(ToSAndUMAFirstRunFragment.class));
             mFreProgressStates.add(FRE_PROGRESS_WELCOME_SHOWN);
-        } else {
-            // Otherwise, if we're skipping past the welcome page, then init the
-            // native process and determine if data reduction proxy and signin
-            // pages should be shown - which both depend on native code.
-            createPostNativePageSequence();
         }
+
+        // Other pages will be created by createPostNativePageSequence() after
+        // native has been initialized.
     }
 
     private void createPostNativePageSequence() {
@@ -144,7 +143,6 @@
         // populates |mPages| which needs to be done even even if onNativeInitialized() was
         // performed in a previous session.
         if (mPostNativePageSequenceCreated) return;
-        ensureBrowserProcessInitialized();
         mFirstRunFlowSequencer.onNativeInitialized(mFreProperties);
 
         boolean notifyAdapter = false;
@@ -168,14 +166,11 @@
         mPostNativePageSequenceCreated = true;
     }
 
-    // Activity:
+    // AsyncInitializationActivity:
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        ChromeBrowserInitializer.getInstance(this).handlePreNativeStartup(new EmptyBrowserParts());
-
+    public void setContentView() {
+        Bundle savedInstanceState = getSavedInstanceState();
         if (savedInstanceState != null) {
             mFreProperties = savedInstanceState;
         } else if (getIntent() != null) {
@@ -225,8 +220,6 @@
                 mPager.setAdapter(mPagerAdapter);
 
                 recordFreProgressHistogram(mFreProgressStates.get(0));
-
-                skipPagesIfNecessary();
             }
         };
         mFirstRunFlowSequencer.start();
@@ -235,13 +228,50 @@
     }
 
     @Override
+    public void finishNativeInitialization() {
+        super.finishNativeInitialization();
+        mNativeSideIsInitialized = true;
+        if (mDeferredCompleteFRE) {
+            completeFirstRunExperience();
+            mDeferredCompleteFRE = false;
+        } else {
+            createPostNativePageSequence();
+            if (mPagesToNotifyOfNativeInit != null) {
+                for (FirstRunPage page : mPagesToNotifyOfNativeInit) {
+                    page.onNativeInitialized();
+                }
+            }
+            mPagesToNotifyOfNativeInit = null;
+            skipPagesIfNecessary();
+        }
+    }
+
+    // Activity:
+
+    @Override
+    public void onAttachFragment(Fragment fragment) {
+        if (!(fragment instanceof FirstRunPage)) return;
+
+        FirstRunPage page = (FirstRunPage) fragment;
+        if (mNativeSideIsInitialized) {
+            page.onNativeInitialized();
+            return;
+        }
+
+        if (mPagesToNotifyOfNativeInit == null) {
+            mPagesToNotifyOfNativeInit = new HashSet<FirstRunPage>();
+        }
+        mPagesToNotifyOfNativeInit.add(page);
+    }
+
+    @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putAll(mFreProperties);
     }
 
     @Override
-    protected void onPause() {
+    public void onPause() {
         super.onPause();
         flushPersistentData();
     }
@@ -253,7 +283,7 @@
     }
 
     @Override
-    protected void onStart() {
+    public void onStart() {
         super.onStart();
         // Since the FRE may be shown before any tab is shown, mark that this is the point at
         // which Chrome went to foreground. This is needed as otherwise an assert will be hit
@@ -325,7 +355,10 @@
 
     @Override
     public void completeFirstRunExperience() {
-        ensureBrowserProcessInitialized();
+        if (!mNativeSideIsInitialized) {
+            mDeferredCompleteFRE = true;
+            return;
+        }
         if (!TextUtils.isEmpty(mResultSignInAccountName)) {
             boolean defaultAccountName =
                     sGlue.isDefaultAccountName(getApplicationContext(), mResultSignInAccountName);
@@ -396,13 +429,6 @@
 
     @Override
     public void acceptTermsOfService(boolean allowCrashUpload) {
-        // At this point, we're advancing past the first page, which has no native
-        // dependencies to further pages in the sequence, if any. These require
-        // native to be initialized and will be added by the call below if needed.
-        // Additionally, the calls later in this function also require native
-        // to be initialized.
-        createPostNativePageSequence();
-
         // If default is true then it corresponds to opt-out and false corresponds to opt-in.
         UmaUtils.recordMetricsReportingDefaultOptIn(!DEFAULT_METRICS_AND_CRASH_REPORTING);
         sGlue.acceptTermsOfService(allowCrashUpload);
@@ -504,28 +530,11 @@
         while (currentPageIndex < mPagerAdapter.getCount()) {
             FirstRunPage currentPage = (FirstRunPage) mPagerAdapter.getItem(currentPageIndex);
             if (!currentPage.shouldSkipPageOnCreate(getApplicationContext())) return;
-            // If we're advancing to the next page, ensure to init the post native page
-            // sequence - as every page except the first requires that to be initialized.
-            // This is a no-op if it has already been done.
-            createPostNativePageSequence();
             if (!jumpToPage(currentPageIndex + 1)) return;
             currentPageIndex = mPager.getCurrentItem();
         }
     }
 
-    private void ensureBrowserProcessInitialized() {
-        if (mNativeSideIsInitialized) return;
-        try {
-            ChromeBrowserInitializer.getInstance(this).handlePostNativeStartup(
-                    false, new EmptyBrowserParts());
-            mNativeSideIsInitialized = true;
-        } catch (ProcessInitException e) {
-            Log.e(TAG, "Unable to load native library.", e);
-            abortFirstRunExperience();
-            return;
-        }
-    }
-
     private void recordFreProgressHistogram(int state) {
         if (mFreProperties.getBoolean(FirstRunActivity.EXTRA_COMING_FROM_CHROME_ICON)) {
             sMobileFreProgressMainIntentHistogram.record(state);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
index 7221c6ff..032b286c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPage.java
@@ -49,6 +49,13 @@
     }
 
     /**
+     * @return Whether the page should be re-created when notifyDataSetChanged() fires.
+     */
+    public boolean shouldRecreatePageOnDataChange() {
+        return true;
+    }
+
+    /**
      * @return Passed arguments if any, or saved instance state if any, or an empty bundle.
      */
     protected Bundle getProperties() {
@@ -68,4 +75,9 @@
     protected void advanceToNextPage() {
         getPageDelegate().advanceToNextPage();
     }
-}
\ No newline at end of file
+
+    /**
+     * Notifies this page that native has been initialized.
+     */
+    protected void onNativeInitialized() {}
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
index f42d039..d576c91 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
@@ -64,6 +64,7 @@
 
     /**
      * Notifies all interested parties that the user has accepted Chrome Terms of Service.
+     * Must be called only after native has been initialized.
      * @param allowCrashUpload True if the user allows to upload crash dumps and collect stats.
      */
     void acceptTermsOfService(boolean allowCrashUpload);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
index 79cb9875..5de1eba4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPagerAdapter.java
@@ -68,8 +68,11 @@
 
     @Override
     public int getItemPosition(Object object) {
-        // We do not keep track of constructed objects, but we want the pages to be recreated
-        // on notifyDataSetChanged. Hence, tell the view that it needs to refresh the objects.
+        // Each page can specify whether it should be re-created or not on a notifyDataSetChanged.
+        if (object instanceof FirstRunPage) {
+            FirstRunPage page = (FirstRunPage) object;
+            return page.shouldRecreatePageOnDataChange() ? POSITION_NONE : POSITION_UNCHANGED;
+        }
         return POSITION_NONE;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
index 889515c..1292e346 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
@@ -6,7 +6,6 @@
 
 import android.app.Activity;
 import android.content.Intent;
-import android.os.Bundle;
 import android.text.method.LinkMovementMethod;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -27,9 +26,8 @@
 */
 public class LightweightFirstRunActivity extends FirstRunActivity {
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
+    public void setContentView() {
+        super.setContentView();
         if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)) {
             completeFirstRunExperience();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
index 3c4c4f53..858c51b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
@@ -31,6 +31,10 @@
     private Button mAcceptButton;
     private CheckBox mSendReportCheckBox;
     private TextView mTosAndPrivacy;
+    private View mTitle;
+    private View mProgressSpinner;
+    private boolean mNativeInitialized;
+    private boolean mTriggerAcceptAfterNativeInit;
 
     @Override
     public View onCreateView(
@@ -42,6 +46,9 @@
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
+        mTitle = view.findViewById(R.id.title);
+        mProgressSpinner = view.findViewById(R.id.progress_spinner);
+        mProgressSpinner.setVisibility(View.GONE);
         mAcceptButton = (Button) view.findViewById(R.id.terms_accept);
         mSendReportCheckBox = (CheckBox) view.findViewById(R.id.send_report_checkbox);
         mTosAndPrivacy = (TextView) view.findViewById(R.id.tos_and_privacy);
@@ -49,7 +56,7 @@
         mAcceptButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                getPageDelegate().acceptTermsOfService(mSendReportCheckBox.isChecked());
+                acceptTermsOfService();
             }
         });
 
@@ -87,12 +94,22 @@
         mTosAndPrivacy.setText(SpanApplier.applySpans(getString(R.string.fre_tos_and_privacy),
                 new SpanInfo("<LINK1>", "</LINK1>", clickableTermsSpan),
                 new SpanInfo("<LINK2>", "</LINK2>", clickablePrivacySpan)));
+
+        // If this page should be skipped, hide all the UI elements except for the
+        // Chrome logo and the spinner.
+        if (FirstRunStatus.shouldSkipWelcomePage()) {
+            setSpinnerVisible(true);
+        }
     }
 
     @Override
     public void setUserVisibleHint(boolean isVisibleToUser) {
         super.setUserVisibleHint(isVisibleToUser);
-        if (isVisibleToUser && mSendReportCheckBox != null) {
+
+        if (!isVisibleToUser) {
+            // Restore original enabled & visibility states, in case the user returns to the page.
+            setSpinnerVisible(false);
+        } else if (mSendReportCheckBox != null) {
             // On certain versions of Android, the checkbox will appear unchecked upon revisiting
             // the page.  Force it to the end state of the drawable animation as a work around.
             // crbug.com/666258
@@ -104,4 +121,42 @@
     public boolean shouldSkipPageOnCreate(Context appContext) {
         return FirstRunStatus.shouldSkipWelcomePage();
     }
+
+    @Override
+    public boolean shouldRecreatePageOnDataChange() {
+        // Specify that this page shouldn't be re-created on notifyDataSetChanged(), so
+        // that state like mTriggerAcceptAfterNativeInit can be preserved on the instance
+        // when native is initialized.
+        return false;
+    }
+
+    @Override
+    protected void onNativeInitialized() {
+        assert !mNativeInitialized;
+
+        mNativeInitialized = true;
+        if (mTriggerAcceptAfterNativeInit) acceptTermsOfService();
+    }
+
+    private void acceptTermsOfService() {
+        if (!mNativeInitialized) {
+            mTriggerAcceptAfterNativeInit = true;
+            setSpinnerVisible(true);
+            return;
+        }
+
+        mTriggerAcceptAfterNativeInit = false;
+        getPageDelegate().acceptTermsOfService(mSendReportCheckBox.isChecked());
+    }
+
+    private void setSpinnerVisible(boolean spinnerVisible) {
+        // When the progress spinner is visibile, we hide the other UI elements so that
+        // the user can't interact with them.
+        int otherElementsVisible = spinnerVisible ? View.INVISIBLE : View.VISIBLE;
+        mTitle.setVisibility(otherElementsVisible);
+        mAcceptButton.setVisibility(otherElementsVisible);
+        mTosAndPrivacy.setVisibility(otherElementsVisible);
+        mSendReportCheckBox.setVisibility(otherElementsVisible);
+        mProgressSpinner.setVisibility(spinnerVisible ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
index 0edbf902..e6af620a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
@@ -154,11 +154,6 @@
     public void onFinishDownloadImage(int id, int httpStatusCode, String imageUrl,
             List<Bitmap> bitmaps, List<Rect> originalImageSizes) {
         if (id != mRequestId) return;
-        if (httpStatusCode < 200 || httpStatusCode >= 300) {
-            mCallback.onImageDownloaded(null);
-            clearRequests();
-            return;
-        }
 
         Iterator<Bitmap> iterBitmap = bitmaps.iterator();
         Iterator<Rect> iterSize = originalImageSizes.iterator();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java
index 084e197..be4797f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/BillingAddressAdapter.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.view.View;
 import android.view.ViewGroup;
@@ -74,6 +75,19 @@
     }
 
     @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        View view = super.getView(position, convertView, parent);
+
+        // Add the left and right padding of the parent's background to the selected item view to
+        // avoid overlaping the downward triangle.
+        Rect rect = new Rect();
+        parent.getBackground().getPadding(rect);
+        view.setPadding(view.getPaddingLeft() + rect.left, view.getPaddingTop(),
+                view.getPaddingRight() + rect.right, view.getPaddingBottom());
+        return view;
+    }
+
+    @Override
     public View getDropDownView(int position, View convertView, ViewGroup parent) {
         TextView textView = convertView == null
                 ? null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
index cd62bc1..792a0ca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninView.java
@@ -226,13 +226,31 @@
     }
 
     /**
-     * Refresh the list of available system accounts.
+     * Refresh the list of available system accounts asynchronously. This is a convenience method
+     * that will ignore whether the accounts updating was actually successful.
      */
     private void updateAccounts() {
-        if (mSignedIn || mProfileData == null) return;
+        updateAccounts(new Callback<Boolean>() {
+            @Override
+            public void onResult(Boolean result) {}
+        });
+    }
+
+    /**
+     * Refresh the list of available system accounts asynchronously.
+     *
+     * @param callback Called once the accounts have been refreshed. Boolean indicates whether the
+     *                 accounts haven been successfully updated.
+     */
+    private void updateAccounts(final Callback<Boolean> callback) {
+        if (mSignedIn || mProfileData == null) {
+            callback.onResult(false);
+            return;
+        }
 
         if (!checkGooglePlayServicesAvailable()) {
             setUpSigninButton(false);
+            callback.onResult(false);
             return;
         }
 
@@ -256,6 +274,13 @@
                     updatingGmsDialog.dismiss();
                 }
                 mIsGooglePlayServicesOutOfDate = false;
+
+                if (mSignedIn) {
+                    // If sign-in completed in the mean time, return in order to avoid showing the
+                    // wrong state in the UI.
+                    return;
+                }
+
                 mAccountNames = result;
 
                 int accountToSelect = 0;
@@ -263,6 +288,7 @@
                     accountToSelect = mAccountNames.indexOf(mForcedAccountName);
                     if (accountToSelect < 0) {
                         mListener.onFailedToSetForcedAccount(mForcedAccountName);
+                        callback.onResult(false);
                         return;
                     }
                 } else {
@@ -275,6 +301,7 @@
                 mSigninChooseView.updateAccounts(mAccountNames, accountToSelect, mProfileData);
                 if (mAccountNames.isEmpty()) {
                     setUpSigninButton(false);
+                    callback.onResult(true);
                     return;
                 }
                 setUpSigninButton(true);
@@ -283,7 +310,10 @@
 
                 // Determine how the accounts have changed. Each list should only have unique
                 // elements.
-                if (oldAccountNames == null || oldAccountNames.isEmpty()) return;
+                if (oldAccountNames == null || oldAccountNames.isEmpty()) {
+                    callback.onResult(true);
+                    return;
+                }
 
                 if (!mAccountNames.get(accountToSelect).equals(
                         oldAccountNames.get(oldSelectedAccount))) {
@@ -299,7 +329,7 @@
                         showConfirmSigninPageAccountTrackerServiceCheck();
                     }
                 }
-
+                callback.onResult(true);
             }
         });
     }
@@ -568,10 +598,15 @@
      */
     public void switchToForcedAccountMode(String forcedAccountName) {
         mForcedAccountName = forcedAccountName;
-        updateAccounts();
-        assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName);
-        switchToSignedMode();
-        assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName);
+        updateAccounts(new Callback<Boolean>() {
+            @Override
+            public void onResult(Boolean result) {
+                if (!result) return;
+                assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName);
+                switchToSignedMode();
+                assert TextUtils.equals(getSelectedAccountName(), mForcedAccountName);
+            }
+        });
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index ee3b521b..5c20d1f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -21,6 +21,7 @@
 import android.widget.TextView;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ShortcutHelper;
@@ -418,8 +419,9 @@
         waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE);
     }
 
-    @MediumTest
-    @Feature({"AppBanners"})
+    // @MediumTest
+    // @Feature({"AppBanners"})
+    @DisabledTest
     public void testBannerAppearsThenDoesNotAppearAgainForCustomTime() throws Exception {
         AppBannerManager.setDaysAfterDismissAndIgnoreForTesting(7, 7);
         triggerWebAppBanner(mWebAppUrl, WEB_APP_TITLE, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
index 2be9fd6..0a49cc4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
@@ -19,6 +19,8 @@
 import org.chromium.content.browser.test.NativeLibraryTestBase;
 import org.chromium.content_public.browser.DownloadState;
 
+import java.util.Set;
+
 /**
  * Tests a DownloadHistoryAdapter that is isolated from the real bridges.
  */
@@ -194,7 +196,7 @@
         // Add a third item with the same date as the second item.
         assertEquals(2, mObserver.onDownloadItemCreatedCallback.getCallCount());
         DownloadItem item2 = StubbedProvider.createDownloadItem(
-                2, "19840117 18:00", false, DownloadState.IN_PROGRESS);
+                2, "19840117 18:00", false, DownloadState.IN_PROGRESS, 0);
         mAdapter.onDownloadItemCreated(item2);
         mObserver.onDownloadItemCreatedCallback.waitForCallback(2);
         assertEquals(mObserver.createdItem, item2);
@@ -205,7 +207,7 @@
         // but it should now be visible.
         int callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount();
         DownloadItem item3 = StubbedProvider.createDownloadItem(
-                2, "19840117 18:00", false, DownloadState.COMPLETE);
+                2, "19840117 18:00", false, DownloadState.COMPLETE, 100);
         mAdapter.onDownloadItemUpdated(item3);
         mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount);
         assertEquals(mObserver.updatedItem, item3);
@@ -233,7 +235,7 @@
         // Initialize the DownloadHistoryAdapter with three items in two date buckets.
         DownloadItem regularItem = StubbedProvider.createDownloadItem(0, "19840116 18:00");
         DownloadItem offTheRecordItem = StubbedProvider.createDownloadItem(
-                1, "19840116 12:00", true, DownloadState.COMPLETE);
+                1, "19840116 12:00", true, DownloadState.COMPLETE, 100);
         OfflinePageDownloadItem offlineItem =
                 StubbedProvider.createOfflineItem(2, "19840117 12:01");
         mDownloadDelegate.regularItems.add(regularItem);
@@ -334,6 +336,52 @@
         assertEquals(0, mAdapter.getItemCount());
     }
 
+    @SmallTest
+    public void testInProgress_FilePathMapAccurate() throws Exception {
+        Set<DownloadHistoryItemWrapper> toDelete;
+
+        initializeAdapter(false);
+        assertEquals(0, mAdapter.getItemCount());
+        assertEquals(0, mAdapter.getTotalDownloadSize());
+
+        // Simulate the creation of a new item by providing a DownloadItem without a path.
+        DownloadItem itemCreated = StubbedProvider.createDownloadItem(
+                9, "19840118 12:01", false, DownloadState.IN_PROGRESS, 0);
+        mAdapter.onDownloadItemCreated(itemCreated);
+        mObserver.onDownloadItemCreatedCallback.waitForCallback(0);
+        assertEquals(mObserver.createdItem, itemCreated);
+
+        checkAdapterContents();
+        toDelete = mAdapter.getItemsForFilePath(itemCreated.getDownloadInfo().getFilePath());
+        assertNull(toDelete);
+
+        // Update the Adapter with new information about the item.
+        int callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount();
+        DownloadItem itemUpdated = StubbedProvider.createDownloadItem(
+                10, "19840118 12:01", false, DownloadState.IN_PROGRESS, 50);
+        mAdapter.onDownloadItemUpdated(itemUpdated);
+        mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount);
+        assertEquals(mObserver.updatedItem, itemUpdated);
+
+        checkAdapterContents(null, itemUpdated);
+        toDelete = mAdapter.getItemsForFilePath(itemUpdated.getDownloadInfo().getFilePath());
+        assertNull(toDelete);
+
+        // Tell the Adapter that the item has finished downloading.
+        callCount = mObserver.onDownloadItemUpdatedCallback.getCallCount();
+        DownloadItem itemCompleted = StubbedProvider.createDownloadItem(
+                10, "19840118 12:01", false, DownloadState.COMPLETE, 100);
+        mAdapter.onDownloadItemUpdated(itemCompleted);
+        mObserver.onDownloadItemUpdatedCallback.waitForCallback(callCount);
+        assertEquals(mObserver.updatedItem, itemCompleted);
+        checkAdapterContents(null, itemCompleted);
+
+        // Confirm that the file now shows up when trying to delete it.
+        toDelete = mAdapter.getItemsForFilePath(itemCompleted.getDownloadInfo().getFilePath());
+        assertEquals(1, toDelete.size());
+        assertEquals(itemCompleted.getId(), toDelete.iterator().next().getId());
+    }
+
     /** Checks that the adapter has the correct items in the right places. */
     private void checkAdapterContents(Object... expectedItems) {
         assertEquals(expectedItems.length, mAdapter.getItemCount());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java
index 44babce9..3846e681 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java
@@ -199,118 +199,114 @@
     @Override
     public void destroy() {}
 
-    /** See {@link #createDownloadItem(int, String, boolean)}. */
+    /** See {@link #createDownloadItem(int, String, boolean, int, int)}. */
     public static DownloadItem createDownloadItem(int which, String date) throws Exception {
-        return createDownloadItem(which, date, false, DownloadState.COMPLETE);
+        return createDownloadItem(which, date, false, DownloadState.COMPLETE, 100);
     }
 
     /** Creates a new DownloadItem with pre-defined values. */
     public static DownloadItem createDownloadItem(
-            int which, String date, boolean isIncognito, int state) throws Exception {
-        DownloadItem item = null;
+            int which, String date, boolean isIncognito, int state, int percent) throws Exception {
+        DownloadInfo.Builder builder = null;
         if (which == 0) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://google.com")
                     .setContentLength(1)
                     .setFileName("first_file.jpg")
                     .setFilePath("/storage/fake_path/Downloads/first_file.jpg")
                     .setDownloadGuid("first_guid")
-                    .setMimeType("image/jpeg")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("image/jpeg");
         } else if (which == 1) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://one.com")
                     .setContentLength(10)
                     .setFileName("second_file.gif")
                     .setFilePath("/storage/fake_path/Downloads/second_file.gif")
                     .setDownloadGuid("second_guid")
-                    .setMimeType("image/gif")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("image/gif");
         } else if (which == 2) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://is.com")
                     .setContentLength(100)
                     .setFileName("third_file")
                     .setFilePath("/storage/fake_path/Downloads/third_file")
                     .setDownloadGuid("third_guid")
-                    .setMimeType("text/plain")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("text/plain");
         } else if (which == 3) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://the.com")
                     .setContentLength(5)
                     .setFileName("four.webm")
                     .setFilePath("/storage/fake_path/Downloads/four.webm")
                     .setDownloadGuid("fourth_guid")
-                    .setMimeType("video/webm")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("video/webm");
         } else if (which == 4) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://loneliest.com")
                     .setContentLength(50)
                     .setFileName("five.mp3")
                     .setFilePath("/storage/fake_path/Downloads/five.mp3")
                     .setDownloadGuid("fifth_guid")
-                    .setMimeType("audio/mp3")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("audio/mp3");
         } else if (which == 5) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://number.com")
                     .setContentLength(500)
                     .setFileName("six.mp3")
                     .setFilePath("/storage/fake_path/Downloads/six.mp3")
                     .setDownloadGuid("sixth_guid")
-                    .setMimeType("audio/mp3")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("audio/mp3");
         } else if (which == 6) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://sigh.com")
                     .setContentLength(ONE_GIGABYTE)
                     .setFileName("huge_image.png")
                     .setFilePath("/storage/fake_path/Downloads/huge_image.png")
                     .setDownloadGuid("seventh_guid")
-                    .setMimeType("image/png")
-                    .setState(state)
-                    .build());
+                    .setMimeType("image/png");
         } else if (which == 7) {
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://sleepy.com")
                     .setContentLength(ONE_GIGABYTE / 2)
                     .setFileName("sleep.pdf")
                     .setFilePath("/storage/fake_path/Downloads/sleep.pdf")
                     .setDownloadGuid("eighth_guid")
-                    .setMimeType("application/pdf")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("application/pdf");
         } else if (which == 8) {
-            // This is a duplicate of item 7 above.
-            item = new DownloadItem(false, new DownloadInfo.Builder()
+            // This is a duplicate of item 7 above with a different GUID.
+            builder = new DownloadInfo.Builder()
                     .setUrl("https://sleepy.com")
                     .setContentLength(ONE_GIGABYTE / 2)
                     .setFileName("sleep.pdf")
                     .setFilePath("/storage/fake_path/Downloads/sleep.pdf")
                     .setDownloadGuid("ninth_guid")
-                    .setMimeType("application/pdf")
-                    .setState(state)
-                    .setIsOffTheRecord(isIncognito)
-                    .build());
+                    .setMimeType("application/pdf");
+        } else if (which == 9) {
+            builder = new DownloadInfo.Builder()
+                    .setUrl("https://totallynew.com")
+                    .setContentLength(ONE_GIGABYTE / 10)
+                    .setFileName("forserious.jpg")
+                    .setFilePath(null)
+                    .setDownloadGuid("tenth_guid")
+                    .setMimeType("image/jpg");
+        } else if (which == 10) {
+            // Duplicate version of #9, but the file path has been set.
+            builder = new DownloadInfo.Builder()
+                    .setUrl("https://totallynew.com")
+                    .setContentLength(ONE_GIGABYTE / 10)
+                    .setFileName("forserious.jpg")
+                    .setFilePath("/storage/fake_path/Downloads/forserious.jpg")
+                    .setDownloadGuid("tenth_guid")
+                    .setMimeType("image/jpg");
         } else {
             return null;
         }
 
+        builder.setIsOffTheRecord(isIncognito);
+        builder.setPercentCompleted(percent);
+        builder.setState(state);
+
+        DownloadItem item = new DownloadItem(false, builder.build());
         item.setStartTime(dateToEpoch(date));
         return item;
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
index c82cca31..3496e02 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
@@ -177,7 +177,7 @@
     public void testDownloadImageFails() {
         mMediaImageManager.downloadImage(mImages, mCallback);
         mMediaImageManager.onFinishDownloadImage(
-                REQUEST_ID_1, 404, IMAGE_URL, mBitmaps, mOriginalImageSizes);
+                REQUEST_ID_1, 404, IMAGE_URL, new ArrayList<Bitmap>(), new ArrayList<Rect>());
 
         verify(mCallback).onImageDownloaded(isNull(Bitmap.class));
         verify(mCallback, times(0)).onImageDownloaded(isNotNull(Bitmap.class));
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc
index 3ca96fa1..5d5d93d0 100644
--- a/chrome/app/mash/mash_runner.cc
+++ b/chrome/app/mash/mash_runner.cc
@@ -19,6 +19,7 @@
 #include "base/process/launch.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
+#include "base/sys_info.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/trace_event/trace_event.h"
@@ -41,7 +42,6 @@
 #include "services/service_manager/runner/common/client_util.h"
 #include "services/service_manager/runner/common/switches.h"
 #include "services/service_manager/runner/init.h"
-#include "services/service_manager/standalone/context.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
 #include "ui/base/ui_base_switches.h"
@@ -134,6 +134,9 @@
 MashRunner::~MashRunner() {}
 
 int MashRunner::Run() {
+  base::TaskScheduler::CreateAndSetSimpleTaskScheduler(
+      base::SysInfo::NumberOfProcessors());
+
   if (IsChild())
     return RunChild();
   RunMain();
@@ -141,8 +144,6 @@
 }
 
 void MashRunner::RunMain() {
-  base::TaskScheduler::CreateAndSetSimpleTaskScheduler(
-      service_manager::kThreadPoolMaxThreads);
   base::SequencedWorkerPool::EnableWithRedirectionToTaskSchedulerForProcess();
 
   // TODO(sky): refactor BackgroundServiceManager so can supply own context, we
@@ -193,11 +194,6 @@
 }
 
 int MashRunner::RunChild() {
-  // TODO(fdoray): Add TaskScheduler initialization code in
-  // service_manager::ServiceRunner. TaskScheduler can't be initialized here
-  // because it wouldn't be visible to the service's dynamic library.
-  // https://crbug.com/664996
-
   service_manager::WaitForDebuggerIfNecessary();
 
   base::i18n::InitializeICU();
diff --git a/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc b/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc
index 2ff93c1..97766c4 100644
--- a/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc
+++ b/chrome/browser/android/offline_pages/request_coordinator_factory_unittest.cc
@@ -27,7 +27,8 @@
   content::BrowserThread::GetBlockingPool()->FlushForTesting();
 }
 
-TEST_F(RequestCoordinatorFactoryTest, BuildRequestCoordinator) {
+// Flaky on android_n5x_swarming_rel. https://crbug.com/679844
+TEST_F(RequestCoordinatorFactoryTest, DISABLED_BuildRequestCoordinator) {
   RequestCoordinatorFactory* factory = RequestCoordinatorFactory::GetInstance();
   EXPECT_NE(nullptr, factory);
   RequestCoordinator* coordinator1 =
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index fbc1b1d..2698c53 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -95,12 +95,6 @@
 #include "content/public/test/ppapi_test_utils.h"
 #endif
 
-#if defined(OS_CHROMEOS)
-#include "ash/common/accessibility_types.h"
-#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/accessibility/speech_monitor.h"
-#endif
-
 using extensions::ContextMenuMatcher;
 using extensions::ExtensionsAPIClient;
 using extensions::MenuItem;
@@ -2222,30 +2216,6 @@
           << message_;
 }
 
-#if defined(OS_CHROMEOS)
-// Flaky, see http://crbug.com/611736.
-IN_PROC_BROWSER_TEST_P(WebViewTest, DISABLED_ChromeVoxInjection) {
-  EXPECT_FALSE(
-      chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-
-  chromeos::SpeechMonitor monitor;
-  chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(
-      true, ash::A11Y_NOTIFICATION_NONE);
-  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
-
-  ASSERT_TRUE(StartEmbeddedTestServer());
-  content::WebContents* guest_web_contents = LoadGuest(
-      "/extensions/platform_apps/web_view/chromevox_injection/guest.html",
-      "web_view/chromevox_injection");
-  ASSERT_TRUE(guest_web_contents);
-
-  for (;;) {
-    if (monitor.GetNextUtterance() == "chrome vox test title")
-      break;
-  }
-}
-#endif
-
 // Flaky on Windows. http://crbug.com/303966
 #if defined(OS_WIN)
 #define MAYBE_TearDownTest DISABLED_TearDownTest
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index 03dc966..5eb97f5 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -29,10 +29,16 @@
 #include "media/media_features.h"
 
 #if defined(OS_WIN)
+#include "base/win/pe_image.h"
 #include "chrome/install_static/install_util.h"
 #include "components/browser_watcher/stability_data_names.h"
 #endif
 
+#if defined(OS_WIN)
+// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+#endif
+
 namespace chrome {
 
 namespace {
@@ -109,11 +115,11 @@
       stability_file, kMemorySize, kAllocatorId,
       browser_watcher::kStabilityDebuggingFeature.name, kStackDepth);
 
-  // Record basic information: product, version, channel, special build and
-  // platform.
+  // Record basic information.
   base::debug::GlobalActivityTracker* global_tracker =
       base::debug::GlobalActivityTracker::Get();
   if (global_tracker) {
+    // Record product, version, channel, special build and platform.
     wchar_t exe_file[MAX_PATH] = {};
     CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file)));
 
@@ -136,6 +142,18 @@
 #elif defined(ARCH_CPU_X86_64)
     global_data.SetString(browser_watcher::kStabilityPlatform, "Win64");
 #endif
+
+    // Record information about chrome's module.
+    global_data.SetUint(browser_watcher::kStabilityModuleAddress,
+                        reinterpret_cast<uint64_t>(&__ImageBase));
+
+    base::win::PEImage pe(&__ImageBase);
+    PIMAGE_NT_HEADERS headers = pe.GetNTHeaders();
+    CHECK(headers);
+    global_data.SetUint(browser_watcher::kStabilityModuleTimestamp,
+                        headers->FileHeader.TimeDateStamp);
+    global_data.SetUint(browser_watcher::kStabilityModuleSize,
+                        headers->OptionalHeader.SizeOfImage);
   }
 }
 #endif  // defined(OS_WIN)
diff --git a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc
index 5f11a6d..15d618a 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.cc
@@ -5,119 +5,14 @@
 #include "chrome/browser/chromeos/accessibility/accessibility_extension_loader.h"
 
 #include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/path_service.h"
-#include "chrome/browser/chromeos/login/lock/screen_locker.h"
-#include "chrome/browser/chromeos/login/lock/webui_screen_locker.h"
-#include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/extension_api_frame_id_map.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/browser/file_reader.h"
-#include "extensions/browser/script_executor.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/extension_messages.h"
-#include "extensions/common/extension_resource.h"
 
 namespace chromeos {
 
-namespace {
-
-// Uses the ScriptExecutor associated with the given |render_view_host| to
-// execute the given |code|.
-void ExecuteScriptHelper(content::RenderViewHost* render_view_host,
-                         const std::string& code,
-                         const std::string& extension_id) {
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderViewHost(render_view_host);
-  if (!web_contents)
-    return;
-  if (!extensions::TabHelper::FromWebContents(web_contents))
-    extensions::TabHelper::CreateForWebContents(web_contents);
-  extensions::TabHelper::FromWebContents(web_contents)
-      ->script_executor()
-      ->ExecuteScript(HostID(HostID::EXTENSIONS, extension_id),
-                      extensions::ScriptExecutor::JAVASCRIPT, code,
-                      extensions::ScriptExecutor::INCLUDE_SUB_FRAMES,
-                      extensions::ExtensionApiFrameIdMap::kTopFrameId,
-                      extensions::ScriptExecutor::DONT_MATCH_ABOUT_BLANK,
-                      extensions::UserScript::DOCUMENT_IDLE,
-                      extensions::ScriptExecutor::ISOLATED_WORLD,
-                      extensions::ScriptExecutor::DEFAULT_PROCESS,
-                      GURL(),  // No webview src.
-                      GURL(),  // No file url.
-                      false,   // Not user gesture.
-                      extensions::ScriptExecutor::NO_RESULT,
-                      extensions::ScriptExecutor::ExecuteScriptCallback());
-}
-
-// Helper class that directly loads an extension's content scripts into
-// all of the frames corresponding to a given RenderViewHost.
-class ContentScriptLoader {
- public:
-  // Initialize the ContentScriptLoader with the ID of the extension
-  // and the RenderViewHost where the scripts should be loaded.
-  ContentScriptLoader(const std::string& extension_id,
-                      int render_process_id,
-                      int render_view_id)
-      : extension_id_(extension_id),
-        render_process_id_(render_process_id),
-        render_view_id_(render_view_id) {}
-
-  // Call this once with the ExtensionResource corresponding to each
-  // content script to be loaded.
-  void AppendScript(extensions::ExtensionResource resource) {
-    resources_.push(resource);
-  }
-
-  // Finally, call this method once to fetch all of the resources and
-  // load them. This method will delete this object when done.
-  void Run() {
-    if (resources_.empty()) {
-      delete this;
-      return;
-    }
-
-    extensions::ExtensionResource resource = resources_.front();
-    resources_.pop();
-    scoped_refptr<FileReader> reader(new FileReader(
-        resource,
-        FileReader::OptionalFileThreadTaskCallback(),  // null callback.
-        base::Bind(&ContentScriptLoader::OnFileLoaded,
-                   base::Unretained(this))));
-    reader->Start();
-  }
-
- private:
-  void OnFileLoaded(bool success, std::unique_ptr<std::string> data) {
-    if (success) {
-      content::RenderViewHost* render_view_host =
-          content::RenderViewHost::FromID(render_process_id_, render_view_id_);
-      if (render_view_host)
-        ExecuteScriptHelper(render_view_host, *data, extension_id_);
-    }
-    Run();
-  }
-
-  std::string extension_id_;
-  int render_process_id_;
-  int render_view_id_;
-  std::queue<extensions::ExtensionResource> resources_;
-};
-
-}  // namespace
-
 AccessibilityExtensionLoader::AccessibilityExtensionLoader(
     const std::string& extension_id,
     const base::FilePath& extension_path,
@@ -125,8 +20,7 @@
     : profile_(nullptr),
       extension_id_(extension_id),
       extension_path_(extension_path),
-      loaded_on_lock_screen_(false),
-      loaded_on_user_screen_(false),
+      loaded_(false),
       unload_callback_(unload_callback),
       weak_ptr_factory_(this) {}
 
@@ -137,7 +31,7 @@
     const base::Closure& done_callback) {
   profile_ = profile;
 
-  if (!loaded_on_user_screen_ && !loaded_on_lock_screen_)
+  if (!loaded_)
     return;
 
   // If the extension was already enabled, but not for this profile, add it
@@ -146,32 +40,25 @@
       extensions::ExtensionSystem::Get(profile_)->extension_service();
   auto* component_loader = extension_service->component_loader();
   if (!component_loader->Exists(extension_id_))
-    LoadExtension(profile_, nullptr, done_callback);
+    LoadExtension(profile_, done_callback);
 }
 
 void AccessibilityExtensionLoader::Load(Profile* profile,
-                                        const std::string& init_script_str,
                                         const base::Closure& done_cb) {
   profile_ = profile;
-  init_script_str_ = init_script_str;
-  ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
-  if (screen_locker && screen_locker->locked()) {
-    // If on the lock screen, loads only to the lock screen as for
-    // now. On unlock, it will be loaded to the user screen.
-    // (see. AccessibilityExtensionLoader::Observe())
-    LoadToLockScreen(done_cb);
-  } else {
-    LoadToUserScreen(done_cb);
-  }
+
+  if (loaded_)
+    return;
+
+  loaded_ = true;
+  LoadExtension(profile_, done_cb);
 }
 
 void AccessibilityExtensionLoader::Unload() {
-  if (loaded_on_lock_screen_)
-    UnloadFromLockScreen();
-
-  if (loaded_on_user_screen_) {
+  if (loaded_) {
     UnloadExtensionFromProfile(profile_);
-    loaded_on_user_screen_ = false;
+    UnloadExtensionFromProfile(ProfileHelper::GetSigninProfile());
+    loaded_ = false;
   }
 
   profile_ = nullptr;
@@ -180,53 +67,6 @@
     unload_callback_.Run();
 }
 
-void AccessibilityExtensionLoader::LoadToUserScreen(
-    const base::Closure& done_cb) {
-  if (loaded_on_user_screen_)
-    return;
-
-  // Determine whether an OOBE screen is currently being shown. If so,
-  // the extension will be injected directly into that screen.
-  content::WebUI* login_web_ui = nullptr;
-
-  if (ProfileHelper::IsSigninProfile(profile_)) {
-    LoginDisplayHost* login_display_host = LoginDisplayHost::default_host();
-    if (login_display_host) {
-      WebUILoginView* web_ui_login_view =
-          login_display_host->GetWebUILoginView();
-      if (web_ui_login_view)
-        login_web_ui = web_ui_login_view->GetWebUI();
-    }
-
-    // Lock screen uses the signin progile.
-    loaded_on_lock_screen_ = true;
-  }
-
-  loaded_on_user_screen_ = true;
-  LoadExtension(profile_,
-                login_web_ui
-                    ? login_web_ui->GetWebContents()->GetRenderViewHost()
-                    : nullptr,
-                done_cb);
-}
-
-void AccessibilityExtensionLoader::LoadToLockScreen(
-    const base::Closure& done_cb) {
-  if (loaded_on_lock_screen_)
-    return;
-
-  ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
-  if (screen_locker && screen_locker->locked()) {
-    content::WebUI* lock_web_ui = screen_locker->web_ui()->GetWebUI();
-    if (lock_web_ui) {
-      Profile* profile = Profile::FromWebUI(lock_web_ui);
-      loaded_on_lock_screen_ = true;
-      LoadExtension(profile, lock_web_ui->GetWebContents()->GetRenderViewHost(),
-                    done_cb);
-    }
-  }
-}
-
 //
 // private
 //
@@ -238,74 +78,11 @@
   extension_service->component_loader()->Remove(extension_path_);
 }
 
-void AccessibilityExtensionLoader::UnloadFromLockScreen() {
-  // Lock screen uses the signin progile.
-  Profile* signin_profile = ProfileHelper::GetSigninProfile();
-  UnloadExtensionFromProfile(signin_profile);
-  loaded_on_lock_screen_ = false;
-}
-
-void AccessibilityExtensionLoader::InjectContentScriptAndCallback(
-    ExtensionService* extension_service,
-    int render_process_id,
-    int render_view_id,
-    const base::Closure& done_cb) {
-  // Make sure to always run |done_cb|.  The extension was loaded even
-  // if we end up not injecting into this particular render view.
-  base::ScopedClosureRunner done_runner(done_cb);
-  content::RenderViewHost* render_view_host =
-      content::RenderViewHost::FromID(render_process_id, render_view_id);
-  if (!render_view_host)
-    return;
-  const content::WebContents* web_contents =
-      content::WebContents::FromRenderViewHost(render_view_host);
-  GURL content_url;
-  if (web_contents)
-    content_url = web_contents->GetLastCommittedURL();
-  const extensions::Extension* extension =
-      extensions::ExtensionRegistry::Get(extension_service->profile())
-          ->enabled_extensions()
-          .GetByID(extension_id_);
-
-  if (!init_script_str_.empty()) {
-    ExecuteScriptHelper(render_view_host, init_script_str_, extension->id());
-  }
-
-  // Inject the content scripts.
-  ContentScriptLoader* loader = new ContentScriptLoader(
-      extension->id(), render_view_host->GetProcess()->GetID(),
-      render_view_host->GetRoutingID());
-
-  const extensions::UserScriptList& content_scripts =
-      extensions::ContentScriptsInfo::GetContentScripts(extension);
-  for (const std::unique_ptr<extensions::UserScript>& script :
-       content_scripts) {
-    if (web_contents && !script->MatchesURL(content_url))
-      continue;
-    for (const std::unique_ptr<extensions::UserScript::File>& file :
-         script->js_scripts()) {
-      extensions::ExtensionResource resource =
-          extension->GetResource(file->relative_path());
-      loader->AppendScript(resource);
-    }
-  }
-  loader->Run();  // It cleans itself up when done.
-}
-
 void AccessibilityExtensionLoader::LoadExtension(
     Profile* profile,
-    content::RenderViewHost* render_view_host,
     base::Closure done_cb) {
   ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
-  if (render_view_host) {
-    // Wrap the passed in callback to inject the content script.
-    done_cb = base::Bind(
-        &AccessibilityExtensionLoader::InjectContentScriptAndCallback,
-        weak_ptr_factory_.GetWeakPtr(), extension_service,
-        render_view_host->GetProcess()->GetID(),
-        render_view_host->GetRoutingID(), done_cb);
-  }
 
   extension_service->component_loader()->AddComponentFromDir(
       extension_path_, extension_id_.c_str(), done_cb);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h
index 34d30ed..a8e983ad 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_extension_loader.h
@@ -9,11 +9,6 @@
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 
-namespace content {
-class RenderViewHost;
-}
-
-class ExtensionService;
 class Profile;
 
 namespace chromeos {
@@ -26,35 +21,19 @@
   ~AccessibilityExtensionLoader();
 
   void SetProfile(Profile* profile, const base::Closure& done_callback);
-  void Load(Profile* profile,
-            const std::string& init_script_str,
-            const base::Closure& done_cb);
+  void Load(Profile* profile, const base::Closure& done_cb);
   void Unload();
-  void LoadToUserScreen(const base::Closure& done_cb);
-  void LoadToLockScreen(const base::Closure& done_cb);
   void LoadExtension(Profile* profile,
-                     content::RenderViewHost* render_view_host,
                      base::Closure done_cb);
 
-  bool loaded_on_lock_screen() { return loaded_on_lock_screen_; }
-
  private:
-  void InjectContentScriptAndCallback(ExtensionService* extension_service,
-                                      int render_process_id,
-                                      int render_view_id,
-                                      const base::Closure& done_cb);
-  void UnloadFromLockScreen();
   void UnloadExtensionFromProfile(Profile* profile);
 
   Profile* profile_;
   std::string extension_id_;
   base::FilePath extension_path_;
-  std::string init_script_str_;
 
-  // Profile which the extension is currently loaded to.
-  // If nullptr, it is not loaded to any profile.
-  bool loaded_on_lock_screen_;
-  bool loaded_on_user_screen_;
+  bool loaded_;
 
   base::Closure unload_callback_;
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 1650a437..5597050 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -66,7 +66,6 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_manager_connection.h"
@@ -87,7 +86,6 @@
 #include "ui/keyboard/keyboard_util.h"
 
 using content::BrowserThread;
-using content::RenderViewHost;
 using extensions::api::braille_display_private::BrailleController;
 using extensions::api::braille_display_private::DisplayState;
 using extensions::api::braille_display_private::KeyEvent;
@@ -261,7 +259,6 @@
       select_to_speak_enabled_(false),
       switch_access_enabled_(false),
       spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE),
-      should_speak_chrome_vox_announcements_on_user_screen_(true),
       system_sounds_enabled_(false),
       braille_display_connected_(false),
       scoped_braille_observer_(this),
@@ -278,9 +275,6 @@
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_PROFILE_DESTROYED,
                               content::NotificationService::AllSources());
-  notification_registrar_.Add(this,
-                              chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
-                              content::NotificationService::AllSources());
 
   input_method::InputMethodManager::Get()->AddObserver(this);
 
@@ -483,7 +477,7 @@
   NotifyAccessibilityStatusChanged(details);
 
   if (enabled) {
-    chromevox_loader_->Load(profile_, "window.INJECTED_AFTER_LOAD = true;",
+    chromevox_loader_->Load(profile_,
                             base::Bind(&AccessibilityManager::PostLoadChromeVox,
                                        weak_ptr_factory_.GetWeakPtr()));
   } else {
@@ -886,8 +880,7 @@
   select_to_speak_enabled_ = enabled;
 
   if (enabled) {
-    select_to_speak_loader_->Load(profile_, "" /* init_script_str */,
-                                  base::Closure() /* done_cb */);
+    select_to_speak_loader_->Load(profile_, base::Closure() /* done_cb */);
     select_to_speak_event_handler_.reset(
         new chromeos::SelectToSpeakEventHandler());
   } else {
@@ -1163,10 +1156,6 @@
   return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN);
 }
 
-void AccessibilityManager::InjectChromeVox(RenderViewHost* render_view_host) {
-  chromevox_loader_->LoadExtension(profile_, render_view_host, base::Closure());
-}
-
 std::unique_ptr<AccessibilityStatusSubscription>
 AccessibilityManager::RegisterCallback(const AccessibilityStatusCallback& cb) {
   return callback_list_.Add(cb);
@@ -1245,9 +1234,6 @@
       // Update |profile_| when entering a session.
       SetProfile(ProfileManager::GetActiveUserProfile());
 
-      // Ensure ChromeVox makes announcements at the start of new sessions.
-      should_speak_chrome_vox_announcements_on_user_screen_ = true;
-
       // Add a session state observer to be able to monitor session changes.
       if (!session_state_observer_.get() && ash::Shell::HasInstance())
         session_state_observer_.reset(
@@ -1260,19 +1246,6 @@
         SetProfile(NULL);
       break;
     }
-    case chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED: {
-      bool is_screen_locked = *content::Details<bool>(details).ptr();
-      if (spoken_feedback_enabled_) {
-        if (is_screen_locked)
-          chromevox_loader_->LoadToLockScreen(base::Closure());
-        // If spoken feedback was enabled, make sure it is also enabled on
-        // the user screen.
-        // The status tray gets verbalized by user screen ChromeVox, so we need
-        // to load it on the user screen even if the screen is locked.
-        chromevox_loader_->LoadToUserScreen(base::Closure());
-      }
-      break;
-    }
   }
 }
 
@@ -1320,24 +1293,17 @@
   // Do any setup work needed immediately after ChromeVox actually loads.
   PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS);
 
-  if (chromevox_loader_->loaded_on_lock_screen() ||
-      should_speak_chrome_vox_announcements_on_user_screen_) {
-    extensions::EventRouter* event_router =
-        extensions::EventRouter::Get(profile_);
-    CHECK(event_router);
+  extensions::EventRouter* event_router =
+      extensions::EventRouter::Get(profile_);
+  CHECK(event_router);
 
-    std::unique_ptr<base::ListValue> event_args(new base::ListValue());
-    std::unique_ptr<extensions::Event> event(new extensions::Event(
-        extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX,
-        extensions::api::accessibility_private::OnIntroduceChromeVox::
-            kEventName,
-        std::move(event_args)));
-    event_router->DispatchEventWithLazyListener(
-        extension_misc::kChromeVoxExtensionId, std::move(event));
-  }
-
-  should_speak_chrome_vox_announcements_on_user_screen_ =
-      chromevox_loader_->loaded_on_lock_screen();
+  std::unique_ptr<base::ListValue> event_args(new base::ListValue());
+  std::unique_ptr<extensions::Event> event(new extensions::Event(
+      extensions::events::ACCESSIBILITY_PRIVATE_ON_INTRODUCE_CHROME_VOX,
+      extensions::api::accessibility_private::OnIntroduceChromeVox::kEventName,
+      std::move(event_args)));
+  event_router->DispatchEventWithLazyListener(
+      extension_misc::kChromeVoxExtensionId, std::move(event));
 
   if (!chromevox_panel_) {
     chromevox_panel_ = new ChromeVoxPanel(profile_);
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 87684cb..3da064d05 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -26,10 +26,6 @@
 #include "extensions/browser/extension_system.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
 
-namespace content {
-class RenderViewHost;
-}
-
 class Profile;
 
 namespace chromeos {
@@ -235,9 +231,6 @@
   // Initiates play of shutdown sound and returns it's duration.
   base::TimeDelta PlayShutdownSound();
 
-  // Injects ChromeVox scripts into given |render_view_host|.
-  void InjectChromeVox(content::RenderViewHost* render_view_host);
-
   // Register a callback to be notified when the status of an accessibility
   // option changes.
   std::unique_ptr<AccessibilityStatusSubscription> RegisterCallback(
@@ -386,8 +379,6 @@
 
   ash::AccessibilityNotificationVisibility spoken_feedback_notification_;
 
-  bool should_speak_chrome_vox_announcements_on_user_screen_;
-
   bool system_sounds_enabled_;
 
   AccessibilityStatusCallbackList callback_list_;
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 876e24b..4858e18 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -163,6 +163,13 @@
     return false;
   }
 
+  // IsPrimaryProfile can return true for an incognito profile corresponding
+  // to the primary profile, but ARC does not support it.
+  if (profile->IsOffTheRecord()) {
+    VLOG(1) << "Incognito profile is not supported in ARC.";
+    return false;
+  }
+
   if (profile->IsLegacySupervised()) {
     VLOG(1) << "Supervised users are not supported in ARC.";
     return false;
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 48ff949..84140764 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -1119,12 +1119,12 @@
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_NORMAL,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_HOVERED,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD_HOVER));
     passphrase_visible_button_->SetToggledImage(
         views::ImageButton::STATE_NORMAL,
         ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index 1236787f..92534666 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -280,12 +280,12 @@
             IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_NORMAL,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD));
     passphrase_visible_button_->SetImage(
         views::ImageButton::STATE_HOVERED,
-        ResourceBundle::GetSharedInstance().
-        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
+        *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+            IDR_NETWORK_SHOW_PASSWORD_HOVER));
     passphrase_visible_button_->SetToggledImage(
         views::ImageButton::STATE_NORMAL,
         ResourceBundle::GetSharedInstance().
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
index fce4b86..ea33e64 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
@@ -74,21 +74,6 @@
   return true;
 }
 
-void ChromeWebViewGuestDelegate::OnDidInitialize() {
-#if defined(OS_CHROMEOS)
-  if (chrome::IsRunningInMash()) {
-    NOTIMPLEMENTED();
-    return;
-  }
-  chromeos::AccessibilityManager* accessibility_manager =
-      chromeos::AccessibilityManager::Get();
-  CHECK(accessibility_manager);
-  accessibility_subscription_ = accessibility_manager->RegisterCallback(
-      base::Bind(&ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged,
-                 weak_ptr_factory_.GetWeakPtr()));
-#endif
-}
-
 // static
 std::unique_ptr<base::ListValue> ChromeWebViewGuestDelegate::MenuModelToValue(
     const ui::SimpleMenuModel& menu_model) {
@@ -128,35 +113,6 @@
              chrome::kChromeUIChromeSigninURL;
 }
 
-void ChromeWebViewGuestDelegate::InjectChromeVoxIfNeeded(
-    content::RenderViewHost* render_view_host) {
-#if defined(OS_CHROMEOS)
-  if (!chromevox_injected_) {
-    chromeos::AccessibilityManager* manager =
-        chromeos::AccessibilityManager::Get();
-    if (manager && manager->IsSpokenFeedbackEnabled()) {
-      manager->InjectChromeVox(render_view_host);
-      chromevox_injected_ = true;
-    }
-  }
-#endif
-}
-
-#if defined(OS_CHROMEOS)
-void ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged(
-    const chromeos::AccessibilityStatusEventDetails& details) {
-  if (details.notification_type == chromeos::ACCESSIBILITY_MANAGER_SHUTDOWN) {
-    accessibility_subscription_.reset();
-  } else if (details.notification_type ==
-      chromeos::ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK) {
-    if (details.enabled)
-      InjectChromeVoxIfNeeded(guest_web_contents()->GetRenderViewHost());
-    else
-      chromevox_injected_ = false;
-  }
-}
-#endif
-
 void ChromeWebViewGuestDelegate::SetContextMenuPosition(
     const gfx::Point& position) {
   if (context_menu_position_ == nullptr)
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
index 682f4a23..f64e07c 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
@@ -11,10 +11,6 @@
 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
 #include "extensions/browser/guest_view/web_view/web_view_guest_delegate.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#endif
-
 class RenderViewContextMenuBase;
 
 namespace ui {
@@ -30,7 +26,6 @@
 
   // WebViewGuestDelegate implementation.
   bool HandleContextMenu(const content::ContextMenuParams& params) override;
-  void OnDidInitialize() override;
   void OnShowContextMenu(int request_id) override;
   bool ShouldHandleFindRequestsForEmbedder() const override;
 
@@ -47,14 +42,6 @@
   static std::unique_ptr<base::ListValue> MenuModelToValue(
       const ui::SimpleMenuModel& menu_model);
 
-  void InjectChromeVoxIfNeeded(content::RenderViewHost* render_view_host);
-
-#if defined(OS_CHROMEOS)
-  // Notification of a change in the state of an accessibility setting.
-  void OnAccessibilityStatusChanged(
-      const chromeos::AccessibilityStatusEventDetails& details);
-#endif
-
   // A counter to generate a unique request id for a context menu request.
   // We only need the ids to be unique for a given WebViewGuest.
   int pending_context_menu_request_id_;
@@ -63,15 +50,6 @@
   // shown. This is .reset() after ShowContextMenu().
   std::unique_ptr<RenderViewContextMenuBase> pending_menu_;
 
-#if defined(OS_CHROMEOS)
-  // Set to |true| if ChromeVox was already injected in main frame.
-  bool chromevox_injected_ = false;
-
-  // Subscription to receive notifications on changes to a11y settings.
-  std::unique_ptr<chromeos::AccessibilityStatusSubscription>
-      accessibility_subscription_;
-#endif
-
   WebViewGuest* const web_view_guest_;
 
   std::unique_ptr<gfx::Point> context_menu_position_;
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 21dbd851..b121fa6c1 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -3294,10 +3294,16 @@
   base::SimpleTestTickClock* clock = OverridePrerenderManagerTimeTicks();
 
   GURL url = embedded_test_server()->GetURL("/prerender/prerender_page.html");
+  base::RunLoop hanging_request_waiter;
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::Bind(&CreateHangingFirstRequestInterceptorOnIO,
+                                     url, GetTestPath("prerender_page.html"),
+                                     hanging_request_waiter.QuitClosure()));
   // As this load will be canceled, it is not waited for, and hence no
   // javascript is executed.
   DisableJavascriptCalls();
   PrerenderTestURL(url, FINAL_STATUS_CANCELLED, 0);
+  hanging_request_waiter.Run();
 
   // This prerender cancels and reuses the first.
   clock->Advance(base::TimeDelta::FromSeconds(1));
diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc
index 60bf8349..d7ea7309 100644
--- a/chrome/browser/prerender/prerender_histograms.cc
+++ b/chrome/browser/prerender/prerender_histograms.cc
@@ -468,10 +468,9 @@
 
   if (!prefetch_age.is_zero()) {
     DCHECK_NE(origin, ORIGIN_NONE);
-    RecordHistogramTime(
-        GetHistogramName(origin, IsOriginWash(), "Prerender.PrefetchAge"),
-        base::TimeDelta::FromMilliseconds(10), base::TimeDelta::FromMinutes(30),
-        prefetch_age, 50);
+    RecordHistogramTime(GetHistogramName(origin, IsOriginWash(), "PrefetchAge"),
+                        base::TimeDelta::FromMilliseconds(10),
+                        base::TimeDelta::FromMinutes(30), prefetch_age, 50);
   }
 
   std::string histogram_base_name;
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index 522c0a4..69d7fb1 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -178,6 +178,7 @@
       "Prerender.websame_PrefetchTTFCP.Warm.Cacheable.Visible", 1);
   histogram_tester().ExpectTotalCount(
       "Prerender.websame_NoStatePrefetchResponseTypes", 2);
+  histogram_tester().ExpectTotalCount("Prerender.websame_PrefetchAge", 1);
 }
 
 // Checks the prefetch of an img tag.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
index b1f96568..8c0c9d50 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -88,12 +88,6 @@
    */
   this.currentRange_ = null;
 
-  /**
-   * @type {cursors.Range}
-   * @private
-   */
-  this.savedRange_ = null;
-
   // Manually bind all functions to |this|.
   for (var func in this) {
     if (typeof(this[func]) == 'function')
@@ -156,9 +150,6 @@
   /** @type {!LiveRegions} @private */
   this.liveRegions_ = new LiveRegions(this);
 
-  /** @type {boolean} @private */
-  this.inExcursion_ = false;
-
   /**
    * Stores the mode as computed the last time a current range was set.
    * @type {?ChromeVoxMode}
@@ -397,9 +388,6 @@
    * @override
    */
   setCurrentRange: function(newRange) {
-    if (!this.inExcursion_ && newRange)
-      this.savedRange_ = new cursors.Range(newRange.start, newRange.end);
-
     if (newRange && !newRange.isValid())
       return;
 
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js
index 2f3505ff..fcc3b8c8 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js
@@ -23,6 +23,8 @@
 
   document.addEventListener('keydown', this.onKeyDown.bind(this), false);
   document.addEventListener('keyup', this.onKeyUp.bind(this), false);
+
+  chrome.accessibilityPrivate.setKeyboardListener(true, false);
 };
 
 BackgroundKeyboardHandler.prototype = {
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index 3032f242..3ae34bf 100644
--- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/route.html">
 <link rel="import" href="/settings_shared_css.html">
@@ -36,30 +36,34 @@
 
     <h2>$i18n{textToSpeechHeading}</h2>
     <div class="settings-box first" actionable>
-      <settings-checkbox class="start" pref="{{prefs.settings.accessibility}}"
+      <settings-toggle-button class="start"
+          pref="{{prefs.settings.accessibility}}"
           label="$i18n{chromeVoxLabel}">
-      </settings-checkbox>
-      <button class="icon-external" is="paper-icon-button-light"
-          on-tap="onChromeVoxSettingsTap_"
-          hidden="[[!prefs.settings.accessibility.value]]"></button>
+        <button class="more-actions icon-external" is="paper-icon-button-light"
+            on-tap="onChromeVoxSettingsTap_"
+            hidden="[[!prefs.settings.accessibility.value]]"></button>
+      </settings-toggle-button>
     </div>
     <template is="dom-if" if="[[showExperimentalFeatures_]]">
       <div class="settings-box block">
-        <settings-checkbox pref="{{prefs.settings.a11y.select_to_speak}}"
+        <settings-toggle-button
+            pref="{{prefs.settings.a11y.select_to_speak}}"
             label="$i18n{selectToSpeakTitle}"
             sub-label="$i18n{selectToSpeakDescription}">
-        </settings-checkbox>
+        </settings-toggle-button>
       </div>
     </template>
 
     <h2>$i18n{displayHeading}</h2>
     <div class="settings-box block first">
-      <settings-checkbox label="$i18n{highContrastLabel}"
-          pref="{{prefs.settings.a11y.high_contrast_enabled}}">
-      </settings-checkbox>
-      <settings-checkbox label="$i18n{screenMagnifierLabel}"
-          pref="{{prefs.settings.a11y.screen_magnifier}}">
-      </settings-checkbox>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.high_contrast_enabled}}"
+          label="$i18n{highContrastLabel}">
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.screen_magnifier}}"
+          label="$i18n{screenMagnifierLabel}">
+      </settings-toggle-button>
     </div>
     <div class="settings-box two-line" on-tap="onDisplayTap_" actionable>
       <div class="start">
@@ -78,23 +82,27 @@
 
     <h2>$i18n{keyboardHeading}</h2>
     <div class="settings-box block first">
-      <settings-checkbox
+      <settings-toggle-button
           pref="{{prefs.settings.a11y.sticky_keys_enabled}}"
           label="$i18n{stickyKeysLabel}">
-      </settings-checkbox>
-      <settings-checkbox pref="{{prefs.settings.a11y.virtual_keyboard}}"
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.virtual_keyboard}}"
           label="$i18n{onScreenKeyboardLabel}">
-      </settings-checkbox>
-      <settings-checkbox pref="{{prefs.settings.a11y.focus_highlight}}"
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.focus_highlight}}"
           label="$i18n{focusHighlightLabel}">
-      </settings-checkbox>
-      <settings-checkbox pref="{{prefs.settings.a11y.caret_highlight}}"
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.caret_highlight}}"
           label="$i18n{caretHighlightLabel}">
-      </settings-checkbox>
+      </settings-toggle-button>
       <template is="dom-if" if="[[showExperimentalFeatures_]]">
-        <settings-checkbox pref="{{prefs.settings.a11y.switch_access}}"
+        <settings-toggle-button
+            pref="{{prefs.settings.a11y.switch_access}}"
             label="$i18n{switchAccessLabel}">
-        </settings-checkbox>
+        </settings-toggle-button>
       </template>
     </div>
     <div class="settings-box two-line" on-tap="onKeyboardTap_" actionable>
@@ -107,10 +115,11 @@
 
     <h2>$i18n{mouseAndTouchpadHeading}</h2>
     <div class="settings-box block first">
-      <settings-checkbox label="$i18n{clickOnStopLabel}"
-          pref="{{prefs.settings.a11y.autoclick}}">
-      </settings-checkbox>
-      <div class="list-item settings-checkbox-spacer">
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.autoclick}}"
+          label="$i18n{clickOnStopLabel}">
+      </settings-toggle-button>
+      <div class="list-item settings-toggle-button-spacer">
         <div>$i18n{delayBeforeClickLabel}</div>
         <settings-dropdown-menu
             pref="{{prefs.settings.a11y.autoclick_delay_ms}}"
@@ -118,15 +127,18 @@
             disabled="[[!prefs.settings.a11y.autoclick.value]]">
         </settings-dropdown-menu>
       </div>
-      <settings-checkbox label="$i18n{tapDraggingLabel}"
-          pref="{{prefs.settings.touchpad.enable_tap_dragging}}">
-      </settings-checkbox>
-      <settings-checkbox label="$i18n{largeMouseCursorLabel}"
-          pref="{{prefs.settings.a11y.large_cursor_enabled}}">
-      </settings-checkbox>
-      <settings-checkbox pref="{{prefs.settings.a11y.cursor_highlight}}"
+      <settings-toggle-button
+          pref="{{prefs.settings.touchpad.enable_tap_dragging}}"
+          label="$i18n{tapDraggingLabel}">
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.large_cursor_enabled}}"
+          label="$i18n{largeMouseCursorLabel}">
+      </settings-toggle-button>
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.cursor_highlight}}"
           label="$i18n{cursorHighlightLabel}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
     <div class="settings-box two-line" on-tap="onMouseTap_" actionable>
       <div class="start">
@@ -138,9 +150,10 @@
 
     <h2>$i18n{audioHeading}</h2>
     <div class="settings-box block first">
-      <settings-checkbox pref="{{prefs.settings.a11y.mono_audio}}"
+      <settings-toggle-button
+          pref="{{prefs.settings.a11y.mono_audio}}"
           label="$i18n{monoAudioLabel}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
 
     <div class="settings-box two-line" on-tap="onMoreFeaturesTap_" actionable>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
index d0141e32..6843f2f 100644
--- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
+++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
@@ -2,7 +2,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="/android_apps_page/android_apps_browser_proxy.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/prefs/prefs_behavior.html">
 <link rel="import" href="/settings_shared_css.html">
@@ -21,10 +21,12 @@
     </style>
 
     <div class="settings-box first">
-      <settings-checkbox id="enabledCheckbox" pref="{{prefs.arc.enabled}}"
+      <settings-toggle-button id="enabled" class="start"
+          pref="{{prefs.arc.enabled}}"
           label="$i18n{androidAppsEnabled}"
-          no-set-pref on-change="onArcEnabledChange_">
-      </settings-checkbox>
+          on-change="onArcEnabledChange_"
+          no-set-pref>
+      </settings-toggle-button>
       <a href="$i18nRaw{androidAppsLearnMoreUrl}" target="_blank">
         $i18n{androidAppsLearnMore}
       </a>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.js b/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
index 44ece83..9ac62e6 100644
--- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
+++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.js
@@ -87,8 +87,7 @@
    * @private
    */
   onConfirmDisableDialogConfirm_: function() {
-    /** @type {!SettingsCheckboxElement} */ (this.$.enabledCheckbox)
-        .sendPrefChange();
+    /** @type {!SettingsCheckboxElement} */ (this.$.enabled).sendPrefChange();
     this.$.confirmDisableDialog.close();
   },
 
@@ -98,8 +97,7 @@
    * @private
    */
   onConfirmDisableDialogCancel_: function() {
-    /** @type {!SettingsCheckboxElement} */ (this.$.enabledCheckbox)
-        .resetToPrefValue();
+    /** @type {!SettingsCheckboxElement} */ (this.$.enabled).resetToPrefValue();
     this.$.confirmDisableDialog.close();
   },
 });
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index 14179aa..b945c8f 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -11,6 +11,7 @@
 <link rel="import" href="/controls/settings_dropdown_menu.html">
 <link rel="import" href="/controls/settings_input.html">
 <link rel="import" href="/controls/settings_radio_group.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/route.html">
 <link rel="import" href="/settings_page/settings_animated_pages.html">
 <link rel="import" href="/settings_page/settings_subpage.html">
@@ -90,11 +91,12 @@
         </div>
         <div class="settings-box"
             hidden="[[!pageVisibility.homeButton]]">
-          <settings-checkbox class="start" label="$i18n{showHomeButton}"
+          <settings-toggle-button class="start"
+              pref="{{prefs.browser.show_home_button}}"
+              label="$i18n{showHomeButton}"
               sub-label="[[getShowHomeSubLabel_(
-                  prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]"
-              pref="{{prefs.browser.show_home_button}}">
-          </settings-checkbox>
+                  prefs.homepage_is_newtabpage.value, prefs.homepage.value)]]">
+          </settings-toggle-button>
         </div>
         <template is="dom-if" if="[[prefs.browser.show_home_button.value]]">
           <div class="list-frame"
@@ -130,15 +132,18 @@
         </template>
         <div class="settings-box"
             hidden="[[!pageVisibility.bookmarksBar]]">
-          <settings-checkbox class="start" label="$i18n{showBookmarksBar}"
-              pref="{{prefs.bookmark_bar.show_on_all_tabs}}">
-          </settings-checkbox>
+          <settings-toggle-button class="start"
+              pref="{{prefs.bookmark_bar.show_on_all_tabs}}"
+              label="$i18n{showBookmarksBar}">
+          </settings-toggle-button>
         </div>
         <div class$="settings-box [[getFirst_(pageVisibility.bookmarksBar)]]">
 <if expr="is_linux and not chromeos">
-          <settings-checkbox class="start" label="$i18n{showWindowDecorations}"
-              pref="{{prefs.browser.custom_chrome_frame}}" inverted>
-          </settings-checkbox>
+          <settings-toggle-button class="start"
+              pref="{{prefs.browser.custom_chrome_frame}}"
+              label="$i18n{showWindowDecorations}"
+              inverted>
+          </settings-toggle-button>
         </div>
         <div class="settings-box">
 </if>
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chrome/browser/resources/settings/controls/settings_toggle_button.html
index c21d78c..624f41a 100644
--- a/chrome/browser/resources/settings/controls/settings_toggle_button.html
+++ b/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -21,8 +21,13 @@
         @apply(--settings-secondary-unchecked);
       }
 
+      paper-toggle-button,
       cr-policy-pref-indicator {
-        -webkit-margin-end: var(--checkbox-spacing);
+        -webkit-margin-start: var(--checkbox-spacing);
+      }
+
+      ::content .more-actions {
+        -webkit-margin-end: 10px;
       }
     </style>
     <div id="outerRow" noSubLabel$="[[!subLabel]]">
@@ -31,6 +36,7 @@
         <div>[[label]]</div>
         <div class="secondary">[[subLabel]]</div>
       </div>
+      <content selector=".more-actions"></content>
       <template is="dom-if" if="[[pref.controlledBy]]">
         <cr-policy-pref-indicator pref="[[pref]]"></cr-policy-pref-indicator>
       </template>
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html
index 840d2606..185df7e 100644
--- a/chrome/browser/resources/settings/date_time_page/date_time_page.html
+++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,10 +1,10 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="/controls/settings_dropdown_menu.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/prefs/prefs_behavior.html">
 <link rel="import" href="/prefs/prefs_types.html">
@@ -28,22 +28,23 @@
       </settings-dropdown-menu>
     </div>
     <div class="settings-box continuation">
-      <paper-checkbox
-          id="timeZoneAutoDetectCheckbox"
-          checked="[[timeZoneAutoDetect_]]"
-          disabled="[[hasTimeZoneAutoDetectPolicy_]]"
-          on-change="onTimeZoneAutoDetectCheckboxChange_">
-        $i18n{timeZoneGeolocation}
-      </paper-checkbox>
+      <div class="start">$i18n{timeZoneGeolocation}</div>
       <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]">
         <cr-policy-pref-indicator pref="[[timeZonePolicyPref_]]">
         </cr-policy-pref-indicator>
       </template>
+      <paper-toggle-button
+          id="timeZoneAutoDetect"
+          checked="[[timeZoneAutoDetect_]]"
+          disabled="[[hasTimeZoneAutoDetectPolicy_]]"
+          on-change="onTimeZoneAutoDetectChange_">
+      </paper-toggle-button>
     </div>
     <div class="settings-box continuation">
-      <settings-checkbox pref="{{prefs.settings.clock.use_24hour_clock}}"
+      <settings-toggle-button class="start"
+          pref="{{prefs.settings.clock.use_24hour_clock}}"
           label="$i18n{use24HourClock}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
     <div class="settings-box" id="setDateTime" actionable
         on-tap="onSetDateTimeTap_" hidden$="[[!canSetDateTime_]]">
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.js b/chrome/browser/resources/settings/date_time_page/date_time_page.js
index 3c7fb7d1..6e28f44 100644
--- a/chrome/browser/resources/settings/date_time_page/date_time_page.js
+++ b/chrome/browser/resources/settings/date_time_page/date_time_page.js
@@ -151,7 +151,7 @@
    * @param {!Event} e
    * @private
    */
-  onTimeZoneAutoDetectCheckboxChange_: function(e) {
+  onTimeZoneAutoDetectChange_: function(e) {
     this.setPrefValue(
         'settings.resolve_timezone_by_geolocation', e.target.checked);
   },
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html
index e5c55c1..2337274 100644
--- a/chrome/browser/resources/settings/device_page/display.html
+++ b/chrome/browser/resources/settings/device_page/display.html
@@ -4,7 +4,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
diff --git a/chrome/browser/resources/settings/device_page/keyboard.html b/chrome/browser/resources/settings/device_page/keyboard.html
index 5b6473a8..73dc9239 100644
--- a/chrome/browser/resources/settings/device_page/keyboard.html
+++ b/chrome/browser/resources/settings/device_page/keyboard.html
@@ -3,8 +3,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="/controls/settings_checkbox.html">
 <link rel="import" href="/controls/settings_dropdown_menu.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/route.html">
 <link rel="import" href="/settings_shared_css.html">
@@ -66,17 +66,17 @@
       </settings-dropdown-menu>
     </div>
     <div class="settings-box">
-      <settings-checkbox
+      <settings-toggle-button class="start"
           pref="{{prefs.settings.language.send_function_keys}}"
           label="$i18n{keyboardSendFunctionKeys}"
           sub-label="$i18n{keyboardSendFunctionKeysDescription}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
     <div class="settings-box">
-      <settings-checkbox
+      <settings-toggle-button class="start"
           pref="{{prefs.settings.language.xkb_auto_repeat_enabled_r2}}"
           label="$i18n{keyboardEnableAutoRepeat}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
     <iron-collapse
         opened="[[prefs.settings.language.xkb_auto_repeat_enabled_r2.value]]">
diff --git a/chrome/browser/resources/settings/device_page/pointers.html b/chrome/browser/resources/settings/device_page/pointers.html
index 7c67f68..60a50fe 100644
--- a/chrome/browser/resources/settings/device_page/pointers.html
+++ b/chrome/browser/resources/settings/device_page/pointers.html
@@ -1,8 +1,8 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
-<link rel="import" href="/controls/settings_checkbox.html">
 <link rel="import" href="/controls/settings_radio_group.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/device_page/device_page_browser_proxy.html">
 <link rel="import" href="/settings_shared_css.html">
 
@@ -30,9 +30,10 @@
       <!-- Subsection title only appears if both mouse and touchpad exist. -->
       <h2 hidden$="[[!hasTouchpad]]">$i18n{mouseTitle}</h2>
       <div class="settings-box first">
-        <settings-checkbox pref="{{prefs.settings.mouse.primary_right}}"
+        <settings-toggle-button class="start"
+            pref="{{prefs.settings.mouse.primary_right}}"
             label="$i18n{mouseSwapButtons}">
-        </settings-checkbox>
+        </settings-toggle-button>
       </div>
       <div class="settings-box">
         <div class="start" id="mouseSpeedLabel">$i18n{mouseSpeed}</div>
@@ -49,14 +50,14 @@
       <!-- Subsection title only appears if both mouse and touchpad exist. -->
       <h2 hidden$="[[!hasMouse]]">$i18n{touchpadTitle}</h2>
       <div class="settings-box block first">
-        <settings-checkbox id="enableTapToClick"
+        <settings-toggle-button id="enableTapToClick"
             pref="{{prefs.settings.touchpad.enable_tap_to_click}}"
             label="$i18n{touchpadTapToClickEnabledLabel}">
-        </settings-checkbox>
-        <settings-checkbox id="enableTapDragging"
+        </settings-toggle-button>
+        <settings-toggle-button id="enableTapDragging"
             pref="{{prefs.settings.touchpad.enable_tap_dragging}}"
             label="$i18n{tapDraggingLabel}">
-        </settings-checkbox>
+        </settings-toggle-button>
       </div>
       <div class="settings-box">
         <div class="start" id="touchpadSpeedLabel">$i18n{touchpadSpeed}</div>
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html
index 42fb14eb..2d4a473 100644
--- a/chrome/browser/resources/settings/device_page/stylus.html
+++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/html/action_link.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/settings_shared_css.html">
 
 <dom-module id="settings-stylus">
@@ -8,18 +8,18 @@
     <style include="settings-shared"></style>
 
     <div class="settings-box">
-      <settings-checkbox
+      <settings-toggle-button class="start"
           pref="{{prefs.settings.enable_stylus_tools}}"
           label="$i18n{stylusEnableStylusTools}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
 
     <div class="settings-box continuation">
-      <settings-checkbox
-          disabled="[[!prefs.settings.enable_stylus_tools.value]]"
+      <settings-toggle-button class="start"
           pref="{{prefs.settings.launch_palette_on_eject_event}}"
-          label="$i18n{stylusAutoOpenStylusTools}">
-      </settings-checkbox>
+          label="$i18n{stylusAutoOpenStylusTools}"
+          disabled="[[!prefs.settings.enable_stylus_tools.value]]">
+      </settings-toggle-button>
     </div>
 
     <div class="settings-box">
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chrome/browser/resources/settings/downloads_page/downloads_page.html
index ee334ebc..6c70bac9 100644
--- a/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="/controls/controlled_button.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/settings_shared_css.html">
 
 <dom-module id="settings-downloads-page">
@@ -29,14 +29,16 @@
       </div>
     </div>
     <div class="settings-box block">
-      <settings-checkbox pref="{{prefs.download.prompt_for_download}}"
+      <settings-toggle-button
+          pref="{{prefs.download.prompt_for_download}}"
           label="$i18n{promptForDownload}">
-      </settings-checkbox>
+      </settings-toggle-button>
 <if expr="chromeos">
-      <settings-checkbox pref="{{prefs.gdata.disabled}}"
+      <settings-toggle-button
+          pref="{{prefs.gdata.disabled}}"
           label="$i18n{disconnectGoogleDriveAccount}"
           hidden="[[!pageVisibility.googleDrive]]">
-      </settings-checkbox>
+      </settings-toggle-button>
 </if>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index 66e0f11e..dd271c2 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -8,7 +8,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="/prefs/prefs.html">
 <link rel="import" href="/route.html">
 <link rel="import" href="internet_shared_css.html">
@@ -154,27 +154,27 @@
         <!-- Prefer this network. -->
         <template is="dom-if" if="[[showPreferNetwork_(networkProperties))]]">
           <div class="settings-box">
-            <paper-checkbox checked="{{preferNetwork_}}"
-                disabled="[[isNetworkPolicyEnforced(
-                    networkProperties.Priority)]]">
-              $i18n{networkPrefer}
-            </paper-checkbox>
+            <div class="start">$i18n{networkPrefer}</div>
             <cr-policy-network-indicator
                 property="[[networkProperties.Priority]]">
             </cr-policy-network-indicator>
+            <paper-toggle-button checked="{{preferNetwork_}}"
+                disabled="[[isNetworkPolicyEnforced(
+                    networkProperties.Priority)]]">
+            </paper-toggle-button>
           </div>
         </template>
         <!-- Autoconnect. -->
         <template is="dom-if" if="[[showAutoConnect_(networkProperties)]]">
           <div class="settings-box">
-            <paper-checkbox checked="{{autoConnect_}}"
-                disabled="[[isNetworkPolicyEnforced(
-                    getManagedAutoConnect_(networkProperties))]]">
-              $i18n{networkAutoConnect}
-            </paper-checkbox>
+            <div class="start">$i18n{networkAutoConnect}</div>
             <cr-policy-network-indicator
                 property="[[getManagedAutoConnect_(networkProperties)]]">
             </cr-policy-network-indicator>
+            <paper-toggle-button checked="{{autoConnect_}}"
+                disabled="[[isNetworkPolicyEnforced(
+                    getManagedAutoConnect_(networkProperties))]]">
+            </paper-toggle-button>
           </div>
         </template>
         <!-- SIM Info (Cellular only). -->
diff --git a/chrome/browser/resources/settings/internet_page/network_ip_config.html b/chrome/browser/resources/settings/internet_page/network_ip_config.html
index d79a2bf..31565f7 100644
--- a/chrome/browser/resources/settings/internet_page/network_ip_config.html
+++ b/chrome/browser/resources/settings/internet_page/network_ip_config.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="internet_shared_css.html">
 <link rel="import" href="network_property_list.html">
 
@@ -8,9 +8,9 @@
   <template>
     <style include="internet-shared"></style>
     <div class="settings-box first">
-      <paper-checkbox checked="{{automatic_}}" disabled="[[!editable]]">
-        $i18n{networkIPConfigAuto}
-      </paper-checkbox>
+      <div class="start">$i18n{networkIPConfigAuto}</div>
+      <paper-toggle-button checked="{{automatic_}}" disabled="[[!editable]]">
+      </paper-toggle-button>
     </div>
     <div class="settings-box continuation"
         hidden$="[[!showIPEditFields_(editable, automatic_)]]">
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy.html b/chrome/browser/resources/settings/internet_page/network_proxy.html
index 8952fa51..ca1f90ce 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy.html
+++ b/chrome/browser/resources/settings/internet_page/network_proxy.html
@@ -6,11 +6,11 @@
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="/controls/extension_controlled_indicator.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/prefs/prefs_behavior.html">
 <link rel="import" href="/settings_vars_css.html">
@@ -47,7 +47,7 @@
         margin: 10px 0;
       }
 
-      #proxyDiv paper-checkbox {
+      #proxyDiv paper-toggle-button {
         padding: 10px 0;
       }
     </style>
@@ -79,11 +79,12 @@
     <div class="settings-box continuation"
         hidden$="[[!shouldShowAllowShared_(
             networkProperties.ProxySettings.Type)]]">
-      <settings-checkbox id="allowShared"
+      <settings-toggle-button id="allowShared" class="start"
           pref="{{prefs.settings.use_shared_proxies}}"
-          no-set-pref label="$i18n{networkProxyAllowShared}"
-          on-change="onAllowSharedProxiesChange_">
-      </settings-checkbox>
+          label="$i18n{networkProxyAllowShared}"
+          on-change="onAllowSharedProxiesChange_"
+          no-set-pref>
+      </settings-toggle-button>
     </div>
 
     <!-- Proxy type dropdown -->
@@ -123,11 +124,13 @@
     <!-- Manual -->
     <div id="proxyDiv" class="settings-box continuation single-column indent"
         hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]">
-      <paper-checkbox checked="{{useSameProxy_}}"
-          disabled="[[!isEditable_('Type', networkProperties, editable,
-              useSharedProxies_)]]">
-        $i18n{networkProxyUseSame}
-      </paper-checkbox>
+      <div class="flex layout horizontal">
+        <div class="flex">$i18n{networkProxyUseSame}</div>
+        <paper-toggle-button checked="{{useSameProxy_}}"
+            disabled="[[!isEditable_('Type', networkProperties, editable,
+                useSharedProxies_)]]">
+        </paper-toggle-button>
+      </div>
       <div hidden$="[[!useSameProxy_]]" class="layout vertical">
         <network-proxy-input 
             on-proxy-change="onProxyInputChange_"
diff --git a/chrome/browser/resources/settings/internet_page/network_siminfo.html b/chrome/browser/resources/settings/internet_page/network_siminfo.html
index f1db2d2..b3d5b589 100644
--- a/chrome/browser/resources/settings/internet_page/network_siminfo.html
+++ b/chrome/browser/resources/settings/internet_page/network_siminfo.html
@@ -3,14 +3,14 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="/icons.html">
 <link rel="import" href="internet_shared_css.html">
 
 <dom-module id="network-siminfo">
   <template>
-    <style include="internet-shared">
+    <style include="settings-shared internet-shared">
       iron-icon {
        -webkit-margin-end: 10px;
       }
@@ -43,6 +43,10 @@
       .settings-box:first-of-type {
         border-top: none;
       }
+
+      paper-toggle-button {
+        -webkit-margin-start: var(--checkbox-spacing);
+      }
     </style>
 
     <!-- SIM missing UI -->
@@ -71,14 +75,14 @@
     <!-- SIM unlocked -->
     <div class="settings-box two-line"
         hidden$="[[!showSimUnlocked_(networkProperties)]]">
-      <paper-checkbox class="start" on-change="onSimLockEnabledChange_"
-          checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
-        $i18n{networkSimLockEnable}
-      </paper-checkbox>
-      <paper-button  on-tap="onChangePinTap_"
+      <div class="start">$i18n{networkSimLockEnable}</div>
+      <paper-button on-tap="onChangePinTap_"
           hidden$="[[!networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
         $i18n{networkSimChangePin}
       </paper-button>
+      <paper-toggle-button on-change="onSimLockEnabledChange_"
+          checked="[[networkProperties.Cellular.SIMLockStatus.LockEnabled]]">
+      </paper-toggle-button>
     </div>
 
     <!-- Enter PIN dialog -->
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
index b7ee06c..f3073fb 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/global_scroll_target_behavior.html">
 <link rel="import" href="/passwords_and_forms_page/password_edit_dialog.html">
 <link rel="import" href="/passwords_and_forms_page/passwords_shared_css.html">
@@ -52,12 +53,12 @@
         -webkit-user-select: text;
       }
     </style>
-    <div class="settings-box first two-line">
-      <settings-checkbox id="autosigninCheckbox"
+    <div class="settings-box first">
+      <settings-toggle-button id="autosigninCheckbox" class="start"
           pref="{{prefs.credentials_enable_autosignin}}"
           label="$i18n{passwordsAutosigninLabel}"
           sub-label="$i18n{passwordsAutosigninDescription}">
-      </settings-checkbox>
+      </settings-toggle-button>
     </div>
     <div id="manageLink" class="settings-box first">
       <!-- This span lays out the url correctly, relative to the label. -->
diff --git a/chrome/browser/resources/settings/people_page/lock_screen.html b/chrome/browser/resources/settings/people_page/lock_screen.html
index be7d39f3..cf290e9 100644
--- a/chrome/browser/resources/settings/people_page/lock_screen.html
+++ b/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -2,6 +2,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/people_page/lock_screen_constants.html">
 <link rel="import" href="/people_page/lock_state_behavior.html">
 <link rel="import" href="/people_page/password_prompt_dialog.html">
@@ -33,7 +34,9 @@
             $i18n{lockScreenPinOrPassword}
           </paper-radio-button>
           <div class="settings-box continuation radio-indent"
-               hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]">
+              hidden$="[[!showConfigurePinButton_(selectedUnlockType)]]">
+            <!-- TODO(dbeam): I seriously doubt paper-button[is=action-link] is
+                 a good idea. -->
             <paper-button is="action-link" on-tap="onConfigurePin_">
               [[getSetupPinText_(hasPin)]]
             </paper-button>
@@ -41,18 +44,18 @@
         </paper-radio-group>
       </div>
 
-      <div class="settings-box single-column">
-        <settings-checkbox pref="{{prefs.settings.enable_screen_lock}}"
-                           label="$i18n{enableScreenlock}">
-        </settings-checkbox>
+      <div class="settings-box">
+        <settings-toggle-button class="start"
+            pref="{{prefs.settings.enable_screen_lock}}"
+            label="$i18n{enableScreenlock}">
+        </settings-toggle-button>
       </div>
 
       <settings-password-prompt-dialog id="passwordPrompt"
-                                       on-close="onPasswordClosed_"
-                                       set-modes="{{setModes_}}">
+          on-close="onPasswordClosed_" set-modes="{{setModes_}}">
       </settings-password-prompt-dialog>
       <settings-setup-pin-dialog id="setupPin" on-done="onPinSetupDone_"
-                                 set-modes="[[setModes_]]">
+          set-modes="[[setModes_]]">
       </settings-setup-pin-dialog>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index d9b0d409..105745a 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -10,7 +10,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/people_page/sync_page.html">
 <link rel="import" href="/people_page/profile_info_browser_proxy.html">
 <link rel="import" href="/people_page/sync_browser_proxy.html">
@@ -200,10 +200,11 @@
 
 <if expr="chromeos">
         <template is="dom-if" if="[[!quickUnlockEnabled_]]">
-          <div class="settings-box single-column">
-            <settings-checkbox pref="{{prefs.settings.enable_screen_lock}}"
+          <div class="settings-box">
+            <settings-toggle-button class="start"
+                pref="{{prefs.settings.enable_screen_lock}}"
                 label="$i18n{enableScreenlock}">
-            </settings-checkbox>
+            </settings-toggle-button>
           </div>
         </template>
 
@@ -235,13 +236,15 @@
                 <a target="_blank" href="$i18n{easyUnlockLearnMoreURL}">
                   $i18n{learnMore}
                 </a>
+                <!-- TODO(dbeam): this should be 1 dom-if with a method instead
+                     of 2 nested dom-ifs. -->
                 <template is="dom-if" if="[[easyUnlockEnabled_]]">
                   <template is="dom-if"
                       if="[[easyUnlockProximityDetectionAllowed_]]">
-                    <settings-checkbox
+                    <settings-toggle-button
                         pref="{{prefs.easy_unlock.proximity_required}}"
                         label="$i18n{easyUnlockRequireProximityLabel}">
-                    </settings-checkbox>
+                    </settings-toggle-button>
                   </template>
                 </template>
               </div>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index b502be0c..6cd9f8aa 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -2,7 +2,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
@@ -44,15 +44,6 @@
           padding: 0;
         };
       }
-
-      /**
-       * This is currently necessary because a link inside a disabled
-       * paper-checkbox inherits `pointer-events: none;` and will not work.
-       * See: https://github.com/PolymerElements/paper-checkbox/issues/166
-       */
-      #paymentLearnMore {
-        pointer-events: initial;
-      }
     </style>
     <div id="[[pages.SPINNER]]" class="settings-box first"
         hidden$="[[!isStatus_(pages.SPINNER, pageStatus_)]]">
@@ -65,96 +56,124 @@
     <div id="[[pages.CONFIGURE]]"
         hidden$="[[!isStatus_(pages.CONFIGURE, pageStatus_)]]">
       <div class="settings-box first">
-        <paper-checkbox id="syncAllDataTypesCheckbox"
+        <div class="start">$i18n{syncEverythingCheckboxLabel}</div>
+        <paper-toggle-button id="syncAllDataTypesControl"
             checked="{{syncPrefs.syncAllDataTypes}}"
             on-change="onSyncAllDataTypesChanged_">
-          $i18n{syncEverythingCheckboxLabel}
-        </paper-checkbox>
+        </paper-toggle-button>
       </div>
 
       <div class="list-frame">
-        <paper-checkbox checked="{{syncPrefs.appsSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.appsRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]">
-          $i18n{appCheckboxLabel}
-        </paper-checkbox>
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{appCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.appsSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.appsRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.appsEnforced)]]">
+          </paper-toggle-button>
+        </div>
 
-        <!-- Autofill has a special on-change handler to deal with
-             Payments integriation. -->
-        <paper-checkbox checked="{{syncPrefs.autofillSynced}}"
-            on-change="onAutofillDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.autofillRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]">
-          $i18n{autofillCheckboxLabel}
-        </paper-checkbox>
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{autofillCheckboxLabel}</div>
+          <!-- Autofill has a special on-change handler to deal with
+               Payments integriation. -->
+          <paper-toggle-button checked="{{syncPrefs.autofillSynced}}"
+              on-change="onAutofillDataTypeChanged_"
+              hidden="[[!syncPrefs.autofillRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.autofillEnforced)]]">
+          </paper-toggle-button>
+        </div>
 
-        <paper-checkbox checked="{{syncPrefs.bookmarksSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.bookmarksRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]">
-          $i18n{bookmarksCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.extensionsSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.extensionsRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]">
-          $i18n{extensionsCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.typedUrlsSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.typedUrlsRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]">
-          $i18n{historyCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.passwordsSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.passwordsRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]">
-          $i18n{passwordsCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.preferencesSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.preferencesRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]">
-          $i18n{settingsCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.themesSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.themesRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]">
-          $i18n{themesAndWallpapersCheckboxLabel}
-        </paper-checkbox>
-        <paper-checkbox checked="{{syncPrefs.tabsSynced}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.tabsRegistered]]"
-            disabled="[[shouldSyncCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]">
-          $i18n{openTabsCheckboxLabel}
-        </paper-checkbox>
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{bookmarksCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.bookmarksSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.bookmarksRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.bookmarksEnforced)]]">
+          </paper-toggle-button>
+        </div>
 
-        <!-- The Payments integration checkbox is a special case in many ways.
-             It's visible only if autofill is registered. It's disabled and
-             unchecked if autofill is unchecked.-->
-        <paper-checkbox checked="{{syncPrefs.paymentsIntegrationEnabled}}"
-            on-change="onSingleSyncDataTypeChanged_" class="list-item"
-            hidden="[[!syncPrefs.autofillRegistered]]"
-            disabled="[[shouldPaymentsCheckboxBeDisabled_(
-                syncPrefs.syncAllDataTypes, syncPrefs.autofillSynced)]]">
-          $i18n{enablePaymentsIntegrationCheckboxLabel}
-          <a href="$i18nRaw{autofillHelpURL}" target="_blank"
-              id="paymentLearnMore" on-tap="onLearnMoreTap_">
-            $i18n{learnMore}
-          </a>
-        </paper-checkbox>
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{extensionsCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.extensionsSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.extensionsRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.extensionsEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{historyCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.typedUrlsSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.typedUrlsRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.typedUrlsEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{passwordsCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.passwordsSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.passwordsRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.passwordsEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{settingsCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.preferencesSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.preferencesRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.preferencesEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{themesAndWallpapersCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.themesSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.themesRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.themesEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <div class="flex">$i18n{openTabsCheckboxLabel}</div>
+          <paper-toggle-button checked="{{syncPrefs.tabsSynced}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.tabsRegistered]]"
+              disabled="[[shouldSyncCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.tabsEnforced)]]">
+          </paper-toggle-button>
+        </div>
+
+        <div class="layout horizontal list-item">
+          <!-- The Payments integration checkbox is a special case in many ways.
+               It's visible only if autofill is registered. It's disabled and
+               unchecked if autofill is unchecked.-->
+          <div class="flex">
+            $i18n{enablePaymentsIntegrationCheckboxLabel}
+            <a href="$i18nRaw{autofillHelpURL}" target="_blank">
+              $i18n{learnMore}
+            </a>
+          </div>
+          <paper-toggle-button
+              checked="{{syncPrefs.paymentsIntegrationEnabled}}"
+              on-change="onSingleSyncDataTypeChanged_"
+              hidden="[[!syncPrefs.autofillRegistered]]"
+              disabled="[[shouldPaymentsCheckboxBeDisabled_(
+                  syncPrefs.syncAllDataTypes, syncPrefs.autofillSynced)]]">
+          </paper-toggle-button>
+        </div>
       </div>
 
       <div class="settings-box two-line" actionable
diff --git a/chrome/browser/resources/settings/people_page/users_page.html b/chrome/browser/resources/settings/people_page/users_page.html
index 9fd6801..f0ddb52 100644
--- a/chrome/browser/resources/settings/people_page/users_page.html
+++ b/chrome/browser/resources/settings/people_page/users_page.html
@@ -1,7 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/settings_shared_css.html">
 <link rel="import" href="user_list.html">
 <link rel="import" href="users_add_user_dialog.html">
@@ -32,28 +32,28 @@
       </template>
     </template>
     <div class="settings-box block">
-      <settings-checkbox
+      <settings-toggle-button
           pref="{{prefs.cros.accounts.allowBWSI}}"
           label="$i18n{guestBrowsingLabel}"
           disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]">
-      </settings-checkbox>
-      <settings-checkbox
+      </settings-toggle-button>
+      <settings-toggle-button
           pref="{{prefs.cros.accounts.supervisedUsersEnabled}}"
           label="$i18n{supervisedUsersLabel}"
           disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]">
-      </settings-checkbox>
-      <settings-checkbox
+      </settings-toggle-button>
+      <settings-toggle-button
           pref="{{prefs.cros.accounts.showUserNamesOnSignIn}}"
           label="$i18n{showOnSigninLabel}"
           disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]">
-      </settings-checkbox>
-      <settings-checkbox
+      </settings-toggle-button>
+      <settings-toggle-button
           pref="{{prefs.cros.accounts.allowGuest}}"
           id="restrictSignIn"
           label="$i18n{restrictSigninLabel}"
           disabled="[[isEditingDisabled_(isOwner_, isWhitelistManaged_)]]"
           inverted>
-      </settings-checkbox>
+      </settings-toggle-button>
       <div class="users">
         <settings-user-list prefs="[[prefs]]"
             disabled="[[isEditingUsersDisabled_(isOwner_, isWhitelistManaged_,
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chrome/browser/resources/settings/printing_page/cloud_printers.html
index fe3c6f69..157c346 100644
--- a/chrome/browser/resources/settings/printing_page/cloud_printers.html
+++ b/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -1,6 +1,6 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/settings_shared_css.html">
 
 <dom-module id="settings-cloud-printers">
@@ -15,8 +15,10 @@
       </span>
     </div>
     <div class="settings-box">
-      <settings-checkbox pref="{{prefs.local_discovery.notifications_enabled}}"
-          label="$i18n{printingNotificationsLabel}"></settings-checkbox>
+      <settings-toggle-button class="start"
+          pref="{{prefs.local_discovery.notifications_enabled}}"
+          label="$i18n{printingNotificationsLabel}">
+      </settings-toggle-button>
     </div>
     <div class="settings-box two-line" on-tap="onManageTap_" actionable>
       <div class="start">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index d315b07..c789f6c 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -6,7 +6,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="/clear_browsing_data_dialog/clear_browsing_data_dialog.html">
-<link rel="import" href="/controls/settings_checkbox.html">
 <link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/lifetime_browser_proxy.html">
 <link rel="import" href="/route.html">
@@ -42,16 +41,6 @@
         min-height: var(--settings-row-min-height);
       }
 
-      #metricsReportingCheckbox,
-      #safeBrowsingExtendedReportingCheckbox {
-        display: inline-block;
-      }
-
-      #metricsReportingCheckbox,
-      #safeBrowsingExtendedReportingCheckbox {
-        width: 100%;
-      }
-
       #metricsReporting paper-tooltip {
         --paper-tooltip: var(--cr-policy-tooltip);
       }
@@ -73,48 +62,41 @@
       <neon-animatable route-path="default">
         <div class="settings-box block first">
           <p class="privacy-explanation">$i18nRaw{improveBrowsingExperience}</p>
-          <settings-checkbox pref="{{prefs.alternate_error_pages.enabled}}"
+          <settings-toggle-button
+              pref="{{prefs.alternate_error_pages.enabled}}"
               label="$i18n{linkDoctorPref}">
-          </settings-checkbox>
-          <settings-checkbox pref="{{prefs.search.suggest_enabled}}"
+          </settings-toggle-button>
+          <settings-toggle-button
+              pref="{{prefs.search.suggest_enabled}}"
               label="$i18n{searchSuggestPref}"
               hidden="[[!pageVisibility.searchPrediction]]">
-          </settings-checkbox>
-          <settings-checkbox pref="{{prefs.net.network_prediction_options}}"
+          </settings-toggle-button>
+          <settings-toggle-button
+              pref="{{prefs.net.network_prediction_options}}"
               label="$i18n{networkPredictionEnabled}"
               hidden="[[!pageVisibility.networkPrediction]]">
-          </settings-checkbox>
+          </settings-toggle-button>
           <div class="layout horizontal center settings-row-min-height">
-            <paper-checkbox id="safeBrowsingExtendedReportingCheckbox"
-                on-tap="onSafeBrowsingExtendedReportingCheckboxTap_"
+            <div class="flex">$i18n{safeBrowsingEnableExtendedReporting}</div>
+            <paper-toggle-button id="safeBrowsingExtendedReportingControl"
+                on-tap="onSafeBrowsingExtendedReportingControlTap_"
                 checked="[[safeBrowsingExtendedReportingEnabled_]]">
-              $i18n{safeBrowsingEnableExtendedReporting}
-            </paper-checkbox>
+            </paper-toggle-button>
           </div>
-          <settings-checkbox pref="{{prefs.safebrowsing.enabled}}"
+          <settings-toggle-button
+              pref="{{prefs.safebrowsing.enabled}}"
               label="$i18n{safeBrowsingEnableProtection}">
-          </settings-checkbox>
+          </settings-toggle-button>
 <if expr="_google_chrome">
 <if expr="chromeos">
-          <settings-checkbox pref="{{prefs.cros.metrics.reportingEnabled}}"
+          <settings-toggle-button
+              pref="{{prefs.cros.metrics.reportingEnabled}}"
               label="$i18n{enableLogging}">
-          </settings-checkbox>
+          </settings-toggle-button>
 </if><!-- chromeos -->
 <if expr="not chromeos">
           <div class="layout horizontal center settings-row-min-height">
-            <paper-checkbox id="metricsReportingCheckbox"
-                on-tap="onMetricsReportingCheckboxTap_"
-                checked="[[metricsReporting_.enabled]]"
-                disabled="[[metricsReporting_.managed]]">
-              $i18n{enableLogging}
-            </paper-checkbox>
-            <template is="dom-if" if="[[metricsReporting_.managed]]" restamp>
-              <iron-icon id="indicator" tabindex=0 icon="cr:domain"></iron-icon>
-              <paper-tooltip for="indicator" position="top"
-                  fit-to-visible-bounds>
-                $i18n{controlledSettingPolicy}
-              </paper-tooltip>
-            </template>
+            <div class="flex">$i18n{enableLogging}</div>
             <template is="dom-if" if="[[showRestart_]]" restamp>
               <div id="restart" class="flex">
                 <paper-button on-tap="onRestartTap_">
@@ -122,21 +104,34 @@
                 </paper-button>
               </div>
             </template>
+            <template is="dom-if" if="[[metricsReporting_.managed]]" restamp>
+              <iron-icon id="indicator" tabindex=0 icon="cr:domain"></iron-icon>
+              <paper-tooltip for="indicator" position="top"
+                  fit-to-visible-bounds>
+                $i18n{controlledSettingPolicy}
+              </paper-tooltip>
+            </template>
+            <paper-toggle-button id="metricsReportingControl"
+                on-tap="onMetricsReportingControlTap_"
+                checked="[[metricsReporting_.enabled]]"
+                disabled="[[metricsReporting_.managed]]">
+            </paper-toggle-button>
           </div>
 </if><!-- not chromeos -->
 </if><!-- _google_chrome -->
-          <settings-checkbox pref="{{prefs.enable_do_not_track}}"
+          <settings-toggle-button
+              pref="{{prefs.enable_do_not_track}}"
               label="$i18n{doNotTrack}">
-          </settings-checkbox>
+          </settings-toggle-button>
 <if expr="chromeos">
-          <settings-checkbox
+          <settings-toggle-button
               pref="{{prefs.cros.device.attestation_for_content_protection_enabled}}"
               label="$i18n{enableContentProtectionAttestation}">
-          </settings-checkbox>
-          <settings-checkbox
+          </settings-toggle-button>
+          <settings-toggle-button
               pref="{{prefs.settings.internet.wake_on_wifi_darkconnect}}"
               label="$i18n{wakeOnWifi}">
-          </settings-checkbox>
+          </settings-toggle-button>
 </if>
         </div>
 <if expr="_google_chrome">
@@ -251,9 +246,9 @@
           </category-default-setting>
           <div class="settings-box">
             <settings-toggle-button class="start"
+                pref="{{prefs.profile.block_third_party_cookies}}"
                 label="$i18n{thirdPartyCookie}"
-                sub-label="$i18n{thirdPartyCookieSublabel}"
-                pref="{{prefs.profile.block_third_party_cookies}}">
+                sub-label="$i18n{thirdPartyCookieSublabel}">
             </settings-toggle-button>
           </div>
           <category-setting-exceptions
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js
index ae72e25..faf61cd 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.js
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -113,9 +113,9 @@
 
 // <if expr="_google_chrome and not chromeos">
   /** @private */
-  onMetricsReportingCheckboxTap_: function() {
+  onMetricsReportingControlTap_: function() {
     var browserProxy = settings.PrivacyPageBrowserProxyImpl.getInstance();
-    var enabled = this.$.metricsReportingCheckbox.checked;
+    var enabled = this.$.metricsReportingControl.checked;
     browserProxy.setMetricsReportingEnabled(enabled);
   },
 
@@ -142,9 +142,9 @@
 // </if>
 
   /** @private */
-  onSafeBrowsingExtendedReportingCheckboxTap_: function() {
+  onSafeBrowsingExtendedReportingControlTap_: function() {
     var browserProxy = settings.PrivacyPageBrowserProxyImpl.getInstance();
-    var enabled = this.$.safeBrowsingExtendedReportingCheckbox.checked;
+    var enabled = this.$.safeBrowsingExtendedReportingControl.checked;
     browserProxy.setSafeBrowsingExtendedReportingEnabled(enabled);
   },
 
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html
index 0320f0f..96b4ba01 100644
--- a/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -5,7 +5,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="/controls/extension_controlled_indicator.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/icons.html">
 <link rel="import" href="/i18n_setup.html">
 <link rel="import" href="/route.html">
@@ -67,27 +67,27 @@
         <template is="dom-if" if="[[googleNowAvailable_]]">
           <!-- Google Now cards in the launcher -->
           <div class="settings-box continuation">
-            <settings-checkbox id="googleNowEnable"
-                label="$i18n{searchEnableGoogleNowLabel}"
-                pref="{{prefs.google_now_launcher.enabled}}">
-            </settings-checkbox>
+            <settings-toggle-button id="googleNowEnable" class="start"
+                pref="{{prefs.google_now_launcher.enabled}}"
+                label="$i18n{searchEnableGoogleNowLabel}">
+            </settings-toggle-button>
           </div>
         </template>
 
         <template is="dom-if" if="[[hotwordInfo_.allowed]]">
           <!-- Hotword (OK Google) -->
           <div class="settings-box two-line continuation">
-            <settings-checkbox id="hotwordSearchEnable" class="start"
+            <settings-toggle-button id="hotwordSearchEnable" class="start"
+                pref="{{hotwordSearchEnablePref_}}"
                 label="$i18n{searchOkGoogleLabel}"
                 sub-label="[[getHotwordSearchEnableSubLabel_(
                            hotwordInfo_.alwaysOn)]]"
-                pref="{{hotwordSearchEnablePref_}}"
                 on-change="onHotwordSearchEnableChange_">
               <a href="$i18nRaw{hotwordLearnMoreUrl}" target="_blank"
                   on-tap="doNothing_">
                 $i18n{searchOkGoogleLearnMore}
               </a>
-            </settings-checkbox>
+            </settings-toggle-button>
             <div class="secondary-action"
                 hidden$="[[!getShowHotwordSearchRetrain_(hotwordInfo_.*)]]">
               <paper-button on-tap="onRetrainTap_" class="secondary-button">
diff --git a/chrome/browser/resources/settings/system_page/system_page.html b/chrome/browser/resources/settings/system_page/system_page.html
index 9a264d6..db416e60 100644
--- a/chrome/browser/resources/settings/system_page/system_page.html
+++ b/chrome/browser/resources/settings/system_page/system_page.html
@@ -3,7 +3,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="/controls/controlled_button.html">
 <link rel="import" href="/controls/extension_controlled_indicator.html">
-<link rel="import" href="/controls/settings_checkbox.html">
+<link rel="import" href="/controls/settings_toggle_button.html">
 <link rel="import" href="/lifetime_browser_proxy.html">
 <link rel="import" href="/prefs/prefs.html">
 <link rel="import" href="/settings_shared_css.html">
@@ -14,19 +14,21 @@
     <style include="settings-shared"></style>
     <div class="settings-box block first">
 <if expr="not is_macosx">
-      <settings-checkbox label="$i18n{backgroundAppsLabel}"
-          pref="{{prefs.background_mode.enabled}}">
-      </settings-checkbox>
+      <settings-toggle-button
+          pref="{{prefs.background_mode.enabled}}"
+          label="$i18n{backgroundAppsLabel}">
+      </settings-toggle-button>
 </if>
-      <div id="hardware-acceleration" class="layout horizontal center">
-        <settings-checkbox class="flex" label="$i18n{hardwareAccelerationLabel}"
-            pref="{{prefs.hardware_acceleration_mode.enabled}}">
-        </settings-checkbox>
+      <settings-toggle-button class="flex" id="hardwareAcceleration"
+          pref="{{prefs.hardware_acceleration_mode.enabled}}"
+          label="$i18n{hardwareAccelerationLabel}">
         <template is="dom-if" if="[[shouldShowRestart_(
             prefs.hardware_acceleration_mode.enabled.value)]]">
-          <paper-button on-tap="onRestartTap_">$i18n{restart}</paper-button>
+          <paper-button on-tap="onRestartTap_" class="more-actions">
+            $i18n{restart}
+          </paper-button>
         </template>
-      </div>
+      </settings-toggle-button>
     </div>
     <div class="settings-box">
       <controlled-button class="primary-button" pref="[[prefs.proxy]]"
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.css b/chrome/browser/resources/vr_shell/vr_shell_ui.css
index af1f1ed..534047c 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.css
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.css
@@ -126,6 +126,8 @@
 }
 
 #omnibox-border {
+  --fadeTimeMs: 500;
+  --fadeYOffset: -0.1;
   --statusBarColor: rgb(66, 133, 244);
   background-color: #ececec;
   border-radius: 200px;
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js
index 93ad0b05..6f0802e 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js
@@ -5,8 +5,8 @@
 var vrShellUi = (function() {
   'use strict';
 
-  let scene = new ui.Scene();
-  let sceneManager;
+  let ui = new scene.Scene();
+  let uiManager;
 
   let uiRootElement = document.querySelector('#ui');
   let uiStyle = window.getComputedStyle(uiRootElement);
@@ -38,13 +38,13 @@
       element.setSize(
           this.SCREEN_HEIGHT * this.SCREEN_RATIO, this.SCREEN_HEIGHT);
       element.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE);
-      this.elementId = scene.addElement(element);
+      this.elementId = ui.addElement(element);
     }
 
     setEnabled(enabled) {
       let update = new api.UiElementUpdate();
       update.setVisible(enabled);
-      scene.updateElement(this.elementId, update);
+      ui.updateElement(this.elementId, update);
     }
 
     setFullscreen(enabled) {
@@ -54,7 +54,7 @@
       } else {
         anim.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE);
       }
-      scene.addAnimation(anim);
+      ui.addAnimation(anim);
     }
 
     // TODO(crbug/643815): Add a method setting aspect ratio (and possible
@@ -81,11 +81,13 @@
 
       // Pull additional custom properties from CSS.
       let style = window.getComputedStyle(domElement);
+      this.translationX = getStyleFloat(style, '--tranX');
+      this.translationY = getStyleFloat(style, '--tranY');
+      this.translationZ = getStyleFloat(style, '--tranZ');
       element.setTranslation(
-          getStyleFloat(style, '--tranX'), getStyleFloat(style, '--tranY'),
-          getStyleFloat(style, '--tranZ'));
+          this.translationX, this.translationY, this.translationZ);
 
-      this.uiElementId = scene.addElement(element);
+      this.uiElementId = ui.addElement(element);
       this.uiAnimationId = -1;
       this.domElement = domElement;
     }
@@ -109,10 +111,10 @@
       let anim = new api.Animation(this.uiElementId, ANIM_DURATION);
       anim.setTranslation(0, 0, distanceForward);
       if (this.uiAnimationId >= 0) {
-        scene.removeAnimation(this.uiAnimationId);
+        ui.removeAnimation(this.uiAnimationId);
       }
-      this.uiAnimationId = scene.addAnimation(anim);
-      scene.flush();
+      this.uiAnimationId = ui.addAnimation(anim);
+      ui.flush();
     }
 
     onMouseEnter() {
@@ -159,7 +161,7 @@
         let position = new api.UiElement(0, 0, 0, 0);
         position.setVisible(false);
         position.setTranslation(startPosition + i * BUTTON_SPACING, -0.68, -1);
-        let id = scene.addElement(position);
+        let id = ui.addElement(position);
 
         let domId = descriptors[i][0];
         let callback = descriptors[i][1];
@@ -169,12 +171,12 @@
         let update = new api.UiElementUpdate();
         update.setParentId(id);
         update.setVisible(false);
-        scene.updateElement(element.uiElementId, update);
+        ui.updateElement(element.uiElementId, update);
       }
 
       this.reloadUiButton = new DomUiElement('#reload-ui-button');
       this.reloadUiButton.domElement.addEventListener('click', function() {
-        scene.purge();
+        ui.purge();
         api.doAction(api.Action.RELOAD_UI);
       });
 
@@ -184,7 +186,7 @@
       update.setScale(2.2, 2.2, 1);
       update.setTranslation(0, -0.6, 0.3);
       update.setAnchoring(api.XAnchoring.XNONE, api.YAnchoring.YBOTTOM);
-      scene.updateElement(this.reloadUiButton.uiElementId, update);
+      ui.updateElement(this.reloadUiButton.uiElementId, update);
     }
 
     setEnabled(enabled) {
@@ -201,11 +203,11 @@
       for (let i = 0; i < this.buttons.length; i++) {
         let update = new api.UiElementUpdate();
         update.setVisible(this.enabled);
-        scene.updateElement(this.buttons[i].uiElementId, update);
+        ui.updateElement(this.buttons[i].uiElementId, update);
       }
       let update = new api.UiElementUpdate();
       update.setVisible(this.enabled && this.reloadUiEnabled);
-      scene.updateElement(this.reloadUiButton.uiElementId, update);
+      ui.updateElement(this.reloadUiButton.uiElementId, update);
     }
   };
 
@@ -229,7 +231,7 @@
       update.setHitTestable(false);
       update.setVisible(false);
       update.setLockToFieldOfView(true);
-      scene.updateElement(this.webVrSecureWarning.uiElementId, update);
+      ui.updateElement(this.webVrSecureWarning.uiElementId, update);
 
       // Temporary WebVR security warning. This warning is shown in the center
       // of the field of view, for a limited period of time.
@@ -240,7 +242,7 @@
       update.setHitTestable(false);
       update.setVisible(false);
       update.setLockToFieldOfView(true);
-      scene.updateElement(this.transientWarning.uiElementId, update);
+      ui.updateElement(this.transientWarning.uiElementId, update);
     }
 
     setEnabled(enabled) {
@@ -271,46 +273,48 @@
     showOrHideWarnings(visible) {
       let update = new api.UiElementUpdate();
       update.setVisible(visible);
-      scene.updateElement(this.webVrSecureWarning.uiElementId, update);
+      ui.updateElement(this.webVrSecureWarning.uiElementId, update);
       update = new api.UiElementUpdate();
       update.setVisible(visible);
-      scene.updateElement(this.transientWarning.uiElementId, update);
+      ui.updateElement(this.transientWarning.uiElementId, update);
     }
 
     onTransientTimer() {
       let update = new api.UiElementUpdate();
       update.setVisible(false);
-      scene.updateElement(this.transientWarning.uiElementId, update);
+      ui.updateElement(this.transientWarning.uiElementId, update);
       this.secureOriginTimer = null;
-      scene.flush();
+      ui.flush();
     }
   };
 
   class Omnibox {
-    constructor(contentQuadId) {
+    constructor() {
       this.domUiElement = new DomUiElement('#omnibox-container');
       this.enabled = false;
+      this.hidden = false;
       this.loading = false;
       this.loadingProgress = 0;
       this.level = 0;
       this.visibilityTimeout = 0;
       this.visibilityTimer = null;
-      this.visibleAfterTransition = false;
       this.nativeState = {};
 
       // Initially invisible.
       let update = new api.UiElementUpdate();
       update.setVisible(false);
-      scene.updateElement(this.domUiElement.uiElementId, update);
+      ui.updateElement(this.domUiElement.uiElementId, update);
       this.nativeState.visible = false;
 
-      // Pull colors from CSS so that Javascript can set the progress indicator
-      // gradient programmatically.
+      // Pull some CSS properties so that Javascript can reconfigure the omnibox
+      // programmatically.
       let border =
           this.domUiElement.domElement.querySelector('#omnibox-border');
       let style = window.getComputedStyle(border);
       this.statusBarColor = getStyleString(style, '--statusBarColor');
       this.backgroundColor = style.backgroundColor;
+      this.fadeTimeMs = getStyleFloat(style, '--fadeTimeMs');
+      this.fadeYOffset = getStyleFloat(style, '--fadeYOffset');
 
       // Listen to the end of transitions, so that the box can be natively
       // hidden after it finishes hiding itself.
@@ -395,7 +399,7 @@
     }
 
     onAnimationDone(e) {
-      if (e.propertyName == 'opacity' && !this.visibleAfterTransition) {
+      if (e.propertyName == 'opacity' && this.hidden) {
         this.setNativeVisibility(false);
       }
     }
@@ -420,14 +424,24 @@
         indicator.style.background = this.backgroundColor;
       }
 
-      // Make the box fade away if it's disappearing.
-      if (!this.loading && this.visibilityTimeout > 0 &&
-          !this.visibilityTimer) {
-        document.querySelector('#omnibox-border').className = 'hidden';
-        this.visibleAfterTransition = false;
-      } else {
-        document.querySelector('#omnibox-border').className = '';
-        this.visibleAfterTransition = true;
+      let shouldBeHidden =
+          !this.loading && this.visibilityTimeout > 0 && !this.visibilityTimer;
+      if (shouldBeHidden != this.hidden) {
+        // Make the box fade away if it's disappearing.
+        this.hidden = shouldBeHidden;
+        document.querySelector('#omnibox-border').className =
+            this.hidden ? 'hidden' : '';
+
+        // Drop the position as it fades, or raise the position if appearing.
+        let yOffset = this.hidden ? this.fadeYOffset : 0;
+        let animation =
+            new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs);
+        animation.setTranslation(
+            this.domUiElement.translationX,
+            this.domUiElement.translationY + yOffset,
+            this.domUiElement.translationZ);
+        ui.addAnimation(animation);
+        ui.flush();
       }
 
       this.setNativeVisibility(true);
@@ -440,12 +454,12 @@
       this.nativeState.visible = visible;
       let update = new api.UiElementUpdate();
       update.setVisible(visible);
-      scene.updateElement(this.domUiElement.uiElementId, update);
-      scene.flush();
+      ui.updateElement(this.domUiElement.uiElementId, update);
+      ui.flush();
     }
   };
 
-  class SceneManager {
+  class UiManager {
     constructor() {
       this.mode = api.Mode.UNKNOWN;
       this.menuMode = false;
@@ -456,7 +470,7 @@
 
       this.controls = new Controls(contentId);
       this.secureOriginWarnings = new SecureOriginWarnings();
-      this.omnibox = new Omnibox(contentId);
+      this.omnibox = new Omnibox();
     }
 
     setMode(mode, menuMode, fullscreen) {
@@ -497,36 +511,36 @@
   };
 
   function initialize() {
-    sceneManager = new SceneManager();
-    scene.flush();
+    uiManager = new UiManager();
+    ui.flush();
 
     api.domLoaded();
   }
 
   function command(dict) {
     if ('mode' in dict) {
-      sceneManager.setMode(dict['mode'], dict['menuMode'], dict['fullscreen']);
+      uiManager.setMode(dict['mode'], dict['menuMode'], dict['fullscreen']);
     }
     if ('securityLevel' in dict) {
-      sceneManager.setSecurityLevel(dict['securityLevel']);
+      uiManager.setSecurityLevel(dict['securityLevel']);
     }
     if ('webVRSecureOrigin' in dict) {
-      sceneManager.setWebVRSecureOrigin(dict['webVRSecureOrigin']);
+      uiManager.setWebVRSecureOrigin(dict['webVRSecureOrigin']);
     }
     if ('enableReloadUi' in dict) {
-      sceneManager.setReloadUiEnabled(dict['enableReloadUi']);
+      uiManager.setReloadUiEnabled(dict['enableReloadUi']);
     }
     if ('url' in dict) {
       let url = dict['url'];
-      sceneManager.omnibox.setURL(url['host'], url['path']);
+      uiManager.omnibox.setURL(url['host'], url['path']);
     }
     if ('loading' in dict) {
-      sceneManager.omnibox.setLoading(dict['loading']);
+      uiManager.omnibox.setLoading(dict['loading']);
     }
     if ('loadingProgress' in dict) {
-      sceneManager.omnibox.setLoadingProgress(dict['loadingProgress']);
+      uiManager.omnibox.setLoadingProgress(dict['loadingProgress']);
     }
-    scene.flush();
+    ui.flush();
   }
 
   return {
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
index 877a8ea5..967de17 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui_api.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var api = new Object();
+var api = {};
 
 /**
  * Enumeration of scene update commands.
diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
index d3a1f905..00182e1 100644
--- a/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
+++ b/chrome/browser/resources/vr_shell/vr_shell_ui_scene.js
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var ui = new Object();
+var scene = {};
 
 /**
- * The scene class assists in managing element and animations in the scene.
- * It allows scene update commands to be queued in batches, and manages
- * allocation of element and animation IDs.
+ * The scene class assists in managing element and animations in the UI.  It
+ * allows UI update API commands to be queued in batches, and manages allocation
+ * of element and animation IDs.
  *
  * Examples:
  *
- * var scene = new ui.Scene();
+ * var ui = new scene.Scene();
  *
  * // Add an element.
  * var el = new api.UiElement(100, 200, 50, 50);
@@ -24,25 +24,25 @@
  * // Place it just below the content quad edge.
  * el.setTranslation(0, -0.2, 0.0);
  *
- * // Add it to the scene.
- * var buttonId = scene.addElement(el);
- * scene.flush();
+ * // Add it to the ui.
+ * var buttonId = ui.addElement(el);
+ * ui.flush();
  *
  * // Make the button twice as big.
  * var update = new api.UiElementUpdate();
  * update.setSize(bunttonWidth * 2, buttonHeight * 2);
- * scene.updateElement(buttonId, update);
- * scene.flush();
+ * ui.updateElement(buttonId, update);
+ * ui.flush();
  *
  * // Animate the button size back to its original size, over 250 ms.
  * var resize = new api.Animation(buttonId, 250);
  * resize.setSize(buttonWidth, buttonHeight);
- * scene.addAnimation(resize);
- * scene.flush();
+ * ui.addAnimation(resize);
+ * ui.flush();
  *
  * @struct
  */
-ui.Scene = class {
+scene.Scene = class {
   constructor() {
     /** @private {number} */
     this.idIndex = 1;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 570b6d31..7d361a70 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1417,6 +1417,7 @@
       "//ash/common/strings",
       "//ash/public/cpp",
       "//ash/public/interfaces",
+      "//ash/resources/vector_icons",
       "//components/session_manager/core",
       "//components/user_manager",
       "//services/ui/public/cpp",
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
index cda8e1d..8788a45 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -156,8 +156,10 @@
 AppShortcutLauncherItemController::GetApplicationList(int event_flags) {
   ChromeLauncherAppMenuItems items;
   // Add the application name to the menu.
+  base::string16 app_title = LauncherControllerHelper::GetAppTitle(
+      launcher_controller()->profile(), app_id());
   items.push_back(
-      base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false));
+      base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false));
 
   std::vector<content::WebContents*> content_list = GetRunningApplications();
 
@@ -216,11 +218,6 @@
   return Activate(ash::LAUNCH_FROM_UNKNOWN);
 }
 
-base::string16 AppShortcutLauncherItemController::GetTitle() {
-  return LauncherControllerHelper::GetAppTitle(launcher_controller()->profile(),
-                                               app_id());
-}
-
 ash::ShelfMenuModel* AppShortcutLauncherItemController::CreateApplicationMenu(
     int event_flags) {
   return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
index 5bbccc6..7ba7958c 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -48,7 +48,6 @@
   ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
index 82ee61f76..fa22849f 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc
@@ -110,8 +110,11 @@
 ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList(
     int event_flags) {
   ChromeLauncherAppMenuItems items;
+  // Add the application name to the menu.
+  base::string16 app_title = LauncherControllerHelper::GetAppTitle(
+      launcher_controller()->profile(), app_id());
   items.push_back(
-      base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false));
+      base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false));
   return items;
 }
 
@@ -132,11 +135,6 @@
   }
 }
 
-base::string16 AppWindowLauncherItemController::GetTitle() {
-  return LauncherControllerHelper::GetAppTitle(launcher_controller()->profile(),
-                                               app_id());
-}
-
 void AppWindowLauncherItemController::OnWindowPropertyChanged(
     aura::Window* window,
     const void* key,
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
index 106539f3..6f2b7df 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h
@@ -50,7 +50,6 @@
   ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   void Close() override;
 
   // aura::WindowObserver overrides:
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
index 7cb1bd8..2890ada 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.cc
@@ -37,20 +37,6 @@
   return ash::ShelfItemDelegate::kNoAction;
 }
 
-base::string16 ArcAppDeferredLauncherItemController::GetTitle() {
-  ArcAppListPrefs* arc_prefs =
-      ArcAppListPrefs::Get(launcher_controller()->profile());
-  DCHECK(arc_prefs);
-  std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = arc_prefs->GetApp(
-      ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id()));
-  if (!app_info) {
-    NOTREACHED();
-    return base::string16();
-  }
-
-  return base::UTF8ToUTF16(app_info->name);
-}
-
 ash::ShelfMenuModel*
 ArcAppDeferredLauncherItemController::CreateApplicationMenu(int event_flags) {
   return nullptr;
diff --git a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
index f8530fe..ea33aa1 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_item_controller.h
@@ -35,7 +35,6 @@
   // ash::ShelfItemDelegate
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index 422d2383..580bf05 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
@@ -305,7 +306,10 @@
   const std::string app_id = GetTestApp1Id(kTestAppPackage);
   if (is_pinned()) {
     shelf_delegate()->PinAppWithID(app_id);
-    EXPECT_TRUE(shelf_delegate()->GetShelfIDForAppID(app_id));
+    const ash::ShelfID shelf_id = shelf_delegate()->GetShelfIDForAppID(app_id);
+    EXPECT_TRUE(shelf_id);
+    const ash::ShelfItem* item = chrome_controller()->GetItem(shelf_id);
+    EXPECT_EQ(base::UTF8ToUTF16(kTestAppName), item->title);
   } else {
     EXPECT_FALSE(shelf_delegate()->GetShelfIDForAppID(app_id));
   }
@@ -328,7 +332,10 @@
 
   // Launching non-ready Arc app creates item on shelf and spinning animation.
   arc::LaunchApp(profile(), app_id, ui::EF_LEFT_MOUSE_BUTTON);
-  EXPECT_TRUE(shelf_delegate()->GetShelfIDForAppID(app_id));
+  const ash::ShelfID shelf_id = shelf_delegate()->GetShelfIDForAppID(app_id);
+  EXPECT_TRUE(shelf_id);
+  const ash::ShelfItem* item = chrome_controller()->GetItem(shelf_id);
+  EXPECT_EQ(base::UTF8ToUTF16(kTestAppName), item->title);
   AppAnimatedWaiter(app_id).Wait();
 
   switch (test_action()) {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
index 88cf6a5..6e3d940 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
+#include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
 #include "ui/aura/window.h"
 #include "ui/base/base_window.h"
 
@@ -49,20 +50,6 @@
   }
 }
 
-base::string16 ArcAppWindowLauncherItemController::GetTitle() {
-  ArcAppListPrefs* arc_prefs =
-      ArcAppListPrefs::Get(launcher_controller()->profile());
-  DCHECK(arc_prefs);
-  std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = arc_prefs->GetApp(
-      ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id()));
-  if (!app_info) {
-    NOTREACHED();
-    return base::string16();
-  }
-
-  return base::UTF8ToUTF16(app_info->name);
-}
-
 ash::ShelfMenuModel* ArcAppWindowLauncherItemController::CreateApplicationMenu(
     int event_flags) {
   return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
@@ -72,6 +59,8 @@
 ArcAppWindowLauncherItemController::GetApplicationList(int event_flags) {
   ChromeLauncherAppMenuItems items =
       AppWindowLauncherItemController::GetApplicationList(event_flags);
+  base::string16 app_title = LauncherControllerHelper::GetAppTitle(
+      launcher_controller()->profile(), app_id());
   for (auto it = windows().begin(); it != windows().end(); ++it) {
     // TODO(khmel): resolve correct icon here.
     size_t i = std::distance(windows().begin(), it);
@@ -79,7 +68,7 @@
     aura::Window* window = (*it)->GetNativeWindow();
     items.push_back(base::MakeUnique<ChromeLauncherAppMenuItemV2App>(
         ((window && !window->GetTitle().empty()) ? window->GetTitle()
-                                                 : GetTitle()),
+                                                 : app_title),
         &image, app_id(), launcher_controller(), i,
         i == 0 /* has_leading_separator */));
   }
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h
index c81ebc5..61bb3774e 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h
@@ -22,7 +22,6 @@
   ~ArcAppWindowLauncherItemController() override;
 
   // LauncherItemController overrides:
-  base::string16 GetTitle() override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
   ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index d8a7f541..8f541ef 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -170,8 +170,9 @@
   ChromeLauncherAppMenuItems items;
   bool found_tabbed_browser = false;
   // Add the application name to the menu.
+  base::string16 app_title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
   items.push_back(
-      base::MakeUnique<ChromeLauncherAppMenuItem>(GetTitle(), nullptr, false));
+      base::MakeUnique<ChromeLauncherAppMenuItem>(app_title, nullptr, false));
   for (auto* browser : GetListOfActiveBrowsers()) {
     TabStripModel* tab_strip = browser->tab_strip_model();
     if (tab_strip->active_index() == -1)
@@ -223,10 +224,6 @@
   return Activate(ash::LAUNCH_FROM_UNKNOWN);
 }
 
-base::string16 BrowserShortcutLauncherItemController::GetTitle() {
-  return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
-}
-
 ash::ShelfMenuModel*
 BrowserShortcutLauncherItemController::CreateApplicationMenu(int event_flags) {
   return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index f281de66..2b77cd06 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -50,7 +50,6 @@
   ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override;
   ash::ShelfItemDelegate::PerformedAction ItemSelected(
       const ui::Event& event) override;
-  base::string16 GetTitle() override;
   ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override;
   void Close() override;
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
index 045b01a9..a010ecdc 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -11,6 +11,7 @@
 #include "ash/common/multi_profile_uma.h"
 #include "ash/common/shelf/shelf_model.h"
 #include "ash/common/shelf/wm_shelf.h"
+#include "ash/common/strings/grit/ash_strings.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
 #include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
@@ -67,6 +68,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/favicon/content/content_favicon_driver.h"
@@ -1279,6 +1281,7 @@
   item.type = shelf_item_type;
   item.app_id = app_id;
   item.image = extensions::util::GetDefaultAppIcon();
+  item.title = LauncherControllerHelper::GetAppTitle(profile(), app_id);
 
   ash::ShelfItemStatus new_state = GetAppState(app_id);
   if (new_state != ash::STATUS_CLOSED)
@@ -1303,6 +1306,7 @@
   browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT;
   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
   browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
+  browser_shortcut.title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
   ash::ShelfID id = model_->next_id();
   model_->AddAt(0, browser_shortcut);
   id_to_item_controller_map_[id] =
@@ -1445,10 +1449,19 @@
 // AppSyncUIStateObserver:
 
 void ChromeLauncherControllerImpl::OnAppSyncUIStatusChanged() {
-  if (app_sync_ui_state_->status() == AppSyncUIState::STATUS_SYNCING)
-    model_->set_status(ash::ShelfModel::STATUS_LOADING);
-  else
-    model_->set_status(ash::ShelfModel::STATUS_NORMAL);
+  // Update the app list button title to reflect the syncing status.
+  base::string16 title = l10n_util::GetStringUTF16(
+      app_sync_ui_state_->status() == AppSyncUIState::STATUS_SYNCING
+          ? IDS_ASH_SHELF_APP_LIST_LAUNCHER_SYNCING_TITLE
+          : IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE);
+
+  const int app_list_index = model_->GetItemIndexForType(ash::TYPE_APP_LIST);
+  DCHECK_GE(app_list_index, 0);
+  ash::ShelfItem item = model_->items()[app_list_index];
+  if (item.title != title) {
+    item.title = title;
+    model_->Set(app_list_index, item);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
index c24ec796..c0920ce6 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_unittest.cc
@@ -267,7 +267,6 @@
       const ui::Event& event) override {
     return kExistingWindowActivated;
   }
-  base::string16 GetTitle() override { return base::string16(); }
   ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override {
     ChromeLauncherAppMenuItems items;
     items.push_back(base::MakeUnique<ChromeLauncherAppMenuItem>(
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
index 06423c8c..6efa7f3 100644
--- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
@@ -103,25 +104,25 @@
 base::string16 LauncherControllerHelper::GetAppTitle(
     Profile* profile,
     const std::string& app_id) {
-  base::string16 title;
   if (app_id.empty())
-    return title;
+    return base::string16();
 
-  // Get title if the app is an Arc app.
+  // Get the title if the app is an Arc app.
   ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile);
-  if (arc_prefs && arc_prefs->IsRegistered(app_id)) {
+  const std::string arc_app_id =
+      ArcAppWindowLauncherController::GetArcAppIdFromShelfAppId(app_id);
+  if (arc_prefs && arc_prefs->IsRegistered(arc_app_id)) {
     std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
-        arc_prefs->GetApp(app_id);
+        arc_prefs->GetApp(arc_app_id);
     DCHECK(app_info.get());
     if (app_info)
-      title = base::UTF8ToUTF16(app_info->name);
-    return title;
+      return base::UTF8ToUTF16(app_info->name);
   }
 
   const extensions::Extension* extension = GetExtensionByID(profile, app_id);
   if (extension)
-    title = base::UTF8ToUTF16(extension->name());
-  return title;
+    return base::UTF8ToUTF16(extension->name());
+  return base::string16();
 }
 
 std::string LauncherControllerHelper::GetAppID(content::WebContents* tab) {
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc
index c3aaac70..a069c99 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -50,12 +50,23 @@
     PrefService* local_state = g_browser_process->local_state();
     bool has_seen_win10_promo =
         local_state && local_state->GetBoolean(prefs::kHasSeenWin10PromoPage);
+    // The set default browser operation can be disabled by the browser
+    // distribution (e.g. SxS Canary), or by enterprise policy. In these cases,
+    // the Win 10 promo page should not be displayed.
+    bool disabled_by_enterprise_policy =
+        local_state &&
+        local_state->IsManagedPreference(
+            prefs::kDefaultBrowserSettingEnabled) &&
+        !local_state->GetBoolean(prefs::kDefaultBrowserSettingEnabled);
+    bool set_default_browser_allowed =
+        !disabled_by_enterprise_policy &&
+        shell_integration::CanSetAsDefaultBrowser();
     bool is_default_browser =
         g_browser_process->CachedDefaultWebClientState() ==
         shell_integration::IS_DEFAULT;
-    return CheckWin10OnboardingTabPolicy(is_first_run, has_seen_welcome_page,
-                                         has_seen_win10_promo, is_signed_in,
-                                         is_default_browser);
+    return CheckWin10OnboardingTabPolicy(
+        is_first_run, has_seen_welcome_page, has_seen_win10_promo, is_signed_in,
+        set_default_browser_allowed, is_default_browser);
   }
 #endif  // defined(OS_WIN)
 
@@ -135,12 +146,15 @@
     bool has_seen_welcome_page,
     bool has_seen_win10_promo,
     bool is_signed_in,
+    bool set_default_browser_allowed,
     bool is_default_browser) {
   StartupTabs tabs;
-  if (!has_seen_win10_promo && !is_default_browser)
+  if (set_default_browser_allowed && !has_seen_win10_promo &&
+      !is_default_browser) {
     tabs.emplace_back(GetWin10WelcomePageUrl(!is_first_run), false);
-  else if (!has_seen_welcome_page && !is_signed_in)
+  } else if (!has_seen_welcome_page && !is_signed_in) {
     tabs.emplace_back(GetWelcomePageUrl(!is_first_run), false);
+  }
   return tabs;
 }
 #endif
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h
index 633ee02..96004fea 100644
--- a/chrome/browser/ui/startup/startup_tab_provider.h
+++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -68,11 +68,13 @@
 #if defined(OS_WIN)
   // Determines which tabs should be shown according to onboarding/first run
   // policy, including promo content specific to Windows 10.
-  static StartupTabs CheckWin10OnboardingTabPolicy(bool is_first_run,
-                                                   bool has_seen_welcome_page,
-                                                   bool has_seen_win10_promo,
-                                                   bool is_signed_in,
-                                                   bool is_default_browser);
+  static StartupTabs CheckWin10OnboardingTabPolicy(
+      bool is_first_run,
+      bool has_seen_welcome_page,
+      bool has_seen_win10_promo,
+      bool is_signed_in,
+      bool set_default_browser_allowed,
+      bool is_default_browser);
 #endif
 
   // Processes first run URLs specified in Master Preferences file, replacing
diff --git a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
index 226f0b79b..abd61979 100644
--- a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
+++ b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
@@ -46,7 +46,7 @@
   // Show Win 10 Welcome page if it has not been seen, but the standard page
   // has.
   StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, true, false, false, false);
+      true, true, false, false, true, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(false),
@@ -56,7 +56,7 @@
   // Show standard Welcome page if the Win 10 Welcome page has been seen, but
   // the standard page has not.
   output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, false, true, false, false);
+      true, false, true, false, true, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url);
@@ -65,7 +65,7 @@
   // If neither page has been seen, the Win 10 Welcome page takes precedence
   // this launch.
   output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, false, false, false, false);
+      true, false, false, false, true, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(false),
@@ -77,7 +77,7 @@
   // Show a variant of the Win 10 Welcome page after first run, if it has not
   // been seen.
   StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      false, false, false, false, false);
+      false, false, false, false, true, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWin10WelcomePageUrl(true),
@@ -87,7 +87,7 @@
   // Show a variant of the standard Welcome page after first run, if the Win 10
   // Welcome page has already been seen but the standard has not.
   output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      false, false, true, false, false);
+      false, false, true, false, true, false);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(true), output[0].url);
@@ -97,14 +97,14 @@
 TEST(StartupTabProviderTest, CheckWin10OnboardingTabPolicy_Negative) {
   // Do not show either page if it has already been shown.
   StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, true, true, false, false);
+      true, true, true, false, true, false);
 
   EXPECT_TRUE(output.empty());
 
   // If Chrome is already the default browser, don't show the Win 10 Welcome
   // page, and don't preempt the standard Welcome page.
   output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, false, false, false, true);
+      true, false, false, false, true, true);
 
   ASSERT_EQ(1U, output.size());
   EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url);
@@ -112,10 +112,28 @@
 
   // If the user is signed in, block showing the standard Welcome page.
   output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
-      true, false, true, true, false);
+      true, false, true, true, true, false);
 
   EXPECT_TRUE(output.empty());
 }
+
+TEST(StartupTabProviderTest,
+     CheckWin10OnboardingTabPolicy_SetDefaultBrowserNotAllowed) {
+  // Skip the Win 10 promo if setting the default browser is not allowed.
+  StartupTabs output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
+      true, false, false, false, false, false);
+
+  ASSERT_EQ(1U, output.size());
+  EXPECT_EQ(StartupTabProviderImpl::GetWelcomePageUrl(false), output[0].url);
+
+  // After first run, no onboarding content is displayed when setting the
+  // default browser is not allowed.
+  output = StartupTabProviderImpl::CheckWin10OnboardingTabPolicy(
+      true, true, false, false, false, false);
+
+  EXPECT_TRUE(output.empty());
+}
+
 #endif
 
 TEST(StartupTabProviderTest, CheckMasterPrefsTabPolicy) {
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
index 45d2a559..c61cb3f 100644
--- a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
@@ -7,6 +7,7 @@
 #include "ash/common/ash_layout_constants.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/frame/header_painter_util.h"
+#include "ash/resources/vector_icons/vector_icons.h"
 #include "base/logging.h"  // DCHECK
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
@@ -22,7 +23,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gfx/vector_icons_public.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -285,29 +285,27 @@
 }
 
 void BrowserHeaderPainterAsh::UpdateCaptionButtons() {
-  caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_MINIMIZE,
-      gfx::VectorIconId::WINDOW_CONTROL_MINIMIZE);
-  caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_CLOSE, gfx::VectorIconId::WINDOW_CONTROL_CLOSE);
+  caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_MINIMIZE,
+                                            ash::kWindowControlMinimizeIcon);
+  caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_CLOSE,
+                                            ash::kWindowControlCloseIcon);
   caption_button_container_->SetButtonImage(
       ash::CAPTION_BUTTON_ICON_LEFT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_LEFT_SNAPPED);
+      ash::kWindowControlLeftSnappedIcon);
   caption_button_container_->SetButtonImage(
       ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
-      gfx::VectorIconId::WINDOW_CONTROL_RIGHT_SNAPPED);
+      ash::kWindowControlRightSnappedIcon);
 
-  gfx::VectorIconId size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_MAXIMIZE;
+  const gfx::VectorIcon* size_icon = &ash::kWindowControlMaximizeIcon;
   gfx::Size button_size(
       GetAshLayoutSize(AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON));
   if (frame_->IsMaximized() || frame_->IsFullscreen()) {
-    size_icon_id = gfx::VectorIconId::WINDOW_CONTROL_RESTORE;
+    size_icon = &ash::kWindowControlRestoreIcon;
     button_size =
         GetAshLayoutSize(AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON);
   }
   caption_button_container_->SetButtonImage(
-      ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE,
-      size_icon_id);
+      ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon);
   caption_button_container_->SetButtonSize(button_size);
 }
 
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
index 871efc0..3e5cd88a 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -16,7 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/string_split.h"
-#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/printing/pwg_raster_converter.h"
 #include "components/cloud_devices/common/cloud_device_description.h"
 #include "components/cloud_devices/common/printer_description.h"
@@ -69,10 +69,9 @@
 
 // Callback to PWG raster conversion.
 // Posts a task to update print job with info about file containing converted
-// PWG raster data. The task is posted to |slow_task_runner|.
+// PWG raster data.
 void UpdateJobFileInfo(
     std::unique_ptr<extensions::PrinterProviderPrintJob> job,
-    const scoped_refptr<base::TaskRunner>& slow_task_runner,
     const ExtensionPrinterHandler::PrintJobCallback& callback,
     bool success,
     const base::FilePath& pwg_file_path) {
@@ -81,8 +80,11 @@
     return;
   }
 
-  base::PostTaskAndReplyWithResult(
-      slow_task_runner.get(), FROM_HERE,
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, base::TaskTraits()
+                     .WithShutdownBehavior(
+                         base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+                     .MayBlock(),
       base::Bind(&UpdateJobFileInfoOnWorkerThread, pwg_file_path,
                  base::Passed(&job)),
       callback);
@@ -122,12 +124,8 @@
 }  // namespace
 
 ExtensionPrinterHandler::ExtensionPrinterHandler(
-    content::BrowserContext* browser_context,
-    const scoped_refptr<base::TaskRunner>& slow_task_runner)
-    : browser_context_(browser_context),
-      slow_task_runner_(slow_task_runner),
-      weak_ptr_factory_(this) {
-}
+    content::BrowserContext* browser_context)
+    : browser_context_(browser_context), weak_ptr_factory_(this) {}
 
 ExtensionPrinterHandler::~ExtensionPrinterHandler() {
 }
@@ -274,8 +272,7 @@
       data.get(),
       PWGRasterConverter::GetConversionSettings(printer_description, page_size),
       PWGRasterConverter::GetBitmapSettings(printer_description, ticket),
-      base::Bind(&UpdateJobFileInfo, base::Passed(&job), slow_task_runner_,
-                 callback));
+      base::Bind(&UpdateJobFileInfo, base::Passed(&job), callback));
 }
 
 void ExtensionPrinterHandler::DispatchPrintJob(
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
index 3a0c9f5..183d172 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
@@ -19,7 +19,6 @@
 class DictionaryValue;
 class ListValue;
 class RefCountedMemory;
-class TaskRunner;
 }
 
 namespace content {
@@ -49,9 +48,7 @@
   using PrintJobCallback = base::Callback<void(
       std::unique_ptr<extensions::PrinterProviderPrintJob>)>;
 
-  ExtensionPrinterHandler(
-      content::BrowserContext* browser_context,
-      const scoped_refptr<base::TaskRunner>& slow_task_runner);
+  explicit ExtensionPrinterHandler(content::BrowserContext* browser_context);
 
   ~ExtensionPrinterHandler() override;
 
@@ -122,8 +119,6 @@
   std::unique_ptr<printing::PWGRasterConverter> pwg_raster_converter_;
   int pending_enumeration_count_ = 0;
 
-  scoped_refptr<base::TaskRunner> slow_task_runner_;
-
   base::WeakPtrFactory<ExtensionPrinterHandler> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionPrinterHandler);
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
index 64a80c50..56c50d1 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -22,7 +22,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/values_test_util.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/test_extension_environment.h"
 #include "chrome/browser/printing/pwg_raster_converter.h"
@@ -462,8 +461,8 @@
   void SetUp() override {
     extensions::PrinterProviderAPIFactory::GetInstance()->SetTestingFactory(
         env_.profile(), &BuildTestingPrinterProviderAPI);
-    extension_printer_handler_.reset(new ExtensionPrinterHandler(
-        env_.profile(), base::ThreadTaskRunnerHandle::Get()));
+    extension_printer_handler_.reset(
+        new ExtensionPrinterHandler(env_.profile()));
 
     pwg_raster_converter_ = new FakePWGRasterConverter();
     extension_printer_handler_->SetPWGRasterConverterForTesting(
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chrome/browser/ui/webui/print_preview/printer_handler.cc
index 9e6f3dac..14dad12 100644
--- a/chrome/browser/ui/webui/print_preview/printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/printer_handler.cc
@@ -4,12 +4,11 @@
 
 #include "chrome/browser/ui/webui/print_preview/printer_handler.h"
 
-#include "base/threading/worker_pool.h"
 #include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h"
 
 // static
 std::unique_ptr<PrinterHandler> PrinterHandler::CreateForExtensionPrinters(
     content::BrowserContext* browser_context) {
-  return std::unique_ptr<ExtensionPrinterHandler>(new ExtensionPrinterHandler(
-      browser_context, base::WorkerPool::GetTaskRunner(true)));
+  return std::unique_ptr<ExtensionPrinterHandler>(
+      new ExtensionPrinterHandler(browser_context));
 }
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 17f7a10..dbaaf2b 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -319,11 +319,6 @@
   env->UnSetVar(kEnvProgramFilesPath);
 }
 
-bool InstallUtil::IsMultiInstall(bool system_install) {
-  ProductState state;
-  return state.Initialize(system_install) && state.is_multi_install();
-}
-
 bool CheckIsChromeSxSProcess() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   CHECK(command_line);
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index fb8d7a84..198d3385 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -92,9 +92,6 @@
   // with fresh data.
   static void ResetIsPerUserInstallForTest();
 
-  // Returns true if Chrome at |system_level| is a multi install.
-  static bool IsMultiInstall(bool system_install);
-
   // Returns true if this is running setup process for Chrome SxS (as
   // indicated by the presence of --chrome-sxs on the command line) or if this
   // is running Chrome process from the Chrome SxS installation (as indicated
diff --git a/chrome/installer/util/installation_state.cc b/chrome/installer/util/installation_state.cc
index 271f513..68e548f 100644
--- a/chrome/installer/util/installation_state.cc
+++ b/chrome/installer/util/installation_state.cc
@@ -12,6 +12,7 @@
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/util_constants.h"
 
 namespace installer {
 
@@ -117,7 +118,7 @@
                             &dw_value) == ERROR_SUCCESS) && (dw_value != 0);
     // Multi-install is a legacy option that is read for the sole purpose of
     // migrating clients away from it.
-    multi_install_ = uninstall_command_.HasSwitch(switches::kMultiInstall);
+    multi_install_ = uninstall_command_.HasSwitch("multi-install");
   }
 
   // Read from the ClientStateMedium key.  Values here override those in
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc
index ef58f813..2f7ccb6 100644
--- a/chrome/installer/util/master_preferences.cc
+++ b/chrome/installer/util/master_preferences.cc
@@ -163,12 +163,10 @@
   }
 
   // Strip multi-install from the dictionary, if present. This ensures that any
-  // code that probes the dictionary directly to check for multi-install (rather
-  // than calling is_multi_install()) receives false. The updated dictionary is
-  // not written back to disk.
-  master_dictionary_->Remove(std::string(master_preferences::kDistroDict) +
-                                 '.' + master_preferences::kMultiInstall,
-                             nullptr);
+  // code that probes the dictionary directly to check for multi-install
+  // receives false. The updated dictionary is not written back to disk.
+  master_dictionary_->Remove(
+      std::string(master_preferences::kDistroDict) + ".multi_install", nullptr);
 
   // Cache a pointer to the distribution dictionary. Ignore errors if any.
   master_dictionary_->GetDictionary(installer::master_preferences::kDistroDict,
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h
index 9f1a569..4c570486 100644
--- a/chrome/installer/util/master_preferences.h
+++ b/chrome/installer/util/master_preferences.h
@@ -170,8 +170,6 @@
     return preferences_read_from_file_;
   }
 
-  bool is_multi_install() const { return false; }
-
   // Returns a reference to this MasterPreferences' root dictionary of values.
   const base::DictionaryValue& master_dictionary() const {
     return *master_dictionary_.get();
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc
index e65450b..0af4ab94 100644
--- a/chrome/installer/util/master_preferences_constants.cc
+++ b/chrome/installer/util/master_preferences_constants.cc
@@ -36,7 +36,6 @@
       "suppress_first_run_default_browser_prompt";
   const char kMsi[] = "msi";
   const char kMsiProductId[] = "msi_product_id";
-  const char kMultiInstall[] = "multi_install";
   const char kRequireEula[] = "require_eula";
   const char kSystemLevel[] = "system_level";
   const char kVerboseLogging[] = "verbose_logging";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h
index cb394167..92bbe4b 100644
--- a/chrome/installer/util/master_preferences_constants.h
+++ b/chrome/installer/util/master_preferences_constants.h
@@ -75,8 +75,6 @@
 // String. The MSI Product ID under which the MSI stores its information.  This
 // is used to update the DisplayVersion to match Chrome's version number.
 extern const char kMsiProductId[];
-// Boolean. Support installing multiple products at once.
-extern const char kMultiInstall[];
 // Boolean. Show EULA dialog before install.
 extern const char kRequireEula[];
 // Boolean. Indicates that the first-run 'set-as-default' dialog should not be
diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc
index 8a5a3f8..019ac57 100644
--- a/chrome/installer/util/master_preferences_unittest.cc
+++ b/chrome/installer/util/master_preferences_unittest.cc
@@ -321,23 +321,6 @@
       base::CommandLine::FromString(chrome_cmd.str()));
 
   installer::MasterPreferences pref_chrome(chrome_install);
-
-  EXPECT_FALSE(pref_chrome.is_multi_install());
-}
-
-TEST_F(MasterPreferencesTest, TestMultiInstallIgnoredConfig) {
-  using installer::switches::kMultiInstall;
-  using installer::switches::kChrome;
-
-  std::wstringstream chrome_cmd, cf_cmd, chrome_cf_cmd;
-  chrome_cmd << "setup.exe --" << kMultiInstall << " --" << kChrome;
-
-  base::CommandLine chrome_install(
-      base::CommandLine::FromString(chrome_cmd.str()));
-
-  installer::MasterPreferences pref_chrome(chrome_install);
-
-  EXPECT_FALSE(pref_chrome.is_multi_install());
 }
 
 TEST_F(MasterPreferencesTest, EnforceLegacyCreateAllShortcutsFalse) {
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index e768bf0d2..22a5465 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -8,10 +8,6 @@
 
 namespace switches {
 
-// Install Chrome.
-// Currently this is only required when used in combination with kMultiInstall.
-const char kChrome[] = "chrome";
-
 // Run the installer for Chrome SxS.
 const char kChromeSxS[] = "chrome-sxs";
 
@@ -83,10 +79,6 @@
 // Tells installer to expect to be run as a subsidiary to an MSI.
 const char kMsi[] = "msi";
 
-// Tells installer to install multiple products specified on the command line.
-// (e.g. Chrome Frame, Chrome)
-const char kMultiInstall[] = "multi-install";
-
 // Useful only when used with --update-setup-exe, otherwise ignored. It
 // specifies the full path where updated setup.exe will be stored.
 const char kNewSetupExe[] = "new-setup-exe";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index 4e9e5da..4d8e4521 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -144,7 +144,6 @@
 
 namespace switches {
 
-extern const char kChrome[];
 extern const char kChromeSxS[];
 extern const char kConfigureUserSettings[];
 extern const char kCriticalUpdateVersion[];
@@ -162,7 +161,6 @@
 extern const char kLogFile[];
 extern const char kMakeChromeDefault[];
 extern const char kMsi[];
-extern const char kMultiInstall[];
 extern const char kNewSetupExe[];
 extern const char kOnOsUpgrade[];
 extern const char kPreviousVersion[];
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html
deleted file mode 100644
index 39c42a3..0000000
--- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/guest.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!doctype html>
-<!--
- * Copyright (c) 2014 The Chromium Authors. All rights reserved.  Use of this
- * source code is governed by a BSD-style license that can be found in the
- * LICENSE file.
--->
-<html>
-<head>
-  <title>ChromeVox test title</title>
-</head>
-<body>
-  <div>Some text</div>
-</body>
-</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html
deleted file mode 100644
index c4da227..0000000
--- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html>
-<!--
- * Copyright (c) 2014 The Chromium Authors. All rights reserved.  Use of this
- * source code is governed by a BSD-style license that can be found in the
- * LICENSE file.
--->
-<html>
-<body>
-  <div id="webview-tag-container"></div>
-  <script src="main.js"></script>
-</body>
-</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js
deleted file mode 100644
index de92c73b..0000000
--- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/main.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-var startTest = function() {
-  chrome.test.sendMessage('guest-loaded');
-};
-
-chrome.test.getConfig(function(config) {
-  var guestURL = 'http://localhost:' + config.testServer.port +
-      '/extensions/platform_apps/web_view/chromevox_injection/guest.html';
-  document.querySelector('#webview-tag-container').innerHTML =
-      '<webview style="width: 10px; height: 10px; margin: 0; padding: 0;"' +
-      ' src="' + guestURL + '"' +
-      '></webview>';
-  startTest();
-});
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json
deleted file mode 100644
index fdbcce1f..0000000
--- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/manifest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "<webview> ChromeVox injection test.",
-  "version": "1",
-  "permissions": [
-    "webview"
-  ],
-  "app": {
-    "background": {
-      "scripts": ["test.js"]
-    }
-  }
-}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js b/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js
deleted file mode 100644
index a80d274..0000000
--- a/chrome/test/data/extensions/platform_apps/web_view/chromevox_injection/test.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-chrome.app.runtime.onLaunched.addListener(function() {
-  chrome.app.window.create('main.html', {}, function () {});
-});
diff --git a/chrome/test/data/webui/settings/android_apps_page_test.js b/chrome/test/data/webui/settings/android_apps_page_test.js
index 52d8bc41..95a80c2 100644
--- a/chrome/test/data/webui/settings/android_apps_page_test.js
+++ b/chrome/test/data/webui/settings/android_apps_page_test.js
@@ -61,17 +61,17 @@
           cr.webUIListenerCallback(
               'android-apps-info-update', {appReady: false});
           Polymer.dom.flush();
-          var checkbox = androidAppsPage.$$('#enabledCheckbox');
-          assertTrue(!!checkbox);
-          assertFalse(checkbox.disabled);
-          assertFalse(checkbox.checked);
+          var control = androidAppsPage.$$('#enabled');
+          assertTrue(!!control);
+          assertFalse(control.disabled);
+          assertFalse(control.checked);
           var managed = androidAppsPage.$$('#manageApps');
           assertTrue(!!managed);
           assertTrue(managed.hidden);
 
-          MockInteractions.tap(checkbox.$.checkbox);
+          MockInteractions.tap(control.$.control);
           Polymer.dom.flush();
-          assertTrue(checkbox.checked);
+          assertTrue(control.checked);
         });
   });
 
@@ -88,15 +88,15 @@
           cr.webUIListenerCallback(
               'android-apps-info-update', {appReady: true});
           Polymer.dom.flush();
-          var checkbox = androidAppsPage.$$('#enabledCheckbox');
-          assertTrue(!!checkbox);
-          assertFalse(checkbox.disabled);
-          assertTrue(checkbox.checked);
+          var control = androidAppsPage.$$('#enabled');
+          assertTrue(!!control);
+          assertFalse(control.disabled);
+          assertTrue(control.checked);
           var managed = androidAppsPage.$$('#manageApps');
           assertTrue(!!managed);
           assertFalse(managed.hidden);
 
-          MockInteractions.tap(checkbox.$.checkbox);
+          MockInteractions.tap(control.$.control);
           cr.webUIListenerCallback(
               'android-apps-info-update', {appReady: false});
           Polymer.dom.flush();
@@ -108,7 +108,7 @@
           assertTrue(!!actionButton);
           MockInteractions.tap(actionButton);
           Polymer.dom.flush();
-          assertFalse(checkbox.checked);
+          assertFalse(control.checked);
           assertTrue(managed.hidden);
         });
   });
diff --git a/chrome/test/data/webui/settings/date_time_page_tests.js b/chrome/test/data/webui/settings/date_time_page_tests.js
index c88bc51..7cf96a7 100644
--- a/chrome/test/data/webui/settings/date_time_page_tests.js
+++ b/chrome/test/data/webui/settings/date_time_page_tests.js
@@ -112,7 +112,7 @@
 
     function verifyAutoDetectSetting(autoDetect) {
       assertEquals(autoDetect, dateTime.$$('settings-dropdown-menu').disabled);
-      assertEquals(autoDetect, dateTime.$.timeZoneAutoDetectCheckbox.checked);
+      assertEquals(autoDetect, dateTime.$.timeZoneAutoDetect.checked);
     }
 
     function verifyPolicy(policy) {
@@ -128,7 +128,7 @@
           assertEquals(0, indicator.clientHeight);
       }
 
-      assertEquals(policy, dateTime.$.timeZoneAutoDetectCheckbox.disabled);
+      assertEquals(policy, dateTime.$.timeZoneAutoDetect.disabled);
     }
 
     function verifyTimeZonesPopulated(populated) {
@@ -151,7 +151,7 @@
       verifyPolicy(false);
 
       // Disable auto-detect.
-      MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox);
+      MockInteractions.tap(dateTime.$.timeZoneAutoDetect);
       verifyAutoDetectSetting(false);
       assertTrue(getTimeZonesCalled);
 
@@ -176,7 +176,7 @@
         verifyTimeZonesPopulated(true);
 
         // Enable auto-detect.
-        MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox);
+        MockInteractions.tap(dateTime.$.timeZoneAutoDetect);
         verifyAutoDetectSetting(true);
         done();
       });
@@ -195,7 +195,7 @@
       verifyPolicy(true);
 
       // Cannot disable auto-detect.
-      MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox);
+      MockInteractions.tap(dateTime.$.timeZoneAutoDetect);
       verifyAutoDetectSetting(true);
       assertFalse(getTimeZonesCalled);
 
@@ -230,7 +230,7 @@
         verifyPolicy(false);
 
         // User can disable auto-detect.
-        MockInteractions.tap(dateTime.$.timeZoneAutoDetectCheckbox);
+        MockInteractions.tap(dateTime.$.timeZoneAutoDetect);
         verifyAutoDetectSetting(false);
         done();
       });
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js
index c6b6a9b..477d274 100644
--- a/chrome/test/data/webui/settings/device_page_tests.js
+++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -274,7 +274,7 @@
       test('mouse', function() {
         expectLT(0, pointersPage.$.mouse.offsetHeight);
 
-        expectFalse(pointersPage.$$('#mouse settings-checkbox').checked);
+        expectFalse(pointersPage.$$('#mouse settings-toggle-button').checked);
 
         var slider = assert(pointersPage.$$('#mouse cr-slider'));
         expectEquals(4, slider.value);
diff --git a/chrome/test/data/webui/settings/metrics_reporting_tests.js b/chrome/test/data/webui/settings/metrics_reporting_tests.js
index 37ff7d68..de2f12c 100644
--- a/chrome/test/data/webui/settings/metrics_reporting_tests.js
+++ b/chrome/test/data/webui/settings/metrics_reporting_tests.js
@@ -22,8 +22,8 @@
     return testBrowserProxy.whenCalled('getMetricsReporting').then(function() {
       Polymer.dom.flush();
 
-      var checkbox = page.$.metricsReportingCheckbox;
-      assertEquals(testBrowserProxy.metricsReporting.enabled, checkbox.checked);
+      var control = page.$.metricsReportingControl;
+      assertEquals(testBrowserProxy.metricsReporting.enabled, control.checked);
       var indicatorVisible = !!page.$$('#indicator');
       assertEquals(testBrowserProxy.metricsReporting.managed, indicatorVisible);
 
@@ -34,13 +34,13 @@
       cr.webUIListenerCallback('metrics-reporting-change', changedMetrics);
       Polymer.dom.flush();
 
-      assertEquals(changedMetrics.enabled, checkbox.checked);
+      assertEquals(changedMetrics.enabled, control.checked);
       indicatorVisible = !!page.$$('#indicator');
       assertEquals(changedMetrics.managed, indicatorVisible);
 
       var toggled = !changedMetrics.enabled;
 
-      MockInteractions.tap(checkbox);
+      MockInteractions.tap(control);
       return testBrowserProxy.whenCalled('setMetricsReportingEnabled', toggled);
     });
   });
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js
index c4a0e808..b8cd5c4 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -196,21 +196,21 @@
       });
 
       test('SettingIndividualDatatypes', function() {
-        var syncAllDataTypesCheckbox = syncPage.$.syncAllDataTypesCheckbox;
-        assertFalse(syncAllDataTypesCheckbox.disabled);
-        assertTrue(syncAllDataTypesCheckbox.checked);
+        var syncAllDataTypesControl = syncPage.$.syncAllDataTypesControl;
+        assertFalse(syncAllDataTypesControl.disabled);
+        assertTrue(syncAllDataTypesControl.checked);
 
-        // Assert that all the individual datatype checkboxes are disabled.
-        var datatypeCheckboxes = syncPage
+        // Assert that all the individual datatype controls are disabled.
+        var datatypeControls = syncPage
             .$$('#configure')
-            .querySelectorAll('paper-checkbox.list-item');
-        for (var box of datatypeCheckboxes) {
-          assertTrue(box.disabled);
-          assertTrue(box.checked);
+            .querySelectorAll('.list-item paper-toggle-button');
+        for (var control of datatypeControls) {
+          assertTrue(control.disabled);
+          assertTrue(control.checked);
         }
 
-        // Uncheck the Sync All checkbox.
-        MockInteractions.tap(syncAllDataTypesCheckbox);
+        // Uncheck the Sync All control.
+        MockInteractions.tap(syncAllDataTypesControl);
 
         function verifyPrefs(prefs) {
           var expected = getSyncAllPrefs();
@@ -219,16 +219,16 @@
 
           cr.webUIListenerCallback('sync-prefs-changed', expected);
 
-          // Assert that all the individual datatype checkboxes are enabled.
-          for (var box of datatypeCheckboxes) {
-            assertFalse(box.disabled);
-            assertTrue(box.checked);
+          // Assert that all the individual datatype controls are enabled.
+          for (var control of datatypeControls) {
+            assertFalse(control.disabled);
+            assertTrue(control.checked);
           }
 
           browserProxy.resetResolver('setSyncDatatypes');
 
-          // Test an arbitrarily-selected checkbox (extensions synced checkbox).
-          MockInteractions.tap(datatypeCheckboxes[3]);
+          // Test an arbitrarily-selected control (extensions synced control).
+          MockInteractions.tap(datatypeControls[3]);
           return browserProxy.whenCalled('setSyncDatatypes').then(
               function(prefs) {
                 var expected = getSyncAllPrefs();
@@ -240,30 +240,6 @@
         return browserProxy.whenCalled('setSyncDatatypes').then(verifyPrefs);
       });
 
-      test('ClickingLinkDoesNotChangeCheckboxValue', function() {
-        var syncAllDataTypesCheckbox = syncPage.$.syncAllDataTypesCheckbox;
-
-        // Uncheck the Sync All checkbox.
-        MockInteractions.tap(syncAllDataTypesCheckbox);
-
-        // Make sure the checkbox is enabled and checked.
-        var link = syncPage.$.paymentLearnMore;
-
-        // Suppress opening a new tab, since then the test will continue running
-        // on a background tab (which has throttled timers) and will timeout.
-        link.target = '';
-        link.href = '#';
-
-        assertEquals('PAPER-CHECKBOX', link.parentNode.nodeName);
-        assertFalse(link.parentNode.disabled);
-        assertTrue(link.parentNode.checked);
-
-        MockInteractions.tap(link);
-
-        // The checkbox value should be unchanged after clicking on the link.
-        assertTrue(link.parentNode.checked);
-      });
-
       test('RadioBoxesEnabledWhenUnencrypted', function() {
         // Verify that the encryption radio boxes are enabled.
         assertFalse(encryptWithGoogle.disabled);
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js
index f16097d..5a2f2362 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.js
+++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -260,18 +260,18 @@
             'getSafeBrowsingExtendedReporting').then(function() {
           Polymer.dom.flush();
 
-          // Checkbox starts checked by default
-          var checkbox = page.$.safeBrowsingExtendedReportingCheckbox;
-          assertEquals(true, checkbox.checked);
+          // Control starts checked by default
+          var control = page.$.safeBrowsingExtendedReportingControl;
+          assertEquals(true, control.checked);
 
           // Notification from browser can uncheck the box
           cr.webUIListenerCallback('safe-browsing-extended-reporting-change',
                                    false);
           Polymer.dom.flush();
-          assertEquals(false, checkbox.checked);
+          assertEquals(false, control.checked);
 
           // Tapping on the box will check it again.
-          MockInteractions.tap(checkbox);
+          MockInteractions.tap(control);
           return testBrowserProxy.whenCalled('getSafeBrowsingExtendedReporting',
                                              true);
         });
diff --git a/chrome/test/data/webui/settings/search_page_test.js b/chrome/test/data/webui/settings/search_page_test.js
index c8efd1b5..a8394f17 100644
--- a/chrome/test/data/webui/settings/search_page_test.js
+++ b/chrome/test/data/webui/settings/search_page_test.js
@@ -109,11 +109,11 @@
           assertFalse(browserProxy.hotwordSearchEnabled);
           assertFalse(page.hotwordSearchEnablePref_.value);
 
-          var checkbox = page.$$('#hotwordSearchEnable');
-          assertTrue(!!checkbox);
-          assertFalse(checkbox.disabled);
-          assertFalse(checkbox.checked);
-          MockInteractions.tap(checkbox.$.checkbox);
+          var control = page.$$('#hotwordSearchEnable');
+          assertTrue(!!control);
+          assertFalse(control.disabled);
+          assertFalse(control.checked);
+          MockInteractions.tap(control.$.control);
           Polymer.dom.flush();
           return browserProxy.whenCalled('setHotwordSearchEnabled');
         }).then(function() {
@@ -137,11 +137,11 @@
           assertFalse(page.hotwordInfo_.alwaysOn);
           assertFalse(page.hotwordInfo_.enabled);
 
-          var checkbox = page.$$('#hotwordSearchEnable');
-          assertTrue(!!checkbox);
-          assertFalse(checkbox.disabled);
-          assertFalse(checkbox.checked);
-          MockInteractions.tap(checkbox.$.checkbox);
+          var control = page.$$('#hotwordSearchEnable');
+          assertTrue(!!control);
+          assertFalse(control.disabled);
+          assertFalse(control.checked);
+          MockInteractions.tap(control.$.control);
           Polymer.dom.flush();
           return browserProxy.whenCalled('setHotwordSearchEnabled');
         }).then(function() {
@@ -155,10 +155,10 @@
           Polymer.dom.flush();
           assertTrue(page.googleNowAvailable_);
 
-          var checkbox = page.$$('#googleNowEnable');
-          assertTrue(!!checkbox);
-          assertFalse(checkbox.disabled);
-          assertFalse(checkbox.checked);
+          var control = page.$$('#googleNowEnable');
+          assertTrue(!!control);
+          assertFalse(control.disabled);
+          assertFalse(control.checked);
 
           page.prefs = {
             google_now_launcher: {
@@ -169,8 +169,8 @@
             }
           };
           Polymer.dom.flush();
-          assertFalse(checkbox.disabled);
-          assertTrue(checkbox.checked);
+          assertFalse(control.disabled);
+          assertTrue(control.checked);
         });
       });
     });
diff --git a/chrome/test/data/webui/settings/system_page_tests.js b/chrome/test/data/webui/settings/system_page_tests.js
index a9f2e219..7de7af1 100644
--- a/chrome/test/data/webui/settings/system_page_tests.js
+++ b/chrome/test/data/webui/settings/system_page_tests.js
@@ -66,18 +66,18 @@
     teardown(function() { systemPage.remove(); });
 
     test('restart button', function() {
-      var checkbox = systemPage.$$('#hardware-acceleration settings-checkbox');
-      expectEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP);
+      var control = systemPage.$.hardwareAcceleration;
+      expectEquals(control.checked, HARDWARE_ACCELERATION_AT_STARTUP);
 
       // Restart button should be hidden by default.
-      expectFalse(!!systemPage.$$('#hardware-acceleration paper-button'));
+      expectFalse(!!control.querySelector('paper-button'));
 
       systemPage.set('prefs.hardware_acceleration_mode.enabled.value',
                      !HARDWARE_ACCELERATION_AT_STARTUP);
       Polymer.dom.flush();
-      expectNotEquals(checkbox.checked, HARDWARE_ACCELERATION_AT_STARTUP);
+      expectNotEquals(control.checked, HARDWARE_ACCELERATION_AT_STARTUP);
 
-      var restart = systemPage.$$('#hardware-acceleration paper-button');
+      var restart = control.querySelector('paper-button');
       expectTrue(!!restart);  // The "RESTART" button should be showing now.
 
       MockInteractions.tap(restart);
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 6b997da6..0423c4b 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -193,6 +193,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "arc_service_manager_unittest.cc",
     "arc_session_runner_unittest.cc",
     "bluetooth/arc_bluetooth_bridge_unittest.cc",
     "bluetooth/bluetooth_struct_traits_unittest.cc",
diff --git a/components/arc/arc_service_manager.cc b/components/arc/arc_service_manager.cc
index 73ea36e..f2a81d15 100644
--- a/components/arc/arc_service_manager.cc
+++ b/components/arc/arc_service_manager.cc
@@ -4,8 +4,6 @@
 
 #include "components/arc/arc_service_manager.h"
 
-#include <utility>
-
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/task_runner.h"
@@ -83,9 +81,32 @@
   return arc_bridge_service_.get();
 }
 
-void ArcServiceManager::AddService(std::unique_ptr<ArcService> service) {
+bool ArcServiceManager::AddServiceInternal(
+    const std::string& name,
+    std::unique_ptr<ArcService> service) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  services_.emplace_back(std::move(service));
+  if (!name.empty() && services_.count(name) != 0) {
+    LOG(ERROR) << "Ignoring registration of service with duplicate name: "
+               << name;
+    return false;
+  }
+  services_.insert(std::make_pair(name, std::move(service)));
+  return true;
+}
+
+ArcService* ArcServiceManager::GetNamedServiceInternal(
+    const std::string& name) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (name.empty()) {
+    LOG(ERROR) << "kArcServiceName[] should be a fully-qualified class name.";
+    return nullptr;
+  }
+  auto service = services_.find(name);
+  if (service == services_.end()) {
+    LOG(ERROR) << "Named service " << name << " not found";
+    return nullptr;
+  }
+  return service->second.get();
 }
 
 void ArcServiceManager::AddObserver(Observer* observer) {
diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h
index cf37287..7db5fe7 100644
--- a/components/arc/arc_service_manager.h
+++ b/components/arc/arc_service_manager.h
@@ -6,6 +6,10 @@
 #define COMPONENTS_ARC_ARC_SERVICE_MANAGER_H_
 
 #include <memory>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -22,6 +26,40 @@
 class ArcIntentHelperObserver;
 class ArcService;
 
+namespace internal {
+
+// If an ArcService is declared with a name, e.g.:
+//
+// class MyArcService : public ArcService {
+//  public:
+//   static const char kArcServiceName[];
+//   ...
+// };
+//
+// it can then be retrieved from ArcServiceManager in a type-safe way using
+// GetService<T>(). This two functions allow AddService() to get the name only
+// if it was provided, or use an empty string otherwise.
+//
+// Although the typename is always specified explicitly by the caller, the
+// parameter is required in order for SFINAE to work correctly.  It is not used
+// and can be nullptr, though.
+//
+// In order to avoid collisions, kArcServiceName should be the fully-qualified
+// name of the class.
+template <typename T>
+decltype(T::kArcServiceName, std::string()) GetArcServiceName(T* unused) {
+  if (strlen(T::kArcServiceName) == 0)
+    LOG(ERROR) << "kArcServiceName[] should be a fully-qualified class name.";
+  return T::kArcServiceName;
+}
+
+template <typename T>
+std::string GetArcServiceName(...) {
+  return std::string();
+}
+
+}  // namespace internal
+
 // Manages creation and destruction of services that communicate with the ARC
 // instance via the ArcBridgeService.
 class ArcServiceManager {
@@ -43,8 +81,22 @@
   // class was created on.
   ArcBridgeService* arc_bridge_service();
 
-  // Adds a service to the managed services list.
-  void AddService(std::unique_ptr<ArcService> service);
+  // Adds a service to the managed services list. Returns false if another
+  // named service with that name had already been added.
+  template <typename T>
+  bool AddService(std::unique_ptr<T> service) {
+    return AddServiceInternal(internal::GetArcServiceName<T>(nullptr),
+                              std::move(service));
+  }
+
+  // Gets the named service from the managed services list. This uses SFINAE, so
+  // you can only call this function if the service specified by T provides a
+  // static member variable called kArcServiceName[] (otherwise this will not
+  // compile).
+  template <typename T>
+  T* GetService() {
+    return static_cast<T*>(GetNamedServiceInternal(T::kArcServiceName));
+  }
 
   // Gets the global instance of the ARC Service Manager. This can only be
   // called on the thread that this class was created on.
@@ -82,6 +134,11 @@
  private:
   class IntentHelperObserverImpl;  // implemented in arc_service_manager.cc.
 
+  // Helper methods for AddService and GetService.
+  bool AddServiceInternal(const std::string& name,
+                          std::unique_ptr<ArcService> service);
+  ArcService* GetNamedServiceInternal(const std::string& name);
+
   base::ThreadChecker thread_checker_;
   scoped_refptr<base::TaskRunner> blocking_task_runner_;
 
@@ -89,7 +146,7 @@
   std::unique_ptr<ArcIntentHelperObserver> intent_helper_observer_;
 
   std::unique_ptr<ArcBridgeService> arc_bridge_service_;
-  std::vector<std::unique_ptr<ArcService>> services_;
+  std::unordered_multimap<std::string, std::unique_ptr<ArcService>> services_;
   scoped_refptr<ActivityIconLoader> icon_loader_;
   scoped_refptr<LocalActivityResolver> activity_resolver_;
 
diff --git a/components/arc/arc_service_manager_unittest.cc b/components/arc/arc_service_manager_unittest.cc
new file mode 100644
index 0000000..98c4db8
--- /dev/null
+++ b/components/arc/arc_service_manager_unittest.cc
@@ -0,0 +1,182 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/auto_reset.h"
+#include "base/memory/ptr_util.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_service_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+namespace {
+
+class AnonymousService : public ArcService {
+ public:
+  AnonymousService(ArcBridgeService* arc_bridge_service, bool* alive)
+      : ArcService(arc_bridge_service), alive_(alive, true) {}
+  ~AnonymousService() override = default;
+
+ private:
+  base::AutoReset<bool> alive_;
+};
+
+class NamedService : public ArcService {
+ public:
+  static const char kArcServiceName[];
+  NamedService(ArcBridgeService* arc_bridge_service, bool* alive)
+      : ArcService(arc_bridge_service), alive_(alive, true) {}
+  ~NamedService() override = default;
+
+ private:
+  base::AutoReset<bool> alive_;
+};
+
+class DifferentNamedService : public ArcService {
+ public:
+  static const char kArcServiceName[];
+  DifferentNamedService(ArcBridgeService* arc_bridge_service, bool* alive)
+      : ArcService(arc_bridge_service), alive_(alive, true) {}
+  ~DifferentNamedService() override = default;
+
+ private:
+  base::AutoReset<bool> alive_;
+};
+
+class EmptyNamedService : public ArcService {
+ public:
+  static const char kArcServiceName[];
+  EmptyNamedService(ArcBridgeService* arc_bridge_service, bool* alive)
+      : ArcService(arc_bridge_service), alive_(alive, true) {}
+  ~EmptyNamedService() override = default;
+
+ private:
+  base::AutoReset<bool> alive_;
+};
+
+const char NamedService::kArcServiceName[] =
+    "arc::(anonymous namespace)::NamedService";
+
+const char DifferentNamedService::kArcServiceName[] =
+    "arc::(anonymous namespace)::DifferentNamedService";
+
+const char EmptyNamedService::kArcServiceName[] = "";
+
+}  // namespace
+
+class ArcServiceManagerTest : public testing::Test {
+ public:
+  ArcServiceManagerTest() = default;
+
+  void SetUp() override {
+    arc_bridge_service_ = base::MakeUnique<ArcBridgeService>();
+  }
+
+  void TearDown() override { arc_bridge_service_.reset(); }
+
+  ArcBridgeService* arc_bridge_service() { return arc_bridge_service_.get(); }
+
+ private:
+  std::unique_ptr<ArcBridgeService> arc_bridge_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcServiceManagerTest);
+};
+
+// Exercises the basic getter functionality of ArcServiceManager.
+TEST_F(ArcServiceManagerTest, BasicGetter) {
+  bool named_service_alive = false;
+
+  // ArcServiceManager is empty, GetService() should return nullptr.
+  auto manager = base::MakeUnique<ArcServiceManager>(nullptr);
+  EXPECT_EQ(nullptr, manager->GetService<NamedService>());
+
+  EXPECT_TRUE(manager->AddService(base::MakeUnique<NamedService>(
+      arc_bridge_service(), &named_service_alive)));
+  EXPECT_TRUE(named_service_alive);
+  EXPECT_NE(nullptr, manager->GetService<NamedService>());
+
+  // Finally, the service should not be alive anymore.
+  manager.reset();
+  EXPECT_FALSE(named_service_alive);
+}
+
+// There is no way to distinguish between anonymous services, so it should be
+// possible to add them twice (not that it's recommended).
+TEST_F(ArcServiceManagerTest, MultipleAnonymousServices) {
+  bool anonymous_service_alive = false;
+  bool second_anonymous_service_alive = false;
+
+  auto manager = base::MakeUnique<ArcServiceManager>(nullptr);
+
+  EXPECT_TRUE(manager->AddService(base::MakeUnique<AnonymousService>(
+      arc_bridge_service(), &anonymous_service_alive)));
+  EXPECT_TRUE(anonymous_service_alive);
+  EXPECT_TRUE(manager->AddService(base::MakeUnique<AnonymousService>(
+      arc_bridge_service(), &second_anonymous_service_alive)));
+  EXPECT_TRUE(second_anonymous_service_alive);
+
+  // Finally, the individual services should not be alive anymore.
+  manager.reset();
+  EXPECT_FALSE(anonymous_service_alive);
+  EXPECT_FALSE(second_anonymous_service_alive);
+}
+
+// Named services can only be added once, but can still be retrieved.
+TEST_F(ArcServiceManagerTest, MultipleNamedServices) {
+  bool named_service_alive = false;
+  bool second_named_service_alive = false;
+  bool different_named_service_alive = false;
+
+  auto manager = base::MakeUnique<ArcServiceManager>(nullptr);
+
+  auto named_service = base::MakeUnique<NamedService>(arc_bridge_service(),
+                                                      &named_service_alive);
+  NamedService* raw_named_service = named_service.get();
+  EXPECT_TRUE(named_service_alive);
+  EXPECT_TRUE(manager->AddService(std::move(named_service)));
+  auto second_named_service = base::MakeUnique<NamedService>(
+      arc_bridge_service(), &second_named_service_alive);
+  EXPECT_TRUE(second_named_service_alive);
+  // This will fail and immediately destroy the service.
+  EXPECT_FALSE(manager->AddService(std::move(second_named_service)));
+  EXPECT_FALSE(second_named_service_alive);
+
+  // We should still be able to add a different-named service.
+  auto different_named_service = base::MakeUnique<DifferentNamedService>(
+      arc_bridge_service(), &different_named_service_alive);
+  DifferentNamedService* raw_different_named_service =
+      different_named_service.get();
+  EXPECT_TRUE(different_named_service_alive);
+  EXPECT_TRUE(manager->AddService(std::move(different_named_service)));
+
+  // And find both.
+  EXPECT_EQ(raw_named_service, manager->GetService<NamedService>());
+  EXPECT_EQ(raw_different_named_service,
+            manager->GetService<DifferentNamedService>());
+
+  manager.reset();
+  EXPECT_FALSE(named_service_alive);
+  EXPECT_FALSE(different_named_service_alive);
+}
+
+// Named services with an empty name are treated as anonymous services.
+// Developers shouldn't do that, though, and will trigger an error log.
+TEST_F(ArcServiceManagerTest, EmptyNamedServices) {
+  bool empty_named_service_alive = false;
+
+  auto manager = base::MakeUnique<ArcServiceManager>(nullptr);
+
+  EXPECT_TRUE(manager->AddService(base::MakeUnique<EmptyNamedService>(
+      arc_bridge_service(), &empty_named_service_alive)));
+  EXPECT_TRUE(empty_named_service_alive);
+  EXPECT_EQ(nullptr, manager->GetService<EmptyNamedService>());
+
+  manager.reset();
+  EXPECT_FALSE(empty_named_service_alive);
+}
+
+}  // namespace arc
diff --git a/components/browser_watcher/stability_data_names.cc b/components/browser_watcher/stability_data_names.cc
index 27be25b..03cb921 100644
--- a/components/browser_watcher/stability_data_names.cc
+++ b/components/browser_watcher/stability_data_names.cc
@@ -8,6 +8,9 @@
 
 const char kStabilityChannel[] = "channel";
 const char kStabilityExecutionPhase[] = "stability-execution-phase";
+const char kStabilityModuleAddress[] = "module-address";
+const char kStabilityModuleSize[] = "module-size";
+const char kStabilityModuleTimestamp[] = "module-timestamp";
 const char kStabilityPlatform[] = "platform";
 const char kStabilityProduct[] = "product";
 const char kStabilitySpecialBuild[] = "special-build";
diff --git a/components/browser_watcher/stability_data_names.h b/components/browser_watcher/stability_data_names.h
index 9143811..32fb640 100644
--- a/components/browser_watcher/stability_data_names.h
+++ b/components/browser_watcher/stability_data_names.h
@@ -10,6 +10,9 @@
 // Alphabetical list of stability data names.
 extern const char kStabilityChannel[];
 extern const char kStabilityExecutionPhase[];
+extern const char kStabilityModuleAddress[];
+extern const char kStabilityModuleSize[];
+extern const char kStabilityModuleTimestamp[];
 extern const char kStabilityPlatform[];
 extern const char kStabilityProduct[];
 extern const char kStabilitySpecialBuild[];
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index 65a59172..03f36dd 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -272,28 +272,18 @@
     return;
   cache_path = cache_path.Append(FILE_PATH_LITERAL("cronet"));
 
-  std::unique_ptr<URLRequestContextConfig> config(new URLRequestContextConfig(
-      quic_enabled_,  // Enable QUIC.
-      quic_enabled_ && quic_user_agent_id_.empty()
-          ? getDefaultQuicUserAgentId()
-          : quic_user_agent_id_,      // QUIC User Agent ID.
-      http2_enabled_,                 // Enable SPDY.
-      false,                          // Enable SDCH
-      URLRequestContextConfig::DISK,  // Type of http cache.
-      0,                              // Max size of http cache in bytes.
-      false,                          // Disable caching for HTTP responses.
-      cache_path.value(),  // Storage path for http cache and cookie storage.
-      user_agent_,         // User-Agent request header field.
-      "{}",                // JSON encoded experimental options.
-      "",                  // Data reduction proxy key.
-      "",                  // Data reduction proxy.
-      "",                  // Fallback data reduction proxy.
-      "",                  // Data reduction proxy secure proxy check URL.
-      std::move(mock_cert_verifier_),  // MockCertVerifier to use for testing
-                                       // purposes.
-      false,                           // Enable network quality estimator.
-      true,  // Enable bypassing of public key pinning for local trust anchors
-      ""));  // Certificate verifier cache data.
+  URLRequestContextConfigBuilder context_config_builder;
+  context_config_builder.enable_quic = quic_enabled_;   // Enable QUIC.
+  context_config_builder.enable_spdy = http2_enabled_;  // Enable HTTP/2.
+  context_config_builder.http_cache = URLRequestContextConfig::DISK;
+  context_config_builder.storage_path =
+      cache_path.value();  // Storage path for http cache and cookie storage.
+  context_config_builder.user_agent =
+      user_agent_;  // User-Agent request header field.
+  context_config_builder.mock_cert_verifier = std::move(
+      mock_cert_verifier_);  // MockCertVerifier to use for testing purposes.
+  std::unique_ptr<URLRequestContextConfig> config =
+      context_config_builder.Build();
 
   net::URLRequestContextBuilder context_builder;
 
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index b93bf3d..5e1bc35 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -392,4 +392,19 @@
   // TODO(mef): Use |config| to set cookies.
 }
 
+URLRequestContextConfigBuilder::URLRequestContextConfigBuilder() {}
+URLRequestContextConfigBuilder::~URLRequestContextConfigBuilder() {}
+
+std::unique_ptr<URLRequestContextConfig>
+URLRequestContextConfigBuilder::Build() {
+  return base::MakeUnique<URLRequestContextConfig>(
+      enable_quic, quic_user_agent_id, enable_spdy, enable_sdch, http_cache,
+      http_cache_max_size, load_disable_cache, storage_path, user_agent,
+      experimental_options, data_reduction_proxy_key,
+      data_reduction_primary_proxy, data_reduction_fallback_proxy,
+      data_reduction_secure_proxy_check_url, std::move(mock_cert_verifier),
+      enable_network_quality_estimator,
+      bypass_public_key_pinning_for_local_trust_anchors, cert_verifier_data);
+}
+
 }  // namespace cronet
diff --git a/components/cronet/url_request_context_config.h b/components/cronet/url_request_context_config.h
index f01564e..3ef5159a 100644
--- a/components/cronet/url_request_context_config.h
+++ b/components/cronet/url_request_context_config.h
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/time/time.h"
 #include "net/base/hash_value.h"
+#include "net/cert/cert_verifier.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -176,6 +177,67 @@
   DISALLOW_COPY_AND_ASSIGN(URLRequestContextConfig);
 };
 
+// Stores intermediate state for URLRequestContextConfig.  Initializes with
+// (mostly) sane defaults, then the appropriate member variables can be
+// modified, and it can be finalized with Build().
+struct URLRequestContextConfigBuilder {
+  URLRequestContextConfigBuilder();
+  ~URLRequestContextConfigBuilder();
+
+  // Finalize state into a URLRequestContextConfig.  Must only be called once,
+  // as once |mock_cert_verifier| is moved into a URLRequestContextConfig, it
+  // cannot be used again.
+  std::unique_ptr<URLRequestContextConfig> Build();
+
+  // Enable QUIC.
+  bool enable_quic = false;
+  // QUIC User Agent ID.
+  std::string quic_user_agent_id = "";
+  // Enable SPDY.
+  bool enable_spdy = true;
+  // Enable SDCH.
+  bool enable_sdch = false;
+  // Type of http cache.
+  URLRequestContextConfig::HttpCacheType http_cache =
+      URLRequestContextConfig::DISABLED;
+  // Max size of http cache in bytes.
+  int http_cache_max_size = 0;
+  // Disable caching for HTTP responses. Other information may be stored in
+  // the cache.
+  bool load_disable_cache = false;
+  // Storage path for http cache and cookie storage.
+  std::string storage_path = "";
+  // User-Agent request header field.
+  std::string user_agent = "";
+  // Experimental options encoded as a string in a JSON format containing
+  // experiments and their corresponding configuration options. The format
+  // is a JSON object with the name of the experiment as the key, and the
+  // configuration options as the value. An example:
+  //   {"experiment1": {"option1": "option_value1", "option2": "option_value2",
+  //    ...}, "experiment2: {"option3", "option_value3", ...}, ...}
+  std::string experimental_options = "{}";
+  // Enable Data Reduction Proxy with authentication key.
+  std::string data_reduction_proxy_key = "";
+  std::string data_reduction_primary_proxy = "";
+  std::string data_reduction_fallback_proxy = "";
+  std::string data_reduction_secure_proxy_check_url = "";
+
+  // Certificate verifier for testing.
+  std::unique_ptr<net::CertVerifier> mock_cert_verifier = nullptr;
+
+  // Enable network quality estimator.
+  bool enable_network_quality_estimator = false;
+
+  // Enable public key pinning bypass for local trust anchors.
+  bool bypass_public_key_pinning_for_local_trust_anchors = true;
+
+  // Data to populate CertVerifierCache.
+  std::string cert_verifier_data = "";
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(URLRequestContextConfigBuilder);
+};
+
 }  // namespace cronet
 
 #endif  // COMPONENTS_CRONET_URL_REQUEST_CONTEXT_CONFIG_H_
diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java
index f6e5c7f..2e57753 100644
--- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java
+++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedService.java
@@ -33,8 +33,8 @@
     private static final String VARIATIONS_SERVER_URL =
             "https://clientservices.googleapis.com/chrome-variations/seed?osname=android";
     private static final int BUFFER_SIZE = 4096;
-    private static final int READ_TIMEOUT = 10000; // time in ms
-    private static final int REQUEST_TIMEOUT = 15000; // time in ms
+    private static final int READ_TIMEOUT = 3000; // time in ms
+    private static final int REQUEST_TIMEOUT = 1000; // time in ms
 
     // Values for the "Variations.FirstRun.SeedFetchResult" sparse histogram, which also logs
     // HTTP result codes. These are negative so that they don't conflict with the HTTP codes.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 727e71e..0cf393c8 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1499,17 +1499,10 @@
       "//third_party/webrtc/media:rtc_media_base",
       "//third_party/webrtc/modules/desktop_capture:primitives",
     ]
-
-    if (is_linux || is_mac || is_win) {
-      sources += [
-        "media/capture/desktop_capture_device.cc",
-        "media/capture/desktop_capture_device.h",
-      ]
-      deps += [ "//third_party/webrtc/modules/desktop_capture" ]
-    }
   }
 
-  # Desktop screen capture implementations that are not dependent on WebRTC.
+  # Desktop screen capture implementations, conditionally built depending on
+  # the available implementations for each platform.
   if (is_linux || is_mac || is_win) {
     defines += [ "ENABLE_SCREEN_CAPTURE=1" ]
     sources += [
@@ -1540,6 +1533,13 @@
         "media/capture/window_activity_tracker_mac.mm",
       ]
     }
+    if (enable_webrtc) {
+      sources += [
+        "media/capture/desktop_capture_device.cc",
+        "media/capture/desktop_capture_device.h",
+      ]
+      deps += [ "//third_party/webrtc/modules/desktop_capture" ]
+    }
   }
 
   if (is_win) {
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 21eafb20..71effe5c95 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -66,6 +66,7 @@
   "+third_party/WebKit/public/platform/WebGestureEvent.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
   "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
+  "+third_party/WebKit/public/platform/WebMixedContentContextType.h",
   "+third_party/WebKit/public/platform/WebMouseEvent.h",
   "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebNavigationHintType.h",
@@ -80,9 +81,9 @@
   "+third_party/WebKit/public/platform/modules/broadcastchannel/broadcast_channel.mojom.h",
   "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h",
   "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
+  "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h",
   "+third_party/WebKit/public/platform/modules/notifications/WebNotificationConstants.h",
   "+third_party/WebKit/public/platform/modules/notifications/notification.mojom.h",
-  "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h",
   "+third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/permission.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index a4654300..4f55898 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -92,6 +92,16 @@
   return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
 }
 
+bool ShouldCreateDevToolsForNode(FrameTreeNode* ftn) {
+  return ShouldCreateDevToolsFor(ftn->current_frame_host());
+}
+
+static RenderFrameDevToolsAgentHost* GetAgentHostFor(FrameTreeNode* ftn) {
+  while (ftn && !ShouldCreateDevToolsForNode(ftn))
+    ftn = ftn->parent();
+  return FindAgentHost(ftn);
+}
+
 }  // namespace
 
 // RenderFrameDevToolsAgentHost::FrameHostHolder -------------------------------
@@ -395,7 +405,7 @@
 // static
 bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(
     FrameTreeNode* frame_tree_node) {
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
+  RenderFrameDevToolsAgentHost* agent_host = GetAgentHostFor(frame_tree_node);
   if (!agent_host || !agent_host->session())
     return false;
   return protocol::NetworkHandler::FromSession(agent_host->session())
@@ -405,7 +415,7 @@
 // static
 std::string RenderFrameDevToolsAgentHost::UserAgentOverride(
     FrameTreeNode* frame_tree_node) {
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
+  RenderFrameDevToolsAgentHost* agent_host = GetAgentHostFor(frame_tree_node);
   if (!agent_host || !agent_host->session())
     return std::string();
   return protocol::NetworkHandler::FromSession(agent_host->session())
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index eba07da5..8ed60813 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -30,6 +30,7 @@
 #include "content/public/common/url_constants.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/redirect_info.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
@@ -92,6 +93,7 @@
       navigation_start_(navigation_start),
       pending_nav_entry_id_(pending_nav_entry_id),
       request_context_type_(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
+      mixed_content_context_type_(blink::WebMixedContentContextType::Blockable),
       should_replace_current_entry_(false),
       is_download_(false),
       is_stream_(false),
@@ -315,6 +317,7 @@
   WillStartRequest(method, resource_request_body, sanitized_referrer,
                    has_user_gesture, transition, is_external_protocol,
                    REQUEST_CONTEXT_TYPE_LOCATION,
+                   blink::WebMixedContentContextType::Blockable,
                    base::Bind(&UpdateThrottleCheckResult, &result));
 
   // Reset the callback to ensure it will not be called later.
@@ -422,6 +425,7 @@
     ui::PageTransition transition,
     bool is_external_protocol,
     RequestContextType request_context_type,
+    blink::WebMixedContentContextType mixed_content_context_type,
     const ThrottleChecksFinishedCallback& callback) {
   if (method != "POST")
     DCHECK(!resource_request_body);
@@ -435,6 +439,7 @@
   transition_ = transition;
   is_external_protocol_ = is_external_protocol;
   request_context_type_ = request_context_type;
+  mixed_content_context_type_ = mixed_content_context_type;
   state_ = WILL_SEND_REQUEST;
   complete_callback_ = callback;
 
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index 20a159a..cc02ac4 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -26,6 +26,7 @@
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/common/request_context_type.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "url/gurl.h"
 
 struct FrameHostMsg_DidCommitProvisionalLoad_Params;
@@ -155,6 +156,11 @@
     return request_context_type_;
   }
 
+  blink::WebMixedContentContextType mixed_content_context_type() const {
+    DCHECK_GE(state_, WILL_SEND_REQUEST);
+    return mixed_content_context_type_;
+  }
+
   // Get the unique id from the NavigationEntry associated with this
   // NavigationHandle. Note that a synchronous, renderer-initiated navigation
   // will not have a NavigationEntry associated with it, and this will return 0.
@@ -221,6 +227,7 @@
       ui::PageTransition transition,
       bool is_external_protocol,
       RequestContextType request_context_type,
+      blink::WebMixedContentContextType mixed_content_context_type,
       const ThrottleChecksFinishedCallback& callback);
 
   // Called when the URLRequest will be redirected in the network stack.
@@ -398,6 +405,9 @@
   // The fetch request context type.
   RequestContextType request_context_type_;
 
+  // The mixed content context type for potential mixed content checks.
+  blink::WebMixedContentContextType mixed_content_context_type_;
+
   // This callback will be run when all throttle checks have been performed.
   ThrottleChecksFinishedCallback complete_callback_;
 
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc
index 0a1ec53..8c9ef716 100644
--- a/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -113,6 +113,7 @@
     test_handle_->WillStartRequest(
         "GET", nullptr, Referrer(), false, ui::PAGE_TRANSITION_LINK, false,
         REQUEST_CONTEXT_TYPE_LOCATION,
+        blink::WebMixedContentContextType::Blockable,
         base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
                    base::Unretained(this)));
   }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 8a1007d..9f676eb 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -43,6 +43,7 @@
 #include "net/base/url_util.h"
 #include "net/http/http_request_headers.h"
 #include "net/url_request/redirect_info.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "third_party/WebKit/public/web/WebSandboxFlags.h"
 
 namespace content {
@@ -228,7 +229,9 @@
       BeginNavigationParams(entry.extra_headers(), net::LOAD_NORMAL,
                             false,  // has_user_gestures
                             false,  // skip_service_worker
-                            REQUEST_CONTEXT_TYPE_LOCATION, initiator),
+                            REQUEST_CONTEXT_TYPE_LOCATION,
+                            blink::WebMixedContentContextType::Blockable,
+                            initiator),
       entry.ConstructRequestNavigationParams(
           frame_entry, is_same_document_history_load,
           is_history_navigation_in_new_child,
@@ -239,7 +242,7 @@
           controller->GetLastCommittedEntryIndex(),
           controller->GetEntryCount()),
       browser_initiated,
-      true, // may_transfer
+      true,  // may_transfer
       &frame_entry, &entry));
   return navigation_request;
 }
@@ -357,6 +360,7 @@
                                      common_params_.referrer),
         begin_params_.has_user_gesture, common_params_.transition, false,
         begin_params_.request_context_type,
+        begin_params_.mixed_content_context_type,
         base::Bind(&NavigationRequest::OnStartChecksComplete,
                    base::Unretained(this)));
     return;
diff --git a/content/browser/loader/navigation_resource_throttle.cc b/content/browser/loader/navigation_resource_throttle.cc
index 5ce1654f..6a7f6b6 100644
--- a/content/browser/loader/navigation_resource_throttle.cc
+++ b/content/browser/loader/navigation_resource_throttle.cc
@@ -99,7 +99,8 @@
     bool has_user_gesture,
     ui::PageTransition transition,
     bool is_external_protocol,
-    RequestContextType request_context_type) {
+    RequestContextType request_context_type,
+    blink::WebMixedContentContextType mixed_content_context_type) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   NavigationHandleImpl* navigation_handle =
       FindNavigationHandle(render_process_id, render_frame_host_id, callback);
@@ -109,6 +110,7 @@
   navigation_handle->WillStartRequest(
       method, resource_request_body, sanitized_referrer, has_user_gesture,
       transition, is_external_protocol, request_context_type,
+      mixed_content_context_type,
       base::Bind(&SendCheckResultToIOThread, callback));
 }
 
@@ -178,10 +180,12 @@
 NavigationResourceThrottle::NavigationResourceThrottle(
     net::URLRequest* request,
     ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
-    RequestContextType request_context_type)
+    RequestContextType request_context_type,
+    blink::WebMixedContentContextType mixed_content_context_type)
     : request_(request),
       resource_dispatcher_host_delegate_(resource_dispatcher_host_delegate),
       request_context_type_(request_context_type),
+      mixed_content_context_type_(mixed_content_context_type),
       in_cross_site_transition_(false),
       on_transfer_done_result_(NavigationThrottle::DEFER),
       weak_ptr_factory_(this) {}
@@ -214,7 +218,8 @@
                      request_->url(), Referrer(GURL(request_->referrer()),
                                                info->GetReferrerPolicy())),
                  info->HasUserGesture(), info->GetPageTransition(),
-                 is_external_protocol, request_context_type_));
+                 is_external_protocol, request_context_type_,
+                 mixed_content_context_type_));
   *defer = true;
 }
 
diff --git a/content/browser/loader/navigation_resource_throttle.h b/content/browser/loader/navigation_resource_throttle.h
index a9685e3..62db169 100644
--- a/content/browser/loader/navigation_resource_throttle.h
+++ b/content/browser/loader/navigation_resource_throttle.h
@@ -11,6 +11,7 @@
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/resource_throttle.h"
 #include "content/public/common/request_context_type.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 
 namespace net {
 class URLRequest;
@@ -27,7 +28,8 @@
   NavigationResourceThrottle(
       net::URLRequest* request,
       ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate,
-      RequestContextType request_context_type);
+      RequestContextType request_context_type,
+      blink::WebMixedContentContextType mixed_content_context_type);
   ~NavigationResourceThrottle() override;
 
   // ResourceThrottle overrides:
@@ -56,6 +58,7 @@
   net::URLRequest* request_;
   ResourceDispatcherHostDelegate* resource_dispatcher_host_delegate_;
   RequestContextType request_context_type_;
+  blink::WebMixedContentContextType mixed_content_context_type_;
   bool in_cross_site_transition_;
   NavigationThrottle::ThrottleCheckResult on_transfer_done_result_;
 
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc
index 2b60f650..29fed3e 100644
--- a/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -106,9 +106,10 @@
   std::unique_ptr<NavigationURLLoader> MakeTestLoader(
       const GURL& url,
       NavigationURLLoaderDelegate* delegate) {
-    BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false,
-                                       false, REQUEST_CONTEXT_TYPE_LOCATION,
-                                       url::Origin(url));
+    BeginNavigationParams begin_params(
+        std::string(), net::LOAD_NORMAL, false, false,
+        REQUEST_CONTEXT_TYPE_LOCATION,
+        blink::WebMixedContentContextType::Blockable, url::Origin(url));
     CommonNavigationParams common_params;
     common_params.url = url;
     std::unique_ptr<NavigationRequestInfo> request_info(
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 6cd99e8f..c8351429 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1684,6 +1684,7 @@
   return AddStandardHandlers(request, request_data.resource_type,
                              resource_context,
                              request_data.fetch_request_context_type,
+                             request_data.fetch_mixed_content_context_type,
                              requester_info->appcache_service(), child_id,
                              route_id, std::move(handler));
 }
@@ -1694,6 +1695,7 @@
     ResourceType resource_type,
     ResourceContext* resource_context,
     RequestContextType fetch_request_context_type,
+    blink::WebMixedContentContextType fetch_mixed_content_context_type,
     AppCacheService* appcache_service,
     int child_id,
     int route_id,
@@ -1712,7 +1714,8 @@
   // thread is handled by the NavigationURLloader.
   if (!IsBrowserSideNavigationEnabled() && IsResourceTypeFrame(resource_type)) {
     throttles.push_back(base::MakeUnique<NavigationResourceThrottle>(
-        request, delegate_, fetch_request_context_type));
+        request, delegate_, fetch_request_context_type,
+        fetch_mixed_content_context_type));
   }
 
   if (delegate_) {
@@ -2286,6 +2289,7 @@
   handler = AddStandardHandlers(
       new_request.get(), resource_type, resource_context,
       info.begin_params.request_context_type,
+      info.begin_params.mixed_content_context_type,
       appcache_handle_core ? appcache_handle_core->GetAppCacheService()
                            : nullptr,
       -1,  // child_id
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 90a0112..3089f6a 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -37,6 +37,7 @@
 #include "ipc/ipc_message.h"
 #include "net/base/load_states.h"
 #include "net/base/request_priority.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -618,6 +619,7 @@
       ResourceType resource_type,
       ResourceContext* resource_context,
       RequestContextType fetch_request_context_type,
+      blink::WebMixedContentContextType fetch_mixed_content_context_type,
       AppCacheService* appcache_service,
       int child_id,
       int route_id,
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 9f3361f..f7706e9 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -1083,9 +1083,10 @@
 
       // Make a navigation request.
       TestNavigationURLLoaderDelegate delegate;
-      BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false,
-                                         false, REQUEST_CONTEXT_TYPE_LOCATION,
-                                         url::Origin(url));
+      BeginNavigationParams begin_params(
+          std::string(), net::LOAD_NORMAL, false, false,
+          REQUEST_CONTEXT_TYPE_LOCATION,
+          blink::WebMixedContentContextType::Blockable, url::Origin(url));
       CommonNavigationParams common_params;
       common_params.url = url;
       std::unique_ptr<NavigationRequestInfo> request_info(
@@ -2641,9 +2642,11 @@
   if (IsBrowserSideNavigationEnabled()) {
     // Create a NavigationRequest.
     TestNavigationURLLoaderDelegate delegate;
-    BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false,
-                                       false, REQUEST_CONTEXT_TYPE_LOCATION,
-                                       url::Origin(download_url));
+    BeginNavigationParams begin_params(
+        std::string(), net::LOAD_NORMAL, false, false,
+        REQUEST_CONTEXT_TYPE_LOCATION,
+        blink::WebMixedContentContextType::Blockable,
+        url::Origin(download_url));
     CommonNavigationParams common_params;
     common_params.url = download_url;
     std::unique_ptr<NavigationRequestInfo> request_info(
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index 6af09c0..24880a57 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -40,17 +40,22 @@
 #include "media/capture/video/video_capture_device_client.h"
 #include "media/capture/video/video_capture_device_factory.h"
 
-#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
+#if defined(ENABLE_SCREEN_CAPTURE)
+
+#if BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID)
 #include "content/browser/media/capture/desktop_capture_device.h"
+#endif
+
 #if defined(USE_AURA)
 #include "content/browser/media/capture/desktop_capture_device_aura.h"
 #endif
-#endif
 
-#if defined(ENABLE_SCREEN_CAPTURE) && defined(OS_ANDROID)
+#if defined(OS_ANDROID)
 #include "content/browser/media/capture/screen_capture_device_android.h"
 #endif
 
+#endif  // defined(ENABLE_SCREEN_CAPTURE)
+
 namespace {
 
 class VideoFrameConsumerFeedbackObserverOnTaskRunner
@@ -707,8 +712,10 @@
 #if defined(USE_AURA)
     video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
 #endif  // defined(USE_AURA)
-    if (!video_capture_device)
-      video_capture_device = DesktopCaptureDevice::Create(desktop_id);
+#if BUILDFLAG(ENABLE_WEBRTC)
+  if (!video_capture_device)
+    video_capture_device = DesktopCaptureDevice::Create(desktop_id);
+#endif  // BUILDFLAG(ENABLE_WEBRTC)
 #endif  // defined (OS_ANDROID)
   }
 #endif  // defined(ENABLE_SCREEN_CAPTURE)
@@ -1227,7 +1234,7 @@
     media::VideoCaptureDevice* device,
     gfx::NativeViewId window_id) {
   DCHECK(IsOnDeviceThread());
-#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
+#if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID)
   DesktopCaptureDevice* desktop_device =
       static_cast<DesktopCaptureDevice*>(device);
   desktop_device->SetNotificationWindowId(window_id);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 4fb8c88..4113b7d5 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1669,6 +1669,7 @@
     switches::kDisable3DAPIs,
     switches::kDisableAcceleratedJpegDecoding,
     switches::kDisableAcceleratedVideoDecode,
+    switches::kDisableBackgroundTimerThrottling,
     switches::kDisableBlinkFeatures,
     switches::kDisableBreakpad,
     switches::kDisablePreferCompositingToLCDText,
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index bcb9a6fa..976b7fc 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1174,10 +1174,12 @@
 };
 
 void DownloadImageTestInternal(Shell* shell,
-                               const GURL &image_url,
-                               int expected_http_status) {
+                               const GURL& image_url,
+                               int expected_http_status,
+                               int expected_number_of_images) {
   using ::testing::_;
   using ::testing::InvokeWithoutArgs;
+  using ::testing::SizeIs;
 
   // Set up everything.
   DownloadImageObserver download_image_observer;
@@ -1186,7 +1188,8 @@
 
   // Set up expectation and stub.
   EXPECT_CALL(download_image_observer,
-              OnFinishDownloadImage(_, expected_http_status, _, _, _));
+              OnFinishDownloadImage(_, expected_http_status, _,
+                                    SizeIs(expected_number_of_images), _));
   ON_CALL(download_image_observer, OnFinishDownloadImage(_, _, _, _, _))
       .WillByDefault(
           InvokeWithoutArgs(loop_runner.get(), &MessageLoopRunner::Quit));
@@ -1218,16 +1221,26 @@
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
                        DownloadImage_HttpImage) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  const GURL kImageUrl =
-      embedded_test_server()->GetURL("/image.jpg");
-  DownloadImageTestInternal(shell(), kImageUrl, 200);
+  const GURL kImageUrl = embedded_test_server()->GetURL("/single_face.jpg");
+  DownloadImageTestInternal(shell(), kImageUrl, 200, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
                        DownloadImage_Deny_FileImage) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  shell()->LoadURL(embedded_test_server()->GetURL("/simple_page.html"));
+
+  const GURL kImageUrl = GetTestUrl("", "single_face.jpg");
+  DownloadImageTestInternal(shell(), kImageUrl, 0, 0);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       DownloadImage_Allow_FileImage) {
+  shell()->LoadURL(GetTestUrl("", "simple_page.html"));
+
   const GURL kImageUrl =
       GetTestUrl("", "image.jpg");
-  DownloadImageTestInternal(shell(), kImageUrl, 0);
+  DownloadImageTestInternal(shell(), kImageUrl, 0, 0);
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_NoValidImage) {
@@ -1242,6 +1255,19 @@
   run_loop.Run();
 }
 
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_DataImage) {
+  const GURL kImageUrl = GURL(
+      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHE"
+      "lEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==");
+  DownloadImageTestInternal(shell(), kImageUrl, 0, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       DownloadImage_InvalidDataImage) {
+  const GURL kImageUrl = GURL("data:image/png;invalid");
+  DownloadImageTestInternal(shell(), kImageUrl, 0, 0);
+}
+
 class MouseLockDelegate : public WebContentsDelegate {
  public:
   // WebContentsDelegate:
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index fd4e3167..88785e4 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -1003,8 +1003,8 @@
 }
 
 // Test that vertical overscroll updates are sent only when a user overscrolls
-// vertically.
-#if defined(OS_WIN)
+// vertically. Flaky on several platforms. https://crbug.com/679420
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
 #define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll
 #else
 #define MAYBE_VerticalOverscroll VerticalOverscroll
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
index 5708d60..9ac9311d 100644
--- a/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
+++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
@@ -70,14 +70,11 @@
         &font_fallback, g_font_collection.Get(), sender);
   }
 
-  sk_sp<SkFontMgr> skia_font_manager(SkFontMgr_New_DirectWrite(
-      factory.Get(), g_font_collection.Get(), font_fallback.Get()));
-  blink::WebFontRendering::setSkiaFontManager(skia_font_manager.get());
+  sk_sp<SkFontMgr> skia_font_manager = SkFontMgr_New_DirectWrite(
+      factory.Get(), g_font_collection.Get(), font_fallback.Get());
+  blink::WebFontRendering::setSkiaFontManager(skia_font_manager);
 
-  // Add an extra ref for SetDefaultSkiaFactory, which keeps a ref but doesn't
-  // addref.
-  skia_font_manager->ref();
-  SetDefaultSkiaFactory(skia_font_manager.get());
+  SetDefaultSkiaFactory(std::move(skia_font_manager));
 
   // When IDWriteFontFallback is not available (prior to Win8.1) Skia will
   // still attempt to use DirectWrite to determine fallback fonts (in
diff --git a/content/child/font_warmup_win.cc b/content/child/font_warmup_win.cc
index 739246b..99d0139 100644
--- a/content/child/font_warmup_win.cc
+++ b/content/child/font_warmup_win.cc
@@ -416,7 +416,7 @@
 
 GdiFontPatchData* PatchGdiFontEnumeration(const base::FilePath& path) {
   if (!g_warmup_fontmgr)
-    g_warmup_fontmgr = SkFontMgr_New_DirectWrite();
+    g_warmup_fontmgr = SkFontMgr_New_DirectWrite().release();
   DCHECK(g_warmup_fontmgr);
   return new GdiFontPatchDataImpl(path);
 }
@@ -429,8 +429,9 @@
   g_fake_gdi_object_factory.Get().ResetObjectHandles();
 }
 
-void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr) {
-  g_warmup_fontmgr = fontmgr;
+void SetPreSandboxWarmupFontMgrForTesting(sk_sp<SkFontMgr> fontmgr) {
+  SkSafeUnref(g_warmup_fontmgr);
+  g_warmup_fontmgr = fontmgr.release();
 }
 
 }  // namespace content
diff --git a/content/child/font_warmup_win.h b/content/child/font_warmup_win.h
index 3a89ef2..d62ce5f 100644
--- a/content/child/font_warmup_win.h
+++ b/content/child/font_warmup_win.h
@@ -12,6 +12,7 @@
 #include "content/common/content_export.h"
 
 class SkFontMgr;
+template <typename T> class sk_sp;
 
 namespace content {
 
@@ -39,7 +40,8 @@
 
 // Sets the pre-sandbox warmup font manager directly. This should only be used
 // for testing the implementation.
-CONTENT_EXPORT void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr);
+CONTENT_EXPORT void SetPreSandboxWarmupFontMgrForTesting(
+    sk_sp<SkFontMgr> fontmgr);
 
 // Directwrite connects to the font cache service to retrieve information about
 // fonts installed on the system etc. This works well outside the sandbox and
diff --git a/content/child/font_warmup_win_unittest.cc b/content/child/font_warmup_win_unittest.cc
index 21ba20d..9494655b 100644
--- a/content/child/font_warmup_win_unittest.cc
+++ b/content/child/font_warmup_win_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/sys_byteorder.h"
 #include "base/win/windows_version.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/core/SkString.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/ports/SkFontMgr.h"
@@ -130,7 +131,9 @@
 
 class TestSkFontMgr : public SkFontMgr {
  public:
-  TestSkFontMgr() { content::SetPreSandboxWarmupFontMgrForTesting(this); }
+  TestSkFontMgr() {
+    content::SetPreSandboxWarmupFontMgrForTesting(sk_ref_sp(this));
+  }
   ~TestSkFontMgr() override {
     content::SetPreSandboxWarmupFontMgrForTesting(nullptr);
   }
diff --git a/content/child/request_extra_data.cc b/content/child/request_extra_data.cc
index 1b5ea2e..2d26828 100644
--- a/content/child/request_extra_data.cc
+++ b/content/child/request_extra_data.cc
@@ -27,7 +27,8 @@
       originated_from_service_worker_(false),
       initiated_in_secure_context_(false),
       is_prefetch_(false),
-      download_to_network_cache_only_(false) {}
+      download_to_network_cache_only_(false),
+      block_mixed_plugin_content_(false) {}
 
 RequestExtraData::~RequestExtraData() {
 }
diff --git a/content/child/request_extra_data.h b/content/child/request_extra_data.h
index 553469e..d544989 100644
--- a/content/child/request_extra_data.h
+++ b/content/child/request_extra_data.h
@@ -149,6 +149,15 @@
     download_to_network_cache_only_ = download_to_cache;
   }
 
+  // Copy of the settings value determining if mixed plugin content should be
+  // blocked.
+  bool block_mixed_plugin_content() const {
+    return block_mixed_plugin_content_;
+  }
+  void set_block_mixed_plugin_content(bool block_mixed_plugin_content) {
+    block_mixed_plugin_content_ = block_mixed_plugin_content;
+  }
+
   void CopyToResourceRequest(ResourceRequest* request) const;
 
  private:
@@ -171,6 +180,7 @@
   bool initiated_in_secure_context_;
   bool is_prefetch_;
   bool download_to_network_cache_only_;
+  bool block_mixed_plugin_content_;
 
   DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
 };
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index de9efa92..9c444531 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -586,6 +586,9 @@
       GetFetchRedirectModeForWebURLRequest(request);
   resource_request->fetch_request_context_type =
       GetRequestContextTypeForWebURLRequest(request);
+  resource_request->fetch_mixed_content_context_type =
+      GetMixedContentContextTypeForWebURLRequest(request);
+
   resource_request->fetch_frame_type =
       GetRequestContextFrameTypeForWebURLRequest(request);
   resource_request->request_body =
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc
index 01c19d4e..eb3c606c 100644
--- a/content/child/web_url_loader_impl_unittest.cc
+++ b/content/child/web_url_loader_impl_unittest.cc
@@ -269,6 +269,7 @@
 
   void DoStartAsyncRequest() {
     blink::WebURLRequest request{GURL(kTestURL)};
+    request.setRequestContext(blink::WebURLRequest::RequestContextInternal);
     client()->loader()->loadAsynchronously(request, client());
     ASSERT_TRUE(peer());
   }
@@ -276,6 +277,7 @@
   void DoStartAsyncRequestWithPriority(
       blink::WebURLRequest::Priority priority) {
     blink::WebURLRequest request{GURL(kTestURL)};
+    request.setRequestContext(blink::WebURLRequest::RequestContextInternal);
     request.setPriority(priority);
     client()->loader()->loadAsynchronously(request, client());
     ASSERT_TRUE(peer());
@@ -668,6 +670,7 @@
   const int kEncodedDataLength = 130;
   const GURL url(kTestURL);
   blink::WebURLRequest request(url);
+  request.setRequestContext(blink::WebURLRequest::RequestContextInternal);
 
   // Prepare a mock response
   SyncLoadResponse sync_load_response;
diff --git a/content/child/web_url_request_util.cc b/content/child/web_url_request_util.cc
index 6065831..51faca13 100644
--- a/content/child/web_url_request_util.cc
+++ b/content/child/web_url_request_util.cc
@@ -18,6 +18,7 @@
 #include "third_party/WebKit/public/platform/WebCachePolicy.h"
 #include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebMixedContent.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLError.h"
@@ -471,6 +472,19 @@
   return static_cast<RequestContextType>(request.getRequestContext());
 }
 
+blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest(
+    const blink::WebURLRequest& request) {
+  bool block_mixed_plugin_content = false;
+  if (request.getExtraData()) {
+    RequestExtraData* extra_data =
+        static_cast<RequestExtraData*>(request.getExtraData());
+    block_mixed_plugin_content = extra_data->block_mixed_plugin_content();
+  }
+
+  return blink::WebMixedContent::contextTypeFromRequestContext(
+      request.getRequestContext(), block_mixed_plugin_content);
+}
+
 STATIC_ASSERT_ENUM(SkipServiceWorker::NONE,
                    WebURLRequest::SkipServiceWorker::None);
 STATIC_ASSERT_ENUM(SkipServiceWorker::CONTROLLING,
diff --git a/content/child/web_url_request_util.h b/content/child/web_url_request_util.h
index 6763af8..857a9c3 100644
--- a/content/child/web_url_request_util.h
+++ b/content/child/web_url_request_util.h
@@ -13,6 +13,7 @@
 #include "content/public/common/request_context_frame_type.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 
 namespace blink {
 class WebHTTPBody;
@@ -56,6 +57,8 @@
     const blink::WebURLRequest& request);
 RequestContextType GetRequestContextTypeForWebURLRequest(
     const blink::WebURLRequest& request);
+blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest(
+    const blink::WebURLRequest& request);
 SkipServiceWorker GetSkipServiceWorkerForWebURLRequest(
     const blink::WebURLRequest& request);
 
diff --git a/content/common/DEPS b/content/common/DEPS
index 1053daf..caee767d 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -24,6 +24,7 @@
   "+third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
   "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
+  "+third_party/WebKit/public/platform/WebMixedContentContextType.h",
   "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h",
   "+third_party/WebKit/public/platform/WebPageVisibilityState.h",
@@ -38,8 +39,8 @@
   "+third_party/WebKit/public/platform/modules/device_orientation/WebDeviceOrientationData.h",
   "+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
   "+third_party/WebKit/public/platform/modules/mediasession/media_session.mojom.h",
-  "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
   "+third_party/WebKit/public/platform/modules/permissions/WebPermissionType.h",
+  "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
   "+third_party/WebKit/public/platform/modules/push_messaging/WebPushError.h",
   "+third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h",
   "+third_party/WebKit/public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h",
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 9f65e60..cc85b72 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -347,6 +347,7 @@
   IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
   IPC_STRUCT_TRAITS_MEMBER(skip_service_worker)
   IPC_STRUCT_TRAITS_MEMBER(request_context_type)
+  IPC_STRUCT_TRAITS_MEMBER(mixed_content_context_type)
   IPC_STRUCT_TRAITS_MEMBER(searchable_form_url)
   IPC_STRUCT_TRAITS_MEMBER(searchable_form_encoding)
   IPC_STRUCT_TRAITS_MEMBER(initiator_origin)
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index 51220c0..cf75598 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -84,7 +84,9 @@
     : load_flags(0),
       has_user_gesture(false),
       skip_service_worker(false),
-      request_context_type(REQUEST_CONTEXT_TYPE_LOCATION) {}
+      request_context_type(REQUEST_CONTEXT_TYPE_LOCATION),
+      mixed_content_context_type(blink::WebMixedContentContextType::Blockable) {
+}
 
 BeginNavigationParams::BeginNavigationParams(
     std::string headers,
@@ -92,12 +94,14 @@
     bool has_user_gesture,
     bool skip_service_worker,
     RequestContextType request_context_type,
+    blink::WebMixedContentContextType mixed_content_context_type,
     const base::Optional<url::Origin>& initiator_origin)
     : headers(headers),
       load_flags(load_flags),
       has_user_gesture(has_user_gesture),
       skip_service_worker(skip_service_worker),
       request_context_type(request_context_type),
+      mixed_content_context_type(mixed_content_context_type),
       initiator_origin(initiator_origin) {}
 
 BeginNavigationParams::BeginNavigationParams(
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index 86a5e7e..81e3229c 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -21,6 +21,7 @@
 #include "content/public/common/referrer.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_response.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -144,12 +145,14 @@
   // TODO(clamy): See if it is possible to reuse this in
   // ResourceMsg_Request_Params.
   BeginNavigationParams();
-  BeginNavigationParams(std::string headers,
-                        int load_flags,
-                        bool has_user_gesture,
-                        bool skip_service_worker,
-                        RequestContextType request_context_type,
-                        const base::Optional<url::Origin>& initiator_origin);
+  BeginNavigationParams(
+      std::string headers,
+      int load_flags,
+      bool has_user_gesture,
+      bool skip_service_worker,
+      RequestContextType request_context_type,
+      blink::WebMixedContentContextType mixed_content_context_type,
+      const base::Optional<url::Origin>& initiator_origin);
   BeginNavigationParams(const BeginNavigationParams& other);
   ~BeginNavigationParams();
 
@@ -168,6 +171,9 @@
   // Indicates the request context type.
   RequestContextType request_context_type;
 
+  // The mixed content context type for potential mixed content checks.
+  blink::WebMixedContentContextType mixed_content_context_type;
+
   // See WebSearchableFormData for a description of these.
   GURL searchable_form_url;
   std::string searchable_form_encoding;
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index e806755..31d4ebdb7 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -27,6 +27,7 @@
 #include "net/http/http_response_info.h"
 #include "net/nqe/effective_connection_type.h"
 #include "net/url_request/redirect_info.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 
 #ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
 #define CONTENT_COMMON_RESOURCE_MESSAGES_H_
@@ -135,6 +136,9 @@
 IPC_ENUM_TRAITS_MAX_VALUE(net::EffectiveConnectionType,
                           net::EFFECTIVE_CONNECTION_TYPE_LAST - 1)
 
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebMixedContentContextType,
+                          blink::WebMixedContentContextType::Last)
+
 IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseHead)
 IPC_STRUCT_TRAITS_PARENT(content::ResourceResponseInfo)
   IPC_STRUCT_TRAITS_MEMBER(request_start)
@@ -230,6 +234,7 @@
   IPC_STRUCT_TRAITS_MEMBER(fetch_credentials_mode)
   IPC_STRUCT_TRAITS_MEMBER(fetch_redirect_mode)
   IPC_STRUCT_TRAITS_MEMBER(fetch_request_context_type)
+  IPC_STRUCT_TRAITS_MEMBER(fetch_mixed_content_context_type)
   IPC_STRUCT_TRAITS_MEMBER(fetch_frame_type)
   IPC_STRUCT_TRAITS_MEMBER(request_body)
   IPC_STRUCT_TRAITS_MEMBER(download_to_file)
diff --git a/content/common/resource_request.h b/content/common/resource_request.h
index 0f5651f..a19d912 100644
--- a/content/common/resource_request.h
+++ b/content/common/resource_request.h
@@ -19,6 +19,7 @@
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
 #include "net/base/request_priority.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
 #include "ui/base/page_transition_types.h"
@@ -116,6 +117,10 @@
   RequestContextType fetch_request_context_type =
       REQUEST_CONTEXT_TYPE_UNSPECIFIED;
 
+  // The mixed content context type to be used for mixed content checks.
+  blink::WebMixedContentContextType fetch_mixed_content_context_type =
+      blink::WebMixedContentContextType::Blockable;
+
   // The frame type passed to the ServiceWorker.
   RequestContextFrameType fetch_frame_type =
       REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 120d558..3291804 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -141,6 +141,7 @@
 #include "content/renderer/web_frame_utils.h"
 #include "content/renderer/web_ui_extension.h"
 #include "crypto/sha2.h"
+#include "gin/modules/console.h"
 #include "gin/modules/module_registry.h"
 #include "media/audio/audio_output_device.h"
 #include "media/base/audio_renderer_mixer_input.h"
@@ -2621,6 +2622,9 @@
     return;
 
   v8::HandleScope handle_scope(isolate);
+
+  registry->AddBuiltinModule(isolate, gin::Console::kModuleName,
+                             gin::Console::GetModule(isolate));
   registry->AddBuiltinModule(isolate, mojo::edk::js::Core::kModuleName,
                              mojo::edk::js::Core::GetModule(isolate));
   registry->AddBuiltinModule(isolate, mojo::edk::js::Support::kModuleName,
@@ -6228,7 +6232,9 @@
       info.urlRequest.hasUserGesture(),
       info.urlRequest.skipServiceWorker() !=
           blink::WebURLRequest::SkipServiceWorker::None,
-      GetRequestContextTypeForWebURLRequest(info.urlRequest), initiator_origin);
+      GetRequestContextTypeForWebURLRequest(info.urlRequest),
+      GetMixedContentContextTypeForWebURLRequest(info.urlRequest),
+      initiator_origin);
 
   if (!info.form.isNull()) {
     WebSearchableFormData web_searchable_form_data(info.form);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 5b6afa6c..7186122 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -684,6 +684,7 @@
       blink::WebURLRequest::FetchCredentialsModeInclude);
   request.setFetchRedirectMode(blink::WebURLRequest::FetchRedirectModeManual);
   request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel);
+  request.setRequestContext(blink::WebURLRequest::RequestContextInternal);
   blink::WebFrameClient::NavigationPolicyInfo policy_info(request);
   policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
   policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
diff --git a/content/shell/app/blink_test_platform_support_android.cc b/content/shell/app/blink_test_platform_support_android.cc
index 2a5867c..fb6dadc 100644
--- a/content/shell/app/blink_test_platform_support_android.cc
+++ b/content/shell/app/blink_test_platform_support_android.cc
@@ -5,6 +5,7 @@
 #include "content/shell/app/blink_test_platform_support.h"
 
 #include "skia/ext/fontmgr_default_android.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
 #include "third_party/skia/include/ports/SkFontMgr_android.h"
 
 namespace {
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 0b41550..cf9a43eb 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -41,6 +41,14 @@
     self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403)
 
     # All platforms.
+    self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html',
+        bug=678850)
+    self.Fail('conformance/attribs/gl-vertexattribpointer.html', bug=678850)
+    self.Fail('conformance2/attribs/gl-vertexattribipointer.html', bug=678850)
+
+    self.Fail('conformance/extensions/webgl-compressed-texture-etc.html',
+        bug=679678)
+
     self.Flaky('conformance2/query/occlusion-query.html', bug=603168)
     self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282)
 
@@ -159,6 +167,14 @@
 
     self.Fail('conformance2/reading/format-r11f-g11f-b10f.html',
         ['mac'], bug=1832) # khronos WebGL issue
+    self.Fail('deqp/functional/gles3/fborender/recreate_color_02.html',
+        ['mac'], bug=679682)
+    self.Fail('deqp/functional/gles3/fborender/resize_01.html',
+        ['mac'], bug=679682)
+    self.Fail('deqp/functional/gles3/fragmentoutput/basic.float.html',
+        ['mac'], bug=679684)
+    self.Fail('deqp/functional/gles3/fragmentoutput/array.float.html',
+        ['mac'], bug=679684)
 
     # Mac Retina NVIDIA
     self.Fail('deqp/functional/gles3/fbomultisample*',
@@ -304,6 +320,16 @@
         ['mac', ('nvidia', 0xfe9)], bug=483282)
 
     # Mac AMD
+    self.Fail('deqp/functional/gles3/fbomultisample.8_samples.html',
+        ['mac', 'amd'], bug=679686)
+    self.Fail('deqp/functional/gles3/fbomultisample.4_samples.html',
+        ['mac', 'amd'], bug=679686)
+    self.Fail('deqp/functional/gles3/fbomultisample.2_samples.html',
+        ['mac', 'amd'], bug=679686)
+    self.Fail('deqp/functional/gles3/pixelbufferobject.html',
+        ['mac', 'amd'], bug=679687)
+    self.Fail('deqp/functional/gles3/instancedrendering.html',
+        ['mac', 'amd'], bug=679689)
     self.Fail('conformance/glsl/bugs/bool-type-cast-bug-int-float.html',
         ['mac', 'amd'], bug=643866)
     self.Fail('conformance2/glsl3/bool-type-cast-bug-uint-ivec-uvec.html',
@@ -429,6 +455,14 @@
     self.Fail('deqp/functional/gles3/shaderoperator/common_functions.html',
         ['mac', ('amd', 0x679e)], bug=483282)
 
+    # Mac Multi-vendor failures.
+    self.Fail('deqp/functional/gles3/fragmentoutput/random_00.html',
+        ['mac', 'amd', 'intel'], bug=679690)
+    self.Fail('deqp/functional/gles3/fragmentoutput/random_02.html',
+        ['mac', 'amd', 'intel'], bug=679690)
+    self.Fail('deqp/functional/gles3/fbocolorbuffer/clear.html',
+        ['mac', 'amd', 'intel'], bug=679691)
+
     # Mac Intel
 
     self.Fail(
@@ -456,6 +490,8 @@
       'conformance2/textures/webgl_canvas/tex-3d-rgb9_e5-rgb-half_float.html',
       ['sierra', 'intel'], bug=663188)
 
+    self.Fail('conformance2/textures/misc/angle-stuck-depth-textures.html',
+        ['mac', 'intel'], bug=679692)
     self.Fail('deqp/functional/gles3/fbomultisample*',
         ['mac', 'intel'], bug=641209)
     self.Fail('deqp/functional/gles3/texturefiltering/2d_combinations_01.html',
@@ -571,6 +607,8 @@
                ['linux'], bug=627525)
     self.Fail('conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html',
         ['linux'], bug=483282)
+    self.Fail('conformance2/textures/image_bitmap_from_image/' +
+              'tex-3d-r16f-red-float.html', ['linux'], bug=679695)
 
     # Linux Multi-vendor failures.
     self.Skip('deqp/data/gles3/shaders/qualification_order.html',
@@ -588,6 +626,9 @@
         ['linux', 'nvidia'], bug=618447)
     self.Fail('conformance/glsl/bugs/unary-minus-operator-float-bug.html',
         ['linux', 'nvidia'], bug=672380)
+    self.Fail('conformance2/textures/image_bitmap_from_canvas/' +
+        'tex-3d-srgb8_alpha8-rgba-unsigned_byte.html',
+        ['linux', 'nvidia'], bug=679677)
 
     # Linux Intel
     self.Fail('conformance2/extensions/ext-color-buffer-float.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 6d8b16b..c7393aea0 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -110,6 +110,10 @@
     # ========================
     # Fails on all platforms
 
+    self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html',
+        bug=678850)
+    self.Fail('conformance/attribs/gl-vertexattribpointer.html', bug=678850)
+
     # Need to add detection of feedback loops with multiple render targets.
     self.Fail('conformance/extensions/webgl-draw-buffers-feedback-loop.html',
         bug=1619) # angle bug ID
@@ -136,6 +140,8 @@
         ['win', 'nvidia'], bug=630860)
     self.Fail('conformance/glsl/bugs/unary-minus-operator-float-bug.html',
         ['win', 'nvidia'], bug=672380)
+    self.Fail('conformance/extensions/ext-sRGB.html',
+        ['win', 'nvidia', 'no_passthrough'], bug=679696)
 
     # Win7 / Intel failures
     self.Fail('conformance/textures/misc/' +
@@ -225,8 +231,8 @@
         ['win10', 'intel', 'opengl'], bug=1007) # angle bug ID
 
     # Win / Passthrough command decoder
-    self.Fail('conformance/attribs/gl-vertexattribpointer.html',
-        ['win', 'passthrough', 'd3d11'], bug=1523) # angle bug ID
+    self.Fail('conformance/extensions/ext-sRGB.html',
+        ['win', 'passthrough', 'd3d11'], bug=679696)
     self.Fail('conformance/extensions/angle-instanced-arrays.html',
         ['win', 'passthrough', 'd3d11'], bug=1523) # angle bug ID
     self.Fail('conformance/extensions/ext-disjoint-timer-query.html',
@@ -287,8 +293,6 @@
         ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID
     self.Fail('conformance/more/functions/texSubImage2DHTMLBadArgs.html',
         ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID
-    self.Fail('conformance/more/functions/vertexAttribPointerBadArgs.html',
-        ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID
     self.Fail('conformance/reading/read-pixels-test.html',
         ['win', 'passthrough', 'd3d11'], bug=1639) # angle bug ID
     self.Fail('conformance/renderbuffers/feedback-loop.html',
@@ -369,6 +373,8 @@
     self.Flaky('conformance/textures/video/' +
                'tex-2d-rgb-rgb-unsigned_short_5_6_5.html',
                ['linux'], bug=627525)
+    self.Fail('conformance/extensions/webgl-compressed-texture-etc.html',
+        bug=679678)
 
     # NVIDIA
     self.Flaky('conformance/extensions/oes-element-index-uint.html',
@@ -436,6 +442,10 @@
     # The following tests timed out on android, so skip them for now.
     self.Skip('conformance/textures/image_bitmap_from_video/*',
         ['android'], bug=585108)
+
+    self.Fail('conformance/textures/misc/' +
+        'copytexsubimage2d-large-partial-copy-corruption.html',
+        ['android'], bug=679697)
     # The following WebView crashes are causing problems with further
     # tests in the suite, so skip them for now.
     self.Skip('conformance/textures/video/' +
@@ -554,9 +564,6 @@
               ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951)
     self.Fail('conformance/textures/image_data/*',
               ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951)
-    self.Fail('conformance/textures/misc/' +
-              'copy-tex-sub-image-2d-partial-texture.html',
-              ['android', ('qualcomm', 'Adreno (TM) 418')], bug=643361)
     self.Fail('conformance/textures/svg_image/*',
               ['android', ('qualcomm', 'Adreno (TM) 418')], bug=610951)
     self.Fail('conformance/textures/video/*',
@@ -669,11 +676,6 @@
               'copy-tex-image-and-sub-image-2d.html',
               ['android', ('qualcomm', 'Adreno (TM) 420')], bug=499555)
     self.Fail('conformance/textures/misc/' +
-              'copy-tex-sub-image-2d-partial-texture.html',
-              ['android',
-               ('qualcomm', 'Adreno (TM) 420'),
-               ('qualcomm', 'Adreno (TM) 430')], bug=643361)
-    self.Fail('conformance/textures/misc/' +
               'tex-image-and-sub-image-2d-with-array-buffer-view.html',
               ['android',
                ('qualcomm', 'Adreno (TM) 420'),
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index c23f1a1..764125ce 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -61,6 +61,7 @@
 #elif defined(OS_WIN)
 #include "content/child/font_warmup_win.h"
 #include "third_party/WebKit/public/web/win/WebFontRendering.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/ports/SkFontMgr.h"
 #include "third_party/skia/include/ports/SkTypeface_win.h"
 #include "ui/gfx/win/direct_write.h"
@@ -438,7 +439,7 @@
       base::MakeUnique<LayoutTestDependenciesImpl>());
 
 #if defined(OS_WIN)
-  RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite());
+  RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite().get());
 #endif
 }
 
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 02b50aed..c50f745 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -24,6 +24,7 @@
 #include "content/test/test_render_view_host.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "net/base/load_flags.h"
+#include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
 #include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
 #include "third_party/WebKit/public/web/WebSandboxFlags.h"
@@ -412,7 +413,8 @@
     // TODO(mkwst): The initiator origin here is incorrect.
     BeginNavigationParams begin_params(
         std::string(), net::LOAD_NORMAL, has_user_gesture, false,
-        REQUEST_CONTEXT_TYPE_HYPERLINK, url::Origin());
+        REQUEST_CONTEXT_TYPE_HYPERLINK,
+        blink::WebMixedContentContextType::Blockable, url::Origin());
     CommonNavigationParams common_params;
     common_params.url = url;
     common_params.referrer = Referrer(GURL(), blink::WebReferrerPolicyDefault);
diff --git a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
index 707b5a4..779e9b70 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
@@ -7,8 +7,8 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_scheduler.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_uuid.h"
@@ -150,7 +150,7 @@
   }
 
  protected:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskScheduler scoped_task_scheduler_;
 
   scoped_refptr<BluetoothAdapter> adapter_;
 
diff --git a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc
index ee4d814..74ac10a 100644
--- a/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_socket_bluez_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_async_task_scheduler.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -175,6 +176,7 @@
 
  protected:
   base::MessageLoop message_loop_;
+  base::test::ScopedAsyncTaskScheduler scoped_async_task_scheduler_;
 
   scoped_refptr<BluetoothAdapter> adapter_;
 
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
index 5aaaf08..cd588b54 100644
--- a/device/bluetooth/dbus/fake_bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -23,8 +23,8 @@
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "base/threading/worker_pool.h"
 #include "base/time/time.h"
 #include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
@@ -515,8 +515,12 @@
     return;
   }
 
-  base::WorkerPool::GetTaskRunner(false)
-      ->PostTask(FROM_HERE, base::Bind(&SimulatedProfileSocket, fds[0]));
+  base::PostTaskWithTraits(
+      FROM_HERE, base::TaskTraits()
+                     .WithShutdownBehavior(
+                         base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+                     .MayBlock(),
+      base::Bind(&SimulatedProfileSocket, fds[0]));
 
   base::ScopedFD fd(fds[1]);
 
diff --git a/docs/chromoting_android_hacking.md b/docs/chromoting_android_hacking.md
index 5eebdfea..1c3c8df 100644
--- a/docs/chromoting_android_hacking.md
+++ b/docs/chromoting_android_hacking.md
@@ -95,7 +95,6 @@
 <classpathentry kind="src" path="third_party/libjingle/source/talk/app/webrtc/javatests/src"/>
 <classpathentry kind="src" path="third_party/libjingle/source/talk/examples/android/src"/>
 <classpathentry kind="src" path="android_webview/java/src"/>
-<classpathentry kind="src" path="android_webview/java/generated_src"/>
 <classpathentry kind="src" path="android_webview/test/shell/src"/>
 <classpathentry kind="src" path="android_webview/unittestjava/src"/>
 <classpathentry kind="src" path="android_webview/javatests/src"/>
diff --git a/docs/memory-infra/README.md b/docs/memory-infra/README.md
index 5066a650..eb3252b 100644
--- a/docs/memory-infra/README.md
+++ b/docs/memory-infra/README.md
@@ -93,7 +93,7 @@
  * **UI**: Android only. Memory used by Android java bitmaps for the UI.
  * **V8**: Memory used by V8 Javascript engine.
  * **Web Cache**: Memory used by resources downloaded from the Web, like images
-   and scipts.
+   and scripts.
 
 The **tracing column in gray** reports memory that is used to collect all of the
 above information. This memory would not be used if tracing were not enabled,
@@ -107,6 +107,19 @@
 [gpu-memory]: probe-gpu.md
 [partalloc]:  /base/allocator/partition_allocator/PartitionAlloc.md
 
+## 'effective\_size' vs. 'size'
+
+This is a little like the difference between 'self time' and 'cumulative time'
+in a profiling tool. Size is the total amount of memory allocated/requested
+by a subsystem whereas effective size is the total amount of memory
+used/consumed by a subsystem. If Skia allocates 10mb via partition_alloc
+that memory would show up in the size of both Skia and partition_alloc
+but only in the effective size of Skia since although partition_alloc
+allocates the 10mb it does so on behalf of Skia which is responsible
+for the memory. Summing all effective sizes gives the total amount of
+memory used whereas summing size would give a number larger than the total
+amount of memory used.
+
 ## Related Pages
 
  * [Adding MemoryInfra Tracing to a Component](adding_memory_infra_tracing.md)
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 47f4a6ee..de1fbd6 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -401,8 +401,6 @@
                               content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
                               content::Source<WebContents>(web_contents()));
 
-  if (web_view_guest_delegate_)
-    web_view_guest_delegate_->OnDidInitialize();
   ExtensionsAPIClient::Get()->AttachWebContentsHelpers(web_contents());
   web_view_permission_helper_.reset(new WebViewPermissionHelper(this));
 
diff --git a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
index 373ff34..8abb15f 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
@@ -18,9 +18,6 @@
   // Called when context menu operation was handled.
   virtual bool HandleContextMenu(const content::ContextMenuParams& params) = 0;
 
-  // Called just after additional initialization is performed.
-  virtual void OnDidInitialize() = 0;
-
   // Shows the context menu for the guest.
   virtual void OnShowContextMenu(int request_id) = 0;
 
diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc
index 8a2baba..8e534acb 100644
--- a/extensions/renderer/api_test_base.cc
+++ b/extensions/renderer/api_test_base.cc
@@ -16,6 +16,7 @@
 #include "extensions/renderer/process_info_native_handler.h"
 #include "gin/converter.h"
 #include "gin/dictionary.h"
+#include "gin/modules/console.h"
 #include "mojo/edk/js/core.h"
 #include "mojo/edk/js/handle.h"
 #include "mojo/edk/js/support.h"
@@ -154,6 +155,9 @@
       "exports.$set('MatchAgainstEventFilter', function() { return [] });");
 
   gin::ModuleRegistry::From(env()->context()->v8_context())
+      ->AddBuiltinModule(env()->isolate(), gin::Console::kModuleName,
+                         gin::Console::GetModule(env()->isolate()));
+  gin::ModuleRegistry::From(env()->context()->v8_context())
       ->AddBuiltinModule(env()->isolate(), mojo::edk::js::Core::kModuleName,
                          mojo::edk::js::Core::GetModule(env()->isolate()));
   gin::ModuleRegistry::From(env()->context()->v8_context())
diff --git a/gin/per_isolate_data.cc b/gin/per_isolate_data.cc
index dd4ce9d..029b93d 100644
--- a/gin/per_isolate_data.cc
+++ b/gin/per_isolate_data.cc
@@ -29,7 +29,8 @@
     : isolate_(isolate),
       allocator_(allocator),
       access_mode_(access_mode),
-      task_runner_(task_runner) {
+      task_runner_(
+          task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get()) {
   isolate_->SetData(kEmbedderNativeGin, this);
 }
 
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index 42a331fb..6c28e708 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -106,16 +106,23 @@
 
     // TODO(alexclarke): Should we navigate to about:blank first if using
     // virtual time?
-    if (!args.empty() && !args[0].empty())
-      builder.SetInitialURL(GURL(args[0]));
-
-    web_contents_ = builder.Build();
-    if (!web_contents_) {
-      LOG(ERROR) << "Navigation failed";
-      browser_->Shutdown();
-      return;
+    if (args.empty())
+      args.push_back("about:blank");
+    for (auto it = args.rbegin(); it != args.rend(); ++it) {
+      GURL url(*it);
+      HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build();
+      if (!web_contents) {
+        LOG(ERROR) << "Navigation to " << url << " failed";
+        browser_->Shutdown();
+        return;
+      }
+      if (!web_contents_ && !RemoteDebuggingEnabled()) {
+        // TODO(jzfeng): Support observing multiple targets.
+        url_ = url;
+        web_contents_ = web_contents;
+        web_contents_->AddObserver(this);
+      }
     }
-    web_contents_->AddObserver(this);
   }
 
   void Shutdown() {
@@ -138,8 +145,6 @@
 
   // HeadlessWebContents::Observer implementation:
   void DevToolsTargetReady() override {
-    if (RemoteDebuggingEnabled())
-      return;
     web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
     devtools_client_->GetInspector()->GetExperimental()->AddObserver(this);
     devtools_client_->GetPage()->AddObserver(this);
@@ -400,6 +405,41 @@
   DISALLOW_COPY_AND_ASSIGN(HeadlessShell);
 };
 
+bool ValidateCommandLine(const base::CommandLine& command_line) {
+  if (!command_line.HasSwitch(::switches::kRemoteDebuggingPort)) {
+    if (command_line.GetArgs().size() <= 1)
+      return true;
+    LOG(ERROR) << "Open multiple tabs is only supported when the "
+               << "remote debug port is set.";
+    return false;
+  }
+  if (command_line.HasSwitch(switches::kDumpDom)) {
+    LOG(ERROR) << "Dump DOM is disabled when remote debugging is enabled.";
+    return false;
+  }
+  if (command_line.HasSwitch(switches::kRepl)) {
+    LOG(ERROR) << "Evaluate Javascript is disabled "
+               << "when remote debugging is enabled.";
+    return false;
+  }
+  if (command_line.HasSwitch(switches::kScreenshot)) {
+    LOG(ERROR) << "Capture screenshot is disabled "
+               << "when remote debugging is enabled.";
+    return false;
+  }
+  if (command_line.HasSwitch(switches::kTimeout)) {
+    LOG(ERROR) << "Navigation timeout is disabled "
+               << "when remote debugging is enabled.";
+    return false;
+  }
+  if (command_line.HasSwitch(switches::kVirtualTimeBudget)) {
+    LOG(ERROR) << "Virtual time budget is disabled "
+               << "when remote debugging is enabled.";
+    return false;
+  }
+  return true;
+}
+
 int HeadlessShellMain(int argc, const char** argv) {
   RunChildProcessIfNeeded(argc, argv);
   HeadlessShell shell;
@@ -407,6 +447,9 @@
 
   // Enable devtools if requested.
   base::CommandLine command_line(argc, argv);
+  if (!ValidateCommandLine(command_line))
+    return EXIT_FAILURE;
+
   if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) {
     std::string address = kDevToolsHttpServerAddress;
     if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 15f57eb..4a2edda 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -8,6 +8,7 @@
     "tab_delegate.h",
     "tab_dialog_delegate.h",
     "tab_model.h",
+    "tab_model_list.h",
     "tab_model_observer.h",
     "tab_model_order_controller.h",
     "tab_model_synced_window_delegate.h",
@@ -36,6 +37,7 @@
   ]
   deps = [
     ":tabs",
+    ":tabs_internal_arc",
     "//base",
     "//components/content_settings/core/browser",
     "//components/favicon/core",
@@ -106,12 +108,26 @@
     "//ui/base",
     "//url",
   ]
+  allow_circular_includes_from = [ ":tabs_internal_arc" ]
   libs = [
     "CoreLocation.framework",
     "UIKit.framework",
   ]
 }
 
+source_set("tabs_internal_arc") {
+  sources = [
+    "tab_model_list.mm",
+  ]
+  deps = [
+    ":tabs",
+    "//base",
+    "//ios/chrome/browser/browser_state",
+  ]
+  libs = [ "Foundation.framework" ]
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
 source_set("unit_tests") {
   testonly = true
   sources = [
@@ -122,6 +138,7 @@
   deps = [
     ":tabs",
     ":tabs_internal",
+    ":unit_tests_arc",
     "//base",
     "//components/bookmarks/test",
     "//components/history/core/browser",
@@ -147,3 +164,20 @@
     "//third_party/ocmock",
   ]
 }
+
+source_set("unit_tests_arc") {
+  testonly = true
+  sources = [
+    "tab_model_list_unittest.mm",
+  ]
+  deps = [
+    ":tabs",
+    ":tabs_internal",
+    "//base",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/sessions:test_support",
+    "//ios/web:test_support",
+    "//testing/gtest",
+  ]
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 8bfb11f..aa4cd9a 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -30,6 +30,7 @@
 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
 #include "ios/chrome/browser/tab_parenting_global_observer.h"
 #import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
 #import "ios/chrome/browser/tabs/tab_model_order_controller.h"
 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
@@ -299,6 +300,9 @@
                       selector:@selector(applicationWillEnterForeground:)
                           name:UIApplicationWillEnterForegroundNotification
                         object:nil];
+
+    // Associate with ios::ChromeBrowserState.
+    RegisterTabModelWithChromeBrowserState(_browserState, self);
   }
   return self;
 }
@@ -732,6 +736,9 @@
 // NOTE: This can be called multiple times, so must be robust against that.
 - (void)browserStateDestroyed {
   [[NSNotificationCenter defaultCenter] removeObserver:self];
+  if (_browserState) {
+    UnregisterTabModelFromChromeBrowserState(_browserState, self);
+  }
   _browserState = nullptr;
 }
 
diff --git a/ios/chrome/browser/tabs/tab_model_list.h b/ios/chrome/browser/tabs/tab_model_list.h
new file mode 100644
index 0000000..bbba490
--- /dev/null
+++ b/ios/chrome/browser/tabs/tab_model_list.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 IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_
+#define IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_
+
+#import <Foundation/Foundation.h>
+
+// This file contains free functions to help maintain a 1:N relationship
+// between an ios::ChromeBrowserState and multiple TabModels.
+
+@class TabModel;
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// Registers |tab_model| as associated to |browser_state|. The object will
+// be retained until |UnregisterTabModelFromChromeBrowserState| is called.
+// It is an error if |tab_model is already registered as associated to
+// |browser_state|.
+void RegisterTabModelWithChromeBrowserState(
+    ios::ChromeBrowserState* browser_state,
+    TabModel* tab_model);
+
+// Unregisters the association between |tab_model| and |browser_state|.
+// It is an error if no such association exists.
+void UnregisterTabModelFromChromeBrowserState(
+    ios::ChromeBrowserState* browser_state,
+    TabModel* tab_model);
+
+// Returns the list of all TabModels associated with |browser_state|.
+NSArray<TabModel*>* GetTabModelsForChromeBrowserState(
+    ios::ChromeBrowserState* browser_state);
+
+#endif  // IOS_CHROME_BROWSER_TABS_TAB_MODEL_LIST_H_
diff --git a/ios/chrome/browser/tabs/tab_model_list.mm b/ios/chrome/browser/tabs/tab_model_list.mm
new file mode 100644
index 0000000..b9562232
--- /dev/null
+++ b/ios/chrome/browser/tabs/tab_model_list.mm
@@ -0,0 +1,87 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/tabs/tab_model_list.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Wrapper around a NSMutableArray<TabModel> allowing to bind it to a
+// base::SupportsUserData. Any base::SupportsUserData that owns this
+// wrapper will owns the reference to the TabModels.
+class TabModelList : public base::SupportsUserData::Data {
+ public:
+  TabModelList();
+  ~TabModelList() override;
+
+  static TabModelList* GetForBrowserState(
+      ios::ChromeBrowserState* browser_state,
+      bool create);
+
+  NSMutableSet<TabModel*>* tab_models() const { return tab_models_; }
+
+ private:
+  NSMutableSet<TabModel*>* tab_models_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabModelList);
+};
+
+const char kTabModelListKey = 0;
+
+TabModelList::TabModelList() : tab_models_([[NSMutableSet alloc] init]) {}
+
+TabModelList::~TabModelList() {
+  // TabModelList is destroyed during base::SupportsUserData destruction. At
+  // that point, all TabModels must have been unregistered already.
+  DCHECK_EQ([tab_models_ count], 0u);
+}
+
+// static
+TabModelList* TabModelList::GetForBrowserState(
+    ios::ChromeBrowserState* browser_state,
+    bool create) {
+  TabModelList* tab_model_list =
+      static_cast<TabModelList*>(browser_state->GetUserData(&kTabModelListKey));
+  if (!tab_model_list && create) {
+    // The ownership of TabModelList is transfered to base::SupportsUserData
+    // via the SetUserData call (should take a std::unique_ptr<>).
+    tab_model_list = new TabModelList;
+    browser_state->SetUserData(&kTabModelListKey, tab_model_list);
+  }
+  return tab_model_list;
+}
+}  // namespace
+
+void RegisterTabModelWithChromeBrowserState(
+    ios::ChromeBrowserState* browser_state,
+    TabModel* tab_model) {
+  NSMutableSet<TabModel*>* tab_models =
+      TabModelList::GetForBrowserState(browser_state, true)->tab_models();
+  DCHECK(![tab_models containsObject:tab_model]);
+  [tab_models addObject:tab_model];
+}
+
+void UnregisterTabModelFromChromeBrowserState(
+    ios::ChromeBrowserState* browser_state,
+    TabModel* tab_model) {
+  NSMutableSet<TabModel*>* tab_models =
+      TabModelList::GetForBrowserState(browser_state, false)->tab_models();
+  DCHECK([tab_models containsObject:tab_model]);
+  [tab_models removeObject:tab_model];
+}
+
+NSArray<TabModel*>* GetTabModelsForChromeBrowserState(
+    ios::ChromeBrowserState* browser_state) {
+  TabModelList* tab_model_list =
+      TabModelList::GetForBrowserState(browser_state, false);
+  return tab_model_list ? [tab_model_list->tab_models() allObjects] : nil;
+}
diff --git a/ios/chrome/browser/tabs/tab_model_list_unittest.mm b/ios/chrome/browser/tabs/tab_model_list_unittest.mm
new file mode 100644
index 0000000..d8d6730
--- /dev/null
+++ b/ios/chrome/browser/tabs/tab_model_list_unittest.mm
@@ -0,0 +1,75 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/tabs/tab_model_list.h"
+
+#import "base/mac/scoped_nsobject.h"
+#include "base/memory/ptr_util.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/sessions/test_session_service.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+class TabModelListTest : public PlatformTest {
+ public:
+  TabModelListTest() {
+    TestChromeBrowserState::Builder test_cbs_builder;
+    chrome_browser_state_ = test_cbs_builder.Build();
+  }
+
+  TabModel* CreateTabModel() {
+    return [[TabModel alloc]
+        initWithSessionWindow:nil
+               sessionService:[[TestSessionService alloc] init]
+                 browserState:chrome_browser_state_.get()];
+  }
+
+  NSArray<TabModel*>* RegisteredTabModels() {
+    return GetTabModelsForChromeBrowserState(chrome_browser_state_.get());
+  }
+
+ private:
+  web::TestWebThreadBundle thread_bundle_;
+  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabModelListTest);
+};
+
+TEST_F(TabModelListTest, RegisterAndUnregister) {
+  EXPECT_EQ([RegisteredTabModels() count], 0u);
+
+  TabModel* tab_model = CreateTabModel();
+  EXPECT_EQ([RegisteredTabModels() count], 1u);
+  EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model],
+            static_cast<NSUInteger>(NSNotFound));
+
+  [tab_model browserStateDestroyed];
+
+  EXPECT_EQ([RegisteredTabModels() count], 0u);
+}
+
+TEST_F(TabModelListTest, SupportsMultipleTabModel) {
+  EXPECT_EQ([RegisteredTabModels() count], 0u);
+
+  TabModel* tab_model1 = CreateTabModel();
+  EXPECT_EQ([RegisteredTabModels() count], 1u);
+  EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model1],
+            static_cast<NSUInteger>(NSNotFound));
+
+  TabModel* tab_model2 = CreateTabModel();
+  EXPECT_EQ([RegisteredTabModels() count], 2u);
+  EXPECT_NE([RegisteredTabModels() indexOfObject:tab_model2],
+            static_cast<NSUInteger>(NSNotFound));
+
+  [tab_model1 browserStateDestroyed];
+  [tab_model2 browserStateDestroyed];
+
+  EXPECT_EQ([RegisteredTabModels() count], 0u);
+}
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm
index d99a886..4d2e9068 100644
--- a/ios/chrome/browser/tabs/tab_model_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -147,7 +147,7 @@
     TestChromeBrowserState::Builder test_cbs_builder;
     chrome_browser_state_ = test_cbs_builder.Build();
 
-    sessionWindow_.reset([[SessionWindowIOS new] retain]);
+    sessionWindow_.reset([[SessionWindowIOS alloc] init]);
     // Create tab model with just a dummy session service so the async state
     // saving doesn't trigger unless actually wanted.
     base::scoped_nsobject<TestSessionService> test_service(
diff --git a/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
index 73bee7c..c9389ec 100644
--- a/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
@@ -363,7 +363,7 @@
       ^bool(void) {
         return [audience updated];
       },
-      nullptr, delay);
+      false, delay);
   EXPECT_TRUE([audience updated]);
   // Reset |audience|.
   [audience setUpdated:NO];
@@ -410,7 +410,7 @@
       ^bool(void) {
         return [audience updated];
       },
-      nullptr, delay);
+      false, delay);
   EXPECT_TRUE([audience updated]);
   // Reset |audience|.
   [audience setUpdated:NO];
@@ -443,7 +443,7 @@
       ^bool(void) {
         return [audience2 updated];
       },
-      nullptr, delay);
+      false, delay);
   EXPECT_TRUE([audience2 updated]);
 }
 
diff --git a/ios/chrome/browser/ui/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen_controller.mm
index f964931..cf4902f 100644
--- a/ios/chrome/browser/ui/fullscreen_controller.mm
+++ b/ios/chrome/browser/ui/fullscreen_controller.mm
@@ -144,8 +144,6 @@
 - (void)decrementFullScreenLock;
 // Called when the application is about to be the foreground application.
 - (void)applicationWillEnterForeground:(NSNotification*)notification;
-// TODO(shreyasv): Make the following methods act on a WebViewScrollView proxy
-// instead of taking in a UIScrollView directly.
 // Called from -webViewScrollViewDidScroll: Returns YES if the scroll should be
 // ignored.
 - (BOOL)shouldIgnoreScroll:(CRWWebViewScrollViewProxy*)webViewScrollViewProxy;
@@ -294,8 +292,8 @@
                selector:@selector(decrementFullScreenLock)
                    name:ios_internal::kSideSwipeDidStopNotification
                  object:nil];
-    // TODO(jbbegue): Evaluate using a listener instead of a notification
-    // crbug/451373.
+    // TODO(crbug.com/451373): Evaluate using listeners instead of
+    // notifications.
     [center addObserver:self
                selector:@selector(overscrollActionsWillStart)
                    name:kOverscrollActionsWillStart
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm
index eabe37d..a94c646 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_perftest.mm
@@ -38,7 +38,7 @@
   }
   void SettleUI() {
     base::test::ios::WaitUntilCondition(
-        nil, nullptr, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay));
+        nil, false, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay));
   }
 };
 
diff --git a/ios/chrome/browser/ui/omnibox_perftest.mm b/ios/chrome/browser/ui/omnibox_perftest.mm
index e4e24f8..0c59ec7a 100644
--- a/ios/chrome/browser/ui/omnibox_perftest.mm
+++ b/ios/chrome/browser/ui/omnibox_perftest.mm
@@ -159,7 +159,7 @@
         ^bool() {
           return [keyboard_listener_ isKeyboardVisible];
         },
-        nullptr, base::TimeDelta());
+        false, base::TimeDelta());
     base::test::ios::TimeUntilCondition(
         ^{
           [textField resignFirstResponder];
@@ -167,7 +167,7 @@
         ^bool() {
           return ![keyboard_listener_ isKeyboardVisible];
         },
-        nullptr, base::TimeDelta());
+        false, base::TimeDelta());
     [textField removeFromSuperview];
     return elapsed;
   }
@@ -182,7 +182,7 @@
         ^bool() {
           return [keyboard_listener_ isKeyboardVisible];
         },
-        nullptr, base::TimeDelta());
+        false, base::TimeDelta());
   }
 
   // Performs necessary cleanup (so next pass of unit test can start from
@@ -197,7 +197,7 @@
         ^bool() {
           return ![keyboard_listener_ isKeyboardVisible];
         },
-        nullptr, base::TimeDelta());
+        false, base::TimeDelta());
   }
 
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm
index 5b93233..cb5dbce 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_controller_perftest.mm
@@ -257,9 +257,9 @@
       ^bool() {
         return !tab.webState->IsLoading();
       },
-      nullptr, base::TimeDelta::FromSecondsD(kMaxPageLoadDelay));
+      false, base::TimeDelta::FromSecondsD(kMaxPageLoadDelay));
   base::test::ios::WaitUntilCondition(
-      nil, nullptr, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay));
+      nil, false, base::TimeDelta::FromSecondsD(kMaxUICatchupDelay));
 }
 
 base::TimeDelta StackViewControllerPerfTest::OpenStackView() {
@@ -271,7 +271,7 @@
       ^bool() {
         return [delegate_ showAnimationEnded];
       },
-      nullptr, base::TimeDelta::FromSecondsD(kTotalSpinDelay));
+      false, base::TimeDelta::FromSecondsD(kTotalSpinDelay));
 }
 
 void StackViewControllerPerfTest::MainControllerShowTabSwitcher() {
@@ -326,7 +326,7 @@
       ^bool() {
         return [delegate_ dismissAnimationEnded];
       },
-      nullptr, base::TimeDelta::FromSecondsD(kTotalSpinDelay));
+      false, base::TimeDelta::FromSecondsD(kTotalSpinDelay));
 
   [view_controller_ dismissViewControllerAnimated:NO completion:nil];
   if (!reuse_svc_)
@@ -338,7 +338,7 @@
   // in the OS during view teardown to resolve, so that the view gets its
   // dismissal callbacks.
   base::test::ios::WaitUntilCondition(
-      nil, nullptr, base::TimeDelta::FromSecondsD(kSpinDelay));
+      nil, false, base::TimeDelta::FromSecondsD(kSpinDelay));
 
   return closeTime;
 }
diff --git a/ios/chrome/test/block_cleanup_test.h b/ios/chrome/test/block_cleanup_test.h
index 61ec9f5..09b4c288 100644
--- a/ios/chrome/test/block_cleanup_test.h
+++ b/ios/chrome/test/block_cleanup_test.h
@@ -22,7 +22,7 @@
   void SpinRunLoop(NSTimeInterval cleanup_time);
 
  private:
-  NSAutoreleasePool* block_cleanup_pool_;
+  id block_cleanup_pool_;
 };
 
 #endif  // IOS_CHROME_TEST_BLOCK_CLEANUP_TEST_H_
diff --git a/ios/chrome/test/block_cleanup_test.mm b/ios/chrome/test/block_cleanup_test.mm
index 06ac9e4c..5b35057 100644
--- a/ios/chrome/test/block_cleanup_test.mm
+++ b/ios/chrome/test/block_cleanup_test.mm
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #import "base/mac/scoped_nsobject.h"
+#import "base/mac/foundation_util.h"
 
 void BlockCleanupTest::SetUp() {
   block_cleanup_pool_ = [[NSAutoreleasePool alloc] init];
@@ -22,7 +23,7 @@
   // Drain the autorelease pool to finish cleaning up after blocks.
   // TODO(rohitrao): Can this be an EXPECT, so as to not crash the whole suite?
   DCHECK(block_cleanup_pool_);
-  [block_cleanup_pool_ release];
+  [base::mac::ObjCCastStrict<NSAutoreleasePool>(block_cleanup_pool_) release];
   block_cleanup_pool_ = nil;
 
   PlatformTest::TearDown();
diff --git a/ios/web/ios_web_resources.grd b/ios/web/ios_web_resources.grd
index 763a3f8c..193d0c6 100644
--- a/ios/web/ios_web_resources.grd
+++ b/ios/web/ios_web_resources.grd
@@ -18,6 +18,7 @@
       <include name="IDR_MOJO_UNICODE_JS" file="../../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_MOJO_VALIDATOR_JS" file="../../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_IOS_MOJO_SUPPORT_JS" file="webui/resources/support.js" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_IOS_CONSOLE_JS" file="webui/resources/console.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_IOS_MOJO_SYNC_MESSAGE_CHANNEL_JS" file="webui/resources/sync_message_channel.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_IOS_MOJO_HANDLE_UTIL_JS" file="webui/resources/handle_util.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_IOS_MOJO_CORE_JS" file="webui/resources/core.js" flattenhtml="true" type="BINDATA" />
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm
index 6ad0beb3..1b868c9d 100644
--- a/ios/web/public/test/web_test_with_web_state.mm
+++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -113,9 +113,7 @@
 }
 
 void WebTestWithWebState::WaitForCondition(ConditionBlock condition) {
-  base::MessageLoop* messageLoop = base::MessageLoop::current();
-  DCHECK(messageLoop);
-  base::test::ios::WaitUntilCondition(condition, messageLoop,
+  base::test::ios::WaitUntilCondition(condition, true,
                                       base::TimeDelta::FromSeconds(10));
 }
 
diff --git a/ios/web/webui/crw_web_ui_manager.mm b/ios/web/webui/crw_web_ui_manager.mm
index 298066ad..2efc12b7 100644
--- a/ios/web/webui/crw_web_ui_manager.mm
+++ b/ios/web/webui/crw_web_ui_manager.mm
@@ -226,6 +226,7 @@
       {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS},
       {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS},
       {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS},
+      {web::kConsoleModuleName, IDR_IOS_CONSOLE_JS},
       {web::kSyncMessageChannelModuleName,
        IDR_IOS_MOJO_SYNC_MESSAGE_CHANNEL_JS},
       {web::kHandleUtilModuleName, IDR_IOS_MOJO_HANDLE_UTIL_JS},
diff --git a/ios/web/webui/mojo_js_constants.cc b/ios/web/webui/mojo_js_constants.cc
index 5df3b6f0..ac6227f 100644
--- a/ios/web/webui/mojo_js_constants.cc
+++ b/ios/web/webui/mojo_js_constants.cc
@@ -6,6 +6,7 @@
 
 namespace web {
 
+const char kConsoleModuleName[] = "console";
 const char kSyncMessageChannelModuleName[] =
     "ios/mojo/public/js/sync_message_channel";
 const char kHandleUtilModuleName[] = "ios/mojo/public/js/handle_util";
diff --git a/ios/web/webui/mojo_js_constants.h b/ios/web/webui/mojo_js_constants.h
index e940a8516..3e08244 100644
--- a/ios/web/webui/mojo_js_constants.h
+++ b/ios/web/webui/mojo_js_constants.h
@@ -7,6 +7,7 @@
 
 namespace web {
 
+extern const char kConsoleModuleName[];
 extern const char kSyncMessageChannelModuleName[];
 extern const char kHandleUtilModuleName[];
 extern const char kSupportModuleName[];
diff --git a/ios/web/webui/resources/console.js b/ios/web/webui/resources/console.js
new file mode 100644
index 0000000..4368b00
--- /dev/null
+++ b/ios/web/webui/resources/console.js
@@ -0,0 +1,25 @@
+// 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.
+
+// Module "console"
+//
+// This module provides basic logging support. The reason to define this module
+// to forward calls to the |console| object exposed by the browser, instead of
+// using that object directly: mojo JS bindings are currently loaded using gin
+// and the |console| object is not always available. When the Mojo JS bindings
+// move away from gin, this module could be removed.
+
+define("console", [], function() {
+  /**
+   * Logs a message to the console.
+   * @param {string} message to log.
+   */
+  function log(message) {
+    console.log(message);
+  }
+
+  var exports = {};
+  exports.log = log;
+  return exports;
+});
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index 96e5d0b0..6723474 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -50,6 +50,7 @@
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/scoped_task_scheduler.h"
 #include "base/test/test_suite.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -1765,6 +1766,13 @@
     base::MessageLoop main_loop;
 #endif  // OS_WIN || USE_OZONE
 
+    base::test::ScopedTaskScheduler scoped_task_scheduler(&main_loop);
+
+    media::g_env =
+        reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>(
+            testing::AddGlobalTestEnvironment(
+                new media::VideoDecodeAcceleratorTestEnvironment()));
+
 #if defined(USE_OZONE)
     ui::OzonePlatform::InitializeForUI();
 #endif
@@ -1847,11 +1855,6 @@
 
   base::ShadowingAtExitManager at_exit_manager;
 
-  media::g_env =
-      reinterpret_cast<media::VideoDecodeAcceleratorTestEnvironment*>(
-          testing::AddGlobalTestEnvironment(
-              new media::VideoDecodeAcceleratorTestEnvironment()));
-
   return base::LaunchUnitTestsSerially(
       argc, argv,
       base::Bind(&media::VDATestSuite::Run, base::Unretained(&test_suite)));
diff --git a/mojo/public/js/router.js b/mojo/public/js/router.js
index 3f0d96b..9db1220 100644
--- a/mojo/public/js/router.js
+++ b/mojo/public/js/router.js
@@ -3,11 +3,12 @@
 // found in the LICENSE file.
 
 define("mojo/public/js/router", [
+  "console",
   "mojo/public/js/codec",
   "mojo/public/js/core",
   "mojo/public/js/connector",
   "mojo/public/js/validator",
-], function(codec, core, connector, validator) {
+], function(console, codec, core, connector, validator) {
 
   var Connector = connector.Connector;
   var MessageReader = codec.MessageReader;
@@ -117,8 +118,12 @@
       var reader = new MessageReader(message);
       var requestID = reader.requestID;
       var completer = this.completers_.get(requestID);
-      this.completers_.delete(requestID);
-      completer.resolve(message);
+      if (completer) {
+        this.completers_.delete(requestID);
+        completer.resolve(message);
+      } else {
+        console.log("Unexpected response with request ID: " + requestID);
+      }
     } else {
       if (this.incomingReceiver_)
         this.incomingReceiver_.accept(message);
@@ -127,10 +132,12 @@
 
   Router.prototype.handleInvalidIncomingMessage_ = function(message, error) {
     if (!this.testingController_) {
-      // TODO(yzshen): Consider logging and notifying the embedder.
+      // TODO(yzshen): Consider notifying the embedder.
       // TODO(yzshen): This should also trigger connection error handler.
       // Consider making accept() return a boolean and let the connector deal
       // with this, as the C++ code does.
+      console.log("Invalid message: " + validator.validationError[error]);
+
       this.close();
       return;
     }
diff --git a/net/base/arena.cc b/net/base/arena.cc
index eeb28633..3bf29a7 100644
--- a/net/base/arena.cc
+++ b/net/base/arena.cc
@@ -68,6 +68,7 @@
 
 void UnsafeArena::Reset() {
   blocks_.clear();
+  status_.bytes_allocated_ = 0;
 }
 
 void UnsafeArena::Reserve(size_t additional_space) {
@@ -83,6 +84,7 @@
 
 void UnsafeArena::AllocBlock(size_t size) {
   blocks_.push_back(Block(size));
+  status_.bytes_allocated_ += size;
 }
 
 UnsafeArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {}
diff --git a/net/base/arena.h b/net/base/arena.h
index 223517d..f9a31ac 100644
--- a/net/base/arena.h
+++ b/net/base/arena.h
@@ -16,6 +16,16 @@
 // Not thread-safe.
 class NET_EXPORT_PRIVATE UnsafeArena {
  public:
+  class Status {
+   private:
+    friend class UnsafeArena;
+    size_t bytes_allocated_;
+
+   public:
+    Status() : bytes_allocated_(0) {}
+    size_t bytes_allocated() const { return bytes_allocated_; }
+  };
+
   // Blocks allocated by this arena will be at least |block_size| bytes.
   explicit UnsafeArena(size_t block_size);
   ~UnsafeArena();
@@ -39,6 +49,8 @@
 
   void Reset();
 
+  Status status() const { return status_; }
+
  private:
   struct Block {
     std::unique_ptr<char[]> data;
@@ -57,6 +69,7 @@
 
   size_t block_size_;
   std::vector<Block> blocks_;
+  Status status_;
 };
 
 }  // namespace net
diff --git a/net/disk_cache/blockfile/file_ios.cc b/net/disk_cache/blockfile/file_ios.cc
index 5c9a6fad..47ff7f8 100644
--- a/net/disk_cache/blockfile/file_ios.cc
+++ b/net/disk_cache/blockfile/file_ios.cc
@@ -14,7 +14,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/threading/worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "net/base/net_errors.h"
 #include "net/disk_cache/blockfile/in_flight_io.h"
 #include "net/disk_cache/disk_cache.h"
@@ -121,8 +121,12 @@
       new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
   file->AddRef();  // Balanced on OnOperationComplete()
 
-  base::WorkerPool::PostTask(FROM_HERE,
-      base::Bind(&FileBackgroundIO::Read, operation.get()), true);
+  base::PostTaskWithTraits(
+      FROM_HERE, base::TaskTraits()
+                     .WithShutdownBehavior(
+                         base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+                     .MayBlock(),
+      base::Bind(&FileBackgroundIO::Read, operation.get()));
   OnOperationPosted(operation.get());
 }
 
@@ -133,8 +137,12 @@
       new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
   file->AddRef();  // Balanced on OnOperationComplete()
 
-  base::WorkerPool::PostTask(FROM_HERE,
-      base::Bind(&FileBackgroundIO::Write, operation.get()), true);
+  base::PostTaskWithTraits(
+      FROM_HERE, base::TaskTraits()
+                     .WithShutdownBehavior(
+                         base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
+                     .MayBlock(),
+      base::Bind(&FileBackgroundIO::Write, operation.get()));
   OnOperationPosted(operation.get());
 }
 
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc
index b4ad47d..eeef3b7 100644
--- a/net/disk_cache/disk_cache_perftest.cc
+++ b/net/disk_cache/disk_cache_perftest.cc
@@ -62,7 +62,7 @@
 
   ~DiskCachePerfTest() override {
     if (saved_fd_limit_ < kFdLimitForCacheTests)
-      MaybeSetFdLimit(kFdLimitForCacheTests);
+      MaybeSetFdLimit(saved_fd_limit_);
   }
 
  protected:
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h
index c94f5ac8..9dde5bf 100644
--- a/net/disk_cache/disk_cache_test_base.h
+++ b/net/disk_cache/disk_cache_test_base.h
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/test/scoped_async_task_scheduler.h"
 #include "base/threading/thread.h"
 #include "net/base/cache_type.h"
 #include "net/disk_cache/disk_cache.h"
@@ -56,6 +57,12 @@
  private:
   base::ScopedTempDir temp_dir_;
   std::unique_ptr<base::MessageLoop> message_loop_;
+
+  // Use a ScopedAsyncTaskScheduler instead of a ScopedTaskScheduler to allow
+  // disk_cache::InFlightIO::WaitForPendingIO to wait for TaskScheduler tasks
+  // from the main thread using WaitableEvents (this wouldn't work if
+  // TaskScheduler tasks ran on the main thread).
+  base::test::ScopedAsyncTaskScheduler scoped_async_task_scheduler_;
 };
 
 // Provides basic support for cache related tests.
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index bb980bd0d..62bed8c 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -312,30 +312,8 @@
   return true;
 }
 
-// static
-bool HttpUtil::HasHeader(const std::string& headers, const char* name) {
-  size_t name_len = strlen(name);
-  std::string::const_iterator it =
-      std::search(headers.begin(),
-                  headers.end(),
-                  name,
-                  name + name_len,
-                  base::CaseInsensitiveCompareASCII<char>());
-  if (it == headers.end())
-    return false;
-
-  // ensure match is prefixed by newline
-  if (it != headers.begin() && it[-1] != '\n')
-    return false;
-
-  // ensure match is suffixed by colon
-  if (it + name_len >= headers.end() || it[name_len] != ':')
-    return false;
-
-  return true;
-}
-
 namespace {
+
 // A header string containing any of the following fields will cause
 // an error. The list comes from the XMLHttpRequest standard.
 // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method
@@ -362,7 +340,8 @@
   "user-agent",
   "via",
 };
-}  // anonymous namespace
+
+}  // namespace
 
 // static
 bool HttpUtil::IsSafeHeader(const std::string& name) {
@@ -781,16 +760,6 @@
   return lang_list_with_q;
 }
 
-void HttpUtil::AppendHeaderIfMissing(const char* header_name,
-                                     const std::string& header_value,
-                                     std::string* headers) {
-  if (header_value.empty())
-    return;
-  if (HttpUtil::HasHeader(*headers, header_name))
-    return;
-  *headers += std::string(header_name) + ": " + header_value + "\r\n";
-}
-
 bool HttpUtil::HasStrongValidators(HttpVersion version,
                                    const std::string& etag_header,
                                    const std::string& last_modified_header,
diff --git a/net/http/http_util.h b/net/http/http_util.h
index 1ccf9cc..267b96400 100644
--- a/net/http/http_util.h
+++ b/net/http/http_util.h
@@ -74,11 +74,6 @@
                                     base::Time now,
                                     base::TimeDelta* retry_after);
 
-  // Scans the '\r\n'-delimited headers for the given header name.  Returns
-  // true if a match is found.  Input is assumed to be well-formed.
-  // TODO(darin): kill this
-  static bool HasHeader(const std::string& headers, const char* name);
-
   // Returns true if it is safe to allow users and scripts to specify the header
   // named |name|.
   static bool IsSafeHeader(const std::string& name);
@@ -210,12 +205,6 @@
   static std::string GenerateAcceptLanguageHeader(
       const std::string& raw_language_list);
 
-  // Helper. If |*headers| already contains |header_name| do nothing,
-  // otherwise add <header_name> ": " <header_value> to the end of the list.
-  static void AppendHeaderIfMissing(const char* header_name,
-                                    const std::string& header_value,
-                                    std::string* headers);
-
   // Returns true if the parameters describe a response with a strong etag or
   // last-modified header.  See section 13.3.3 of RFC 2616.
   // An empty string should be passed for missing headers.
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc
index 34c98483..3560e2f4 100644
--- a/net/http/http_util_unittest.cc
+++ b/net/http/http_util_unittest.cc
@@ -100,26 +100,6 @@
   }
 }
 
-TEST(HttpUtilTest, HasHeader) {
-  static const struct {
-    const char* const headers;
-    const char* const name;
-    bool expected_result;
-  } tests[] = {
-    { "", "foo", false },
-    { "foo\r\nbar", "foo", false },
-    { "ffoo: 1", "foo", false },
-    { "foo: 1", "foo", true },
-    { "foo: 1\r\nbar: 2", "foo", true },
-    { "fOO: 1\r\nbar: 2", "foo", true },
-    { "g: 0\r\nfoo: 1\r\nbar: 2", "foo", true },
-  };
-  for (size_t i = 0; i < arraysize(tests); ++i) {
-    bool result = HttpUtil::HasHeader(tests[i].headers, tests[i].name);
-    EXPECT_EQ(tests[i].expected_result, result);
-  }
-}
-
 TEST(HttpUtilTest, HeadersIterator) {
   std::string headers = "foo: 1\t\r\nbar: hello world\r\nbaz: 3 \r\n";
 
diff --git a/net/http2/decoder/decode_buffer_test.cc b/net/http2/decoder/decode_buffer_test.cc
index 35a9fbb..a4d10d7c 100644
--- a/net/http2/decoder/decode_buffer_test.cc
+++ b/net/http2/decoder/decode_buffer_test.cc
@@ -6,9 +6,6 @@
 
 #include <string>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/tools/http2_random.h"
@@ -68,7 +65,7 @@
   bool SlowDecodeField(DecodeBuffer* b,
                        size_t field_size,
                        size_t field_offset,
-                       const base::Callback<bool(DecodeBuffer*)>& fn,
+                       std::function<bool(DecodeBuffer*)> fn,
                        T* f) {
     VLOG(2) << "Remaining: " << b->Remaining();
     VLOG(2) << "field_size: " << field_size;
@@ -80,7 +77,7 @@
     uint32_t old = static_cast<uint32_t>(*f);
     VLOG(2) << "old: " << old;
     size_t old_decode_offset = decode_offset_;
-    bool done = fn.Run(b);
+    bool done = fn(b);
     VLOG(2) << "done: " << done;
     if (old_decode_offset == decode_offset_) {
       // Didn't do any decoding (may have no input, or may have already
@@ -106,35 +103,35 @@
     return done;
   }
 
-  bool decode_f1(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1);
-  }
-  bool decode_f2(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2);
-  }
-  bool decode_f3(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3);
-  }
-  bool decode_f4(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4);
-  }
-  bool decode_f5(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5);
-  }
-  bool decode_f6(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6);
-  }
-  bool decode_f7(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7);
-  }
-  bool decode_f8(TestStruct* p, DecodeBuffer* db) {
-    return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8);
-  }
 
   void SlowDecodeTestStruct(StringPiece input, TestStruct* p) {
     VLOG(2) << "############################################################";
     EXPECT_LE(10u, input.size());
     decode_offset_ = 0;
+    auto decode_f1 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeUInt8(kF1Offset, &decode_offset_, &p->f1);
+    };
+    auto decode_f2 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeUInt16(kF2Offset, &decode_offset_, &p->f2);
+    };
+    auto decode_f3 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeUInt24(kF3Offset, &decode_offset_, &p->f3);
+    };
+    auto decode_f4 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeUInt32(kF4Offset, &decode_offset_, &p->f4);
+    };
+    auto decode_f5 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeUInt31(kF5Offset, &decode_offset_, &p->f5);
+    };
+    auto decode_f6 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeEnum(4, kF6Offset, &decode_offset_, &p->f6);
+    };
+    auto decode_f7 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeEnum(1, kF7Offset, &decode_offset_, &p->f7);
+    };
+    auto decode_f8 = [this, p](DecodeBuffer* db) {
+      return db->SlowDecodeEnum(1, kF8Offset, &decode_offset_, &p->f8);
+    };
     while (input.size() > 0) {
       size_t size = input.size();
       // Sometimes check that zero length input is OK.
@@ -148,38 +145,14 @@
       VLOG(2) << "================= input size " << size;
       DecodeBuffer b(input.data(), size);
       size_t old_decode_offset = decode_offset_;
-      if (SlowDecodeField(&b, 1, kF1Offset,
-                          base::Bind(&DecodeBufferTest::decode_f1,
-                                     base::Unretained(this), p),
-                          &p->f1) &&
-          SlowDecodeField(&b, 2, kF2Offset,
-                          base::Bind(&DecodeBufferTest::decode_f2,
-                                     base::Unretained(this), p),
-                          &p->f2) &&
-          SlowDecodeField(&b, 3, kF3Offset,
-                          base::Bind(&DecodeBufferTest::decode_f3,
-                                     base::Unretained(this), p),
-                          &p->f3) &&
-          SlowDecodeField(&b, 4, kF4Offset,
-                          base::Bind(&DecodeBufferTest::decode_f4,
-                                     base::Unretained(this), p),
-                          &p->f4) &&
-          SlowDecodeField(&b, 4, kF5Offset,
-                          base::Bind(&DecodeBufferTest::decode_f5,
-                                     base::Unretained(this), p),
-                          &p->f5) &&
-          SlowDecodeField(&b, 4, kF6Offset,
-                          base::Bind(&DecodeBufferTest::decode_f6,
-                                     base::Unretained(this), p),
-                          &p->f6) &&
-          SlowDecodeField(&b, 1, kF7Offset,
-                          base::Bind(&DecodeBufferTest::decode_f7,
-                                     base::Unretained(this), p),
-                          &p->f7) &&
-          SlowDecodeField(&b, 1, kF8Offset,
-                          base::Bind(&DecodeBufferTest::decode_f8,
-                                     base::Unretained(this), p),
-                          &p->f8)) {
+      if (SlowDecodeField(&b, 1, kF1Offset, decode_f1, &p->f1) &&
+          SlowDecodeField(&b, 2, kF2Offset, decode_f2, &p->f2) &&
+          SlowDecodeField(&b, 3, kF3Offset, decode_f3, &p->f3) &&
+          SlowDecodeField(&b, 4, kF4Offset, decode_f4, &p->f4) &&
+          SlowDecodeField(&b, 4, kF5Offset, decode_f5, &p->f5) &&
+          SlowDecodeField(&b, 4, kF6Offset, decode_f6, &p->f6) &&
+          SlowDecodeField(&b, 1, kF7Offset, decode_f7, &p->f7) &&
+          SlowDecodeField(&b, 1, kF8Offset, decode_f8, &p->f8)) {
         EXPECT_TRUE(b.Empty());
         EXPECT_EQ(size, input.size());
         EXPECT_EQ(input.size(), b.Offset());  // All input consumed.
@@ -245,7 +218,6 @@
     ts.f2 = random_.Rand16();
     ts.f3 = random_.Rand32();
     ts.f4 = random_.Rand32();
-    // Ensure high-bit is set.
     ts.f5 = 0x80000000 | random_.Rand32();  // Ensure high-bit is set.
     ts.f6 = static_cast<TestEnumClass32>(random_.Rand32());
     ts.f7 = static_cast<TestEnumClass8>(random_.Rand8());
diff --git a/net/http2/decoder/decode_http2_structures_test.cc b/net/http2/decoder/decode_http2_structures_test.cc
index 4b09e7a..0a76bdc 100644
--- a/net/http2/decoder/decode_http2_structures_test.cc
+++ b/net/http2/decoder/decode_http2_structures_test.cc
@@ -14,8 +14,6 @@
 #include <stddef.h>
 #include <string>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/decoder/decode_buffer.h"
@@ -110,17 +108,6 @@
   // Set the fields of |*p| to random values.
   void Randomize(S* p) { ::net::test::Randomize(p, RandomPtr()); }
 
-  AssertionResult ValidatorForDecodeLeadingStructure(const S* expected,
-                                                     const DecodeBuffer& db,
-                                                     DecodeStatus status) {
-    if (expected != nullptr && *expected != structure_) {
-      return AssertionFailure()
-             << "Expected structs to be equal\nExpected: " << *expected
-             << "\n  Actual: " << structure_;
-    }
-    return AssertionSuccess();
-  }
-
   // Fully decodes the Structure at the start of data, and confirms it matches
   // *expected (if provided).
   void DecodeLeadingStructure(const S* expected, StringPiece data) {
@@ -130,20 +117,25 @@
     // The validator is called after each of the several times that the input
     // DecodeBuffer is decoded, each with a different segmentation of the input.
     // Validate that structure_ matches the expected value, if provided.
-    Validator validator =
-        base::Bind(&StructureDecoderTest::ValidatorForDecodeLeadingStructure,
-                   base::Unretained(this), expected);
+    Validator validator = [expected, this](
+        const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+      if (expected != nullptr && *expected != structure_) {
+        return AssertionFailure()
+               << "Expected structs to be equal\nExpected: " << *expected
+               << "\n  Actual: " << structure_;
+      }
+      return AssertionSuccess();
+    };
 
     // First validate that decoding is done and that we've advanced the cursor
     // the expected amount.
-    Validator wrapped_validator =
-        ValidateDoneAndOffset(S::EncodedSize(), validator);
+    validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
 
     // Decode several times, with several segmentations of the input buffer.
     fast_decode_count_ = 0;
     slow_decode_count_ = 0;
     EXPECT_TRUE(DecodeAndValidateSeveralWays(
-        &original, false /*return_non_zero_on_first*/, wrapped_validator));
+        &original, false /*return_non_zero_on_first*/, validator));
 
     if (!HasFailure()) {
       EXPECT_EQ(S::EncodedSize(), decode_offset_);
diff --git a/net/http2/decoder/http2_frame_decoder_test.cc b/net/http2/decoder/http2_frame_decoder_test.cc
index ee1e9e49..0d1d278 100644
--- a/net/http2/decoder/http2_frame_decoder_test.cc
+++ b/net/http2/decoder/http2_frame_decoder_test.cc
@@ -10,8 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector_listener.h"
@@ -38,24 +36,6 @@
 namespace {
 
 class Http2FrameDecoderTest : public RandomDecoderTest {
- public:
-  AssertionResult ValidatorForDecodePayloadExpectingError(
-      const FrameParts& expected,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeError);
-    VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-  }
-
-  AssertionResult ValidatorForBeyondMaximum(const FrameParts& expected,
-                                            const DecodeBuffer& input,
-                                            DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeError);
-    // The decoder detects this error after decoding the header, and without
-    // trying to decode the payload.
-    VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
-    VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-  }
 
  protected:
   void SetUp() override {
@@ -152,13 +132,6 @@
                                         validator);
   }
 
-  AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays(
-      const FrameParts& expected,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeDone);
-    VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-  }
 
   // Decode one frame's payload and confirm that the listener recorded the
   // expected FrameParts instance, and only one FrameParts instance. The
@@ -167,9 +140,11 @@
   AssertionResult DecodePayloadAndValidateSeveralWays(
       StringPiece payload,
       const FrameParts& expected) {
-    Validator validator = base::Bind(
-        &Http2FrameDecoderTest::ValidatorForDecodePayloadAndValidateSeveralWays,
-        base::Unretained(this), base::ConstRef(expected));
+    Validator validator = [&expected, this](
+        const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+      VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+    };
     ResetDecodeSpeedCounters();
     VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
         payload, ValidateDoneAndEmpty(validator)));
@@ -209,12 +184,14 @@
   template <size_t N>
   AssertionResult DecodePayloadExpectingError(const char (&buf)[N],
                                               const FrameParts& expected) {
+    auto validator = [&expected, this](const DecodeBuffer& input,
+                                       DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeError);
+      VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+    };
     ResetDecodeSpeedCounters();
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(
-        ToStringPiece(buf),
-        base::Bind(
-            &Http2FrameDecoderTest::ValidatorForDecodePayloadExpectingError,
-            base::Unretained(this), expected)));
+    EXPECT_TRUE(
+        DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator));
     EXPECT_GT(fast_decode_count_, 0u);
     EXPECT_GT(slow_decode_count_, 0u);
     return AssertionSuccess();
@@ -865,11 +842,17 @@
       Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED, 2);
   FrameParts expected(header);
   expected.has_frame_size_error = true;
+  auto validator = [&expected, this](const DecodeBuffer& input,
+                                     DecodeStatus status) -> AssertionResult {
+    VERIFY_EQ(status, DecodeStatus::kDecodeError);
+    // The decoder detects this error after decoding the header, and without
+    // trying to decode the payload.
+    VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize());
+    VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
+  };
   ResetDecodeSpeedCounters();
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(
-      ToStringPiece(kFrameData),
-      base::Bind(&Http2FrameDecoderTest::ValidatorForBeyondMaximum,
-                 base::Unretained(this), expected)));
+  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData),
+                                                  validator));
   EXPECT_GT(fast_decode_count_, 0u);
   EXPECT_GT(slow_decode_count_, 0u);
 }
diff --git a/net/http2/decoder/http2_structure_decoder_test.cc b/net/http2/decoder/http2_structure_decoder_test.cc
index 68479a1..3ff2f98 100644
--- a/net/http2/decoder/http2_structure_decoder_test.cc
+++ b/net/http2/decoder/http2_structure_decoder_test.cc
@@ -21,8 +21,6 @@
 #include <stddef.h>
 #include <string>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/decoder/decode_buffer.h"
@@ -102,12 +100,6 @@
     }
   }
 
-  AssertionResult ValidatorForDecodeLeadingStructure(const S* expected,
-                                                     const DecodeBuffer& db,
-                                                     DecodeStatus status) {
-    VERIFY_EQ(*expected, structure_);
-    return AssertionSuccess();
-  }
 
   // Fully decodes the Structure at the start of data, and confirms it matches
   // *expected (if provided).
@@ -118,17 +110,18 @@
     // The validator is called after each of the several times that the input
     // DecodeBuffer is decoded, each with a different segmentation of the input.
     // Validate that structure_ matches the expected value, if provided.
-    Validator validator =
-        (expected == nullptr)
-            ? base::Bind(&SucceedingValidator)
-            : base::Bind(&Http2StructureDecoderTest::
-                             ValidatorForDecodeLeadingStructure,
-                         base::Unretained(this), expected);
+    Validator validator;
+    if (expected != nullptr) {
+      validator = [expected, this](const DecodeBuffer& db,
+                                   DecodeStatus status) -> AssertionResult {
+        VERIFY_EQ(*expected, structure_);
+        return AssertionSuccess();
+      };
+    }
 
     // Before that, validate that decoding is done and that we've advanced
     // the cursor the expected amount.
-    Validator wrapped_validator =
-        ValidateDoneAndOffset(S::EncodedSize(), validator);
+    validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
 
     // Decode several times, with several segmentations of the input buffer.
     fast_decode_count_ = 0;
@@ -136,7 +129,7 @@
     incomplete_start_count_ = 0;
     incomplete_resume_count_ = 0;
     VERIFY_SUCCESS(DecodeAndValidateSeveralWays(
-        &original, kMayReturnZeroOnFirst, wrapped_validator));
+        &original, kMayReturnZeroOnFirst, validator));
     VERIFY_FALSE(HasFailure());
     VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset());
     VERIFY_EQ(S::EncodedSize(), original.Offset());
diff --git a/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
index e10fc50..5fa62d61 100644
--- a/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
@@ -8,7 +8,6 @@
 
 #include <string>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -88,9 +87,8 @@
   Http2FrameBuilder fb;
   fb.Append(Http2AltSvcFields{0xffff});  // The longest possible origin length.
   fb.Append("Too little origin!");
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&AbstractPayloadDecoderTest::SucceedingApproveSize)));
+  EXPECT_TRUE(
+      VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr));
 }
 
 class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest,
diff --git a/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
index 248ac0d..cddda79 100644
--- a/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
@@ -8,7 +8,6 @@
 
 #include <string>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -70,21 +69,17 @@
 class GoAwayPayloadDecoderTest
     : public AbstractPayloadDecoderTest<GoAwayPayloadDecoder,
                                         GoAwayPayloadDecoderPeer,
-                                        Listener> {
- public:
-  static bool ApproveSizeForTruncated(size_t size) {
-    return size != Http2GoAwayFields::EncodedSize();
-  }
-};
+                                        Listener> {};
 
 // Confirm we get an error if the payload is not long enough to hold
 // Http2GoAwayFields.
 TEST_F(GoAwayPayloadDecoderTest, Truncated) {
+  auto approve_size = [](size_t size) {
+    return size != Http2GoAwayFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM));
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&GoAwayPayloadDecoderTest::ApproveSizeForTruncated)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 class GoAwayOpaqueDataLengthTests
diff --git a/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
index 89bd29f..69bf56f 100644
--- a/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
@@ -8,7 +8,6 @@
 
 #include <string>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -103,12 +102,7 @@
 class HeadersPayloadDecoderTest
     : public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder,
                                                 HeadersPayloadDecoderPeer,
-                                                Listener> {
- public:
-  static bool ApproveSizeForTruncated(size_t size) {
-    return size != Http2PriorityFields::EncodedSize();
-  }
-};
+                                                Listener> {};
 
 INSTANTIATE_TEST_CASE_P(VariousPadLengths,
                         HeadersPayloadDecoderTest,
@@ -153,12 +147,14 @@
 // Confirm we get an error if the PRIORITY flag is set but the payload is
 // not long enough, regardless of the amount of (valid) padding.
 TEST_P(HeadersPayloadDecoderTest, Truncated) {
+  auto approve_size = [](size_t size) {
+    return size != Http2PriorityFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(),
                                 Random().OneIn(2)));
   EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
-      Http2FrameFlag::FLAG_PRIORITY, fb.buffer(),
-      base::Bind(&HeadersPayloadDecoderTest::ApproveSizeForTruncated),
+      Http2FrameFlag::FLAG_PRIORITY, fb.buffer(), approve_size,
       total_pad_length_));
 }
 
diff --git a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
index b49b15ef..5f998e4 100644
--- a/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
+++ b/net/http2/decoder/payload_decoders/payload_decoder_base_test_util.h
@@ -11,9 +11,6 @@
 
 #include <string>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/decoder/decode_buffer.h"
@@ -123,15 +120,13 @@
           class Listener,
           bool SupportedFrameType = true>
 class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest {
- public:
-  static bool SucceedingApproveSize(size_t size) { return true; }
 
  protected:
   // An ApproveSize function returns true to approve decoding the specified
   // size of payload, else false to skip that size. Typically used for negative
   // tests; for example, decoding a SETTINGS frame at all sizes except for
   // multiples of 6.
-  typedef base::Callback<bool(size_t size)> ApproveSize;
+  typedef std::function<bool(size_t size)> ApproveSize;
 
   AbstractPayloadDecoderTest() {}
 
@@ -196,14 +191,6 @@
     return payload_decoder_.ResumeDecodingPayload(mutable_state(), db);
   }
 
-  // Wrap |validator| in another one which will check that we've reached the
-  // expected state of kDecodeError with OnFrameSizeError having been called by
-  AssertionResult ValidatorForDecodePayloadAndValidateSeveralWays(
-      const FrameParts& expected) {
-    VERIFY_FALSE(listener_.IsInProgress());
-    VERIFY_EQ(1u, listener_.size());
-    VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
-  }
 
   // Decode one frame's payload and confirm that the listener recorded the
   // expected FrameParts instance, and only FrameParts instance. The payload
@@ -212,33 +199,13 @@
   AssertionResult DecodePayloadAndValidateSeveralWays(
       base::StringPiece payload,
       const FrameParts& expected) {
+    NoArgValidator validator = [&expected, this]() -> AssertionResult {
+      VERIFY_FALSE(listener_.IsInProgress());
+      VERIFY_EQ(1u, listener_.size());
+      VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
+    };
     return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-        payload, this->ValidateDoneAndEmpty(base::Bind(
-                     &AbstractPayloadDecoderTest::
-                         ValidatorForDecodePayloadAndValidateSeveralWays,
-                     base::Unretained(this), base::ConstRef(expected))));
-  }
-
-  // Wrap |validator| in another one which will check that we've reached the
-  // expected state of kDecodeError with OnFrameSizeError having been called by
-  // the payload decoder.
-  AssertionResult ValidatorForVerifyDetectsFrameSizeError(
-      const Http2FrameHeader& header,
-      const Validator& validator,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
-             << "; input.Remaining=" << input.Remaining();
-    VERIFY_EQ(DecodeStatus::kDecodeError, status);
-    VERIFY_FALSE(listener_.IsInProgress());
-    VERIFY_EQ(1u, listener_.size());
-    const FrameParts* frame = listener_.frame(0);
-    VERIFY_EQ(header, frame->frame_header);
-    VERIFY_TRUE(frame->has_frame_size_error);
-    // Verify did not get OnPaddingTooLong, as we should only ever produce
-    // one of these two errors for a single frame.
-    VERIFY_FALSE(frame->opt_missing_length);
-    return validator.Run(input, status);
+        payload, ValidateDoneAndEmpty(validator));
   }
 
   // Decode one frame's payload, expecting that the final status will be
@@ -254,13 +221,29 @@
       WrappedValidator wrapped_validator) {
     set_frame_header(header);
     // If wrapped_validator is not a RandomDecoderTest::Validator, make it so.
-    Validator validator = this->ToValidator(wrapped_validator);
+    Validator validator = ToValidator(wrapped_validator);
+    // And wrap that validator in another which will check that we've reached
+    // the expected state of kDecodeError with OnFrameSizeError having been
+    // called by the payload decoder.
+    validator = [header, validator, this](
+        const DecodeBuffer& input,
+        DecodeStatus status) -> ::testing::AssertionResult {
+      DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
+               << "; input.Remaining=" << input.Remaining();
+      VERIFY_EQ(DecodeStatus::kDecodeError, status);
+      VERIFY_FALSE(listener_.IsInProgress());
+      VERIFY_EQ(1u, listener_.size());
+      const FrameParts* frame = listener_.frame(0);
+      VERIFY_EQ(header, frame->frame_header);
+      VERIFY_TRUE(frame->has_frame_size_error);
+      // Verify did not get OnPaddingTooLong, as we should only ever produce
+      // one of these two errors for a single frame.
+      VERIFY_FALSE(frame->opt_missing_length);
+      return validator(input, status);
+    };
     VERIFY_AND_RETURN_SUCCESS(
-        PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-            payload, base::Bind(&AbstractPayloadDecoderTest::
-                                    ValidatorForVerifyDetectsFrameSizeError,
-                                base::Unretained(this), base::ConstRef(header),
-                                base::ConstRef(validator))));
+        PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
+                                                                    validator));
   }
 
   // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload
@@ -299,7 +282,7 @@
     bool validated = false;
     for (size_t real_payload_size = 0;
          real_payload_size <= unpadded_payload.size(); ++real_payload_size) {
-      if (!approve_size.Run(real_payload_size)) {
+      if (approve_size != nullptr && !approve_size(real_payload_size)) {
         continue;
       }
       VLOG(1) << "real_payload_size=" << real_payload_size;
@@ -320,8 +303,7 @@
       // checking stream ids.
       uint32_t stream_id = RandStreamId();
       Http2FrameHeader header(fb.size(), frame_type, flags, stream_id);
-      VERIFY_SUCCESS(VerifyDetectsFrameSizeError(
-          fb.buffer(), header, base::Bind(&SucceedingValidator)));
+      VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr));
       validated = true;
     }
     VERIFY_TRUE(validated);
@@ -406,23 +388,6 @@
     return flags;
   }
 
-  static ::testing::AssertionResult ValidatorForVerifyDetectsPaddingTooLong(
-      const Http2FrameHeader& header,
-      int expected_missing_length,
-      const Listener& listener,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    VERIFY_EQ(DecodeStatus::kDecodeError, status);
-    VERIFY_FALSE(listener.IsInProgress());
-    VERIFY_EQ(1u, listener.size());
-    const FrameParts* frame = listener.frame(0);
-    VERIFY_EQ(header, frame->frame_header);
-    VERIFY_TRUE(frame->opt_missing_length);
-    VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
-    // Verify did not get OnFrameSizeError.
-    VERIFY_FALSE(frame->has_frame_size_error);
-    return ::testing::AssertionSuccess();
-  }
 
   // Verify that we get OnPaddingTooLong when decoding payload, and that the
   // amount of missing padding is as specified. header.IsPadded must be true,
@@ -433,12 +398,23 @@
       int expected_missing_length) {
     set_frame_header(header);
     auto& listener = listener_;
+    Validator validator = [header, expected_missing_length, &listener](
+        const DecodeBuffer& input,
+        DecodeStatus status) -> ::testing::AssertionResult {
+      VERIFY_EQ(DecodeStatus::kDecodeError, status);
+      VERIFY_FALSE(listener.IsInProgress());
+      VERIFY_EQ(1u, listener.size());
+      const FrameParts* frame = listener.frame(0);
+      VERIFY_EQ(header, frame->frame_header);
+      VERIFY_TRUE(frame->opt_missing_length);
+      VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
+      // Verify did not get OnFrameSizeError.
+      VERIFY_FALSE(frame->has_frame_size_error);
+      return ::testing::AssertionSuccess();
+    };
     VERIFY_AND_RETURN_SUCCESS(
-        PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-            payload, base::Bind(&AbstractPaddablePayloadDecoderTest::
-                                    ValidatorForVerifyDetectsPaddingTooLong,
-                                header, expected_missing_length,
-                                base::ConstRef(listener))));
+        PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload,
+                                                                    validator));
   }
 
   // Verifies that we get OnPaddingTooLong for a padded frame payload whose
diff --git a/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
index c3696f7c..5733411 100644
--- a/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/ping_payload_decoder_test.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -61,11 +60,6 @@
     : public AbstractPayloadDecoderTest<PingPayloadDecoder,
                                         PingPayloadDecoderPeer,
                                         Listener> {
- public:
-  static bool ApproveSizeForWrongSize(size_t size) {
-    return size != Http2PingFields::EncodedSize();
-  }
-
  protected:
   Http2PingFields RandPingFields() {
     Http2PingFields fields;
@@ -77,13 +71,14 @@
 // Confirm we get an error if the payload is not the correct size to hold
 // exactly one Http2PingFields.
 TEST_F(PingPayloadDecoderTest, WrongSize) {
+  auto approve_size = [](size_t size) {
+    return size != Http2PingFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(RandPingFields());
   fb.Append(RandPingFields());
   fb.Append(RandPingFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&PingPayloadDecoderTest::ApproveSizeForWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 TEST_F(PingPayloadDecoderTest, Ping) {
diff --git a/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
index dabcba5..d40b07c 100644
--- a/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/priority_payload_decoder_test.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -57,11 +56,6 @@
     : public AbstractPayloadDecoderTest<PriorityPayloadDecoder,
                                         PriorityPayloadDecoderPeer,
                                         Listener> {
- public:
-  static bool ApproveSizeForWrongSize(size_t size) {
-    return size != Http2PriorityFields::EncodedSize();
-  }
-
  protected:
   Http2PriorityFields RandPriorityFields() {
     Http2PriorityFields fields;
@@ -73,12 +67,13 @@
 // Confirm we get an error if the payload is not the correct size to hold
 // exactly one Http2PriorityFields.
 TEST_F(PriorityPayloadDecoderTest, WrongSize) {
+  auto approve_size = [](size_t size) {
+    return size != Http2PriorityFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(RandPriorityFields());
   fb.Append(RandPriorityFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&PriorityPayloadDecoderTest::ApproveSizeForWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 TEST_F(PriorityPayloadDecoderTest, VariousPayloads) {
diff --git a/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
index ba1a815..f7d83836 100644
--- a/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
@@ -8,7 +8,6 @@
 
 #include <string>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -96,10 +95,6 @@
     : public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder,
                                                 PushPromisePayloadDecoderPeer,
                                                 Listener> {
- public:
-  static bool ApproveSizeForTruncated(size_t size) {
-    return size != Http2PushPromiseFields::EncodedSize();
-  }
 };
 
 INSTANTIATE_TEST_CASE_P(VariousPadLengths,
@@ -131,13 +126,14 @@
 // Confirm we get an error if the payload is not long enough for the required
 // portion of the payload, regardless of the amount of (valid) padding.
 TEST_P(PushPromisePayloadDecoderTest, Truncated) {
+  auto approve_size = [](size_t size) {
+    return size != Http2PushPromiseFields::EncodedSize();
+  };
   Http2PushPromiseFields push_promise{RandStreamId()};
   Http2FrameBuilder fb;
   fb.Append(push_promise);
-  EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
-      0, fb.buffer(),
-      base::Bind(&PushPromisePayloadDecoderTest::ApproveSizeForTruncated),
-      total_pad_length_));
+  EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size,
+                                                   total_pad_length_));
 }
 
 // Confirm we get an error if the PADDED flag is set but the payload is not
diff --git a/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
index 703d98ff..88bd803 100644
--- a/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -58,11 +57,6 @@
     : public AbstractPayloadDecoderTest<RstStreamPayloadDecoder,
                                         RstStreamPayloadDecoderPeer,
                                         Listener> {
- public:
-  static bool ApproveSizeForWrongSize(size_t size) {
-    return size != Http2RstStreamFields::EncodedSize();
-  }
-
  protected:
   Http2RstStreamFields RandRstStreamFields() {
     Http2RstStreamFields fields;
@@ -74,13 +68,14 @@
 // Confirm we get an error if the payload is not the correct size to hold
 // exactly one Http2RstStreamFields.
 TEST_F(RstStreamPayloadDecoderTest, WrongSize) {
+  auto approve_size = [](size_t size) {
+    return size != Http2RstStreamFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(RandRstStreamFields());
   fb.Append(RandRstStreamFields());
   fb.Append(RandRstStreamFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&RstStreamPayloadDecoderTest::ApproveSizeForWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 TEST_F(RstStreamPayloadDecoderTest, AllErrors) {
diff --git a/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
index 7a53797..4d26e1b 100644
--- a/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/settings_payload_decoder_test.cc
@@ -8,7 +8,6 @@
 
 #include <vector>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -78,17 +77,6 @@
     : public AbstractPayloadDecoderTest<SettingsPayloadDecoder,
                                         SettingsPayloadDecoderPeer,
                                         Listener> {
- public:
-  static bool ApproveSizeForSettingsWrongSize(size_t size) {
-    // Should get an error if size is not an integral multiple of the size
-    // of one setting.
-    return 0 != (size % Http2SettingFields::EncodedSize());
-  }
-
-  static bool ApproveSizeForSettingsAkcWrongSize(size_t size) {
-    return size != 0;
-  }
-
  protected:
   Http2SettingFields RandSettingsFields() {
     Http2SettingFields fields;
@@ -100,26 +88,27 @@
 // Confirm we get an error if the SETTINGS payload is not the correct size
 // to hold exactly zero or more whole Http2SettingFields.
 TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) {
+  auto approve_size = [](size_t size) {
+    // Should get an error if size is not an integral multiple of the size
+    // of one setting.
+    return 0 != (size % Http2SettingFields::EncodedSize());
+  };
   Http2FrameBuilder fb;
   fb.Append(RandSettingsFields());
   fb.Append(RandSettingsFields());
   fb.Append(RandSettingsFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(
-          &SettingsPayloadDecoderTest::ApproveSizeForSettingsWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 // Confirm we get an error if the SETTINGS ACK payload is not empty.
 TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) {
+  auto approve_size = [](size_t size) { return size != 0; };
   Http2FrameBuilder fb;
   fb.Append(RandSettingsFields());
   fb.Append(RandSettingsFields());
   fb.Append(RandSettingsFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      Http2FrameFlag::FLAG_ACK, fb.buffer(),
-      base::Bind(
-          &SettingsPayloadDecoderTest::ApproveSizeForSettingsAkcWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::FLAG_ACK, fb.buffer(),
+                                          approve_size));
 }
 
 // SETTINGS must have stream_id==0, but the payload decoder doesn't check that.
diff --git a/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc b/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
index 5517dab..5914b8166 100644
--- a/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
+++ b/net/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include "base/bind.h"
 #include "base/logging.h"
 #include "net/http2/decoder/frame_parts.h"
 #include "net/http2/decoder/frame_parts_collector.h"
@@ -60,10 +59,6 @@
     : public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder,
                                         WindowUpdatePayloadDecoderPeer,
                                         Listener> {
- public:
-  static bool ApproveSizeForWrongSize(size_t size) {
-    return size != Http2WindowUpdateFields::EncodedSize();
-  }
 
  protected:
   Http2WindowUpdateFields RandWindowUpdateFields() {
@@ -77,13 +72,14 @@
 // Confirm we get an error if the payload is not the correct size to hold
 // exactly one Http2WindowUpdateFields.
 TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) {
+  auto approve_size = [](size_t size) {
+    return size != Http2WindowUpdateFields::EncodedSize();
+  };
   Http2FrameBuilder fb;
   fb.Append(RandWindowUpdateFields());
   fb.Append(RandWindowUpdateFields());
   fb.Append(RandWindowUpdateFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(
-      0, fb.buffer(),
-      base::Bind(&WindowUpdatePayloadDecoderTest::ApproveSizeForWrongSize)));
+  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
 }
 
 TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) {
diff --git a/net/http2/hpack/decoder/hpack_block_decoder_test.cc b/net/http2/hpack/decoder/hpack_block_decoder_test.cc
index 421f0fc5..566963d 100644
--- a/net/http2/hpack/decoder/hpack_block_decoder_test.cc
+++ b/net/http2/hpack/decoder/hpack_block_decoder_test.cc
@@ -8,8 +8,6 @@
 
 #include <sstream>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "net/http2/decoder/decode_buffer.h"
 #include "net/http2/hpack/decoder/hpack_block_collector.h"
 #include "net/http2/hpack/http2_hpack_constants.h"
@@ -29,31 +27,6 @@
 namespace {
 
 class HpackBlockDecoderTest : public RandomDecoderTest {
- public:
-  AssertionResult VerifyExpected(const HpackBlockCollector& expected) {
-    VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
-  }
-
-  AssertionResult ValidateForSpecExample_C_2_1() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
-        HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
-        "custom-header"));
-  }
-
-  AssertionResult ValidateForSpecExample_C_2_2() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader(
-        HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path"));
-  }
-
-  AssertionResult ValidateForSpecExample_C_2_3() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
-        HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false,
-        "secret"));
-  }
-
-  AssertionResult ValidateForSpecExample_C_2_4() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2));
-  }
 
  protected:
   HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) {
@@ -112,9 +85,11 @@
 
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1
 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) {
-  NoArgValidator do_check =
-      base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_1,
-                 base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
+        HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
+        "custom-header"));
+  };
   EXPECT_TRUE(
       DecodeHpackExampleAndValidateSeveralWays(R"(
       40                                      | == Literal indexed ==
@@ -126,14 +101,15 @@
                                               |   custom-header
       )",
                                                ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2
 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) {
-  NoArgValidator do_check =
-      base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_2,
-                 base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader(
+        HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path"));
+  };
   EXPECT_TRUE(
       DecodeHpackExampleAndValidateSeveralWays(R"(
       04                                      | == Literal not indexed ==
@@ -144,14 +120,16 @@
                                               | -> :path: /sample/path
       )",
                                                ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3
 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) {
-  NoArgValidator do_check =
-      base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_3,
-                 base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader(
+        HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false,
+        "secret"));
+  };
   EXPECT_TRUE(
       DecodeHpackExampleAndValidateSeveralWays(R"(
       10                                      | == Literal never indexed ==
@@ -162,14 +140,14 @@
                                               | -> password: secret
       )",
                                                ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4
 TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) {
-  NoArgValidator do_check =
-      base::Bind(&HpackBlockDecoderTest::ValidateForSpecExample_C_2_4,
-                 base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2));
+  };
   EXPECT_TRUE(
       DecodeHpackExampleAndValidateSeveralWays(R"(
       82                                      | == Indexed - Add ==
@@ -177,7 +155,7 @@
                                               | -> :method: GET
       )",
                                                ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1
 TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) {
@@ -205,11 +183,12 @@
   expected.ExpectIndexedHeader(4);
   expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
                                           1, false, "www.example.com");
-  NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
-                                       base::Unretained(this), expected);
+  NoArgValidator do_check = [expected, this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+  };
   EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
       example, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 // http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1
@@ -254,11 +233,12 @@
                                           "Mon, 21 Oct 2013 20:13:21 GMT");
   expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader,
                                           46, false, "https://www.example.com");
-  NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
-                                       base::Unretained(this), expected);
+  NoArgValidator do_check = [expected, this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+  };
   EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays(
       example, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 // Generate a bunch of HPACK block entries to expect, use those expectations
@@ -303,11 +283,12 @@
   HpackBlockBuilder hbb;
   expected.AppendToHpackBlockBuilder(&hbb);
 
-  NoArgValidator do_check = base::Bind(&HpackBlockDecoderTest::VerifyExpected,
-                                       base::Unretained(this), expected);
+  NoArgValidator do_check = [expected, this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected));
+  };
   EXPECT_TRUE(
       DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 }  // namespace
diff --git a/net/http2/hpack/decoder/hpack_entry_decoder_test.cc b/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
index 34581fa..6a1c293f 100644
--- a/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
+++ b/net/http2/hpack/decoder/hpack_entry_decoder_test.cc
@@ -6,8 +6,6 @@
 
 // Tests of HpackEntryDecoder.
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "net/http2/hpack/decoder/hpack_entry_collector.h"
 #include "net/http2/hpack/tools/hpack_block_builder.h"
 #include "net/http2/tools/failure.h"
@@ -23,25 +21,6 @@
 namespace {
 
 class HpackEntryDecoderTest : public RandomDecoderTest {
- public:
-  AssertionResult ValidateIndexedHeader(uint32_t ndx) {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx));
-  }
-
-  AssertionResult ValidateForIndexedLiteralValue_Literal() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
-        HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header"));
-  }
-
-  AssertionResult ValidateForIndexedLiteralNameValue_Literal() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
-        HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
-        "custom-header"));
-  }
-
-  AssertionResult ValidateForDynamicTableSizeUpdate_Literal() {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31));
-  }
 
  protected:
   HpackEntryDecoderTest() : listener_(&collector_) {}
@@ -79,34 +58,34 @@
   {
     const char input[] = {0x82u};  // == Index 2 ==
     DecodeBuffer b(input);
-    NoArgValidator do_check =
-        base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
-                   base::Unretained(this), 2);
+    NoArgValidator do_check = [this]() {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
   collector_.Clear();
   {
     const char input[] = {0xfeu};  // == Index 126 ==
     DecodeBuffer b(input);
-    NoArgValidator do_check =
-        base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
-                   base::Unretained(this), 126);
+    NoArgValidator do_check = [this]() {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
   collector_.Clear();
   {
     const char input[] = {0xffu, 0x00};  // == Index 127 ==
     DecodeBuffer b(input);
-    NoArgValidator do_check =
-        base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
-                   base::Unretained(this), 127);
+    NoArgValidator do_check = [this]() {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
 }
 
@@ -116,12 +95,12 @@
     HpackBlockBuilder hbb;
     hbb.AppendIndexedHeader(ndx);
 
-    NoArgValidator do_check =
-        base::Bind(&HpackEntryDecoderTest::ValidateIndexedHeader,
-                   base::Unretained(this), ndx);
+    NoArgValidator do_check = [this, ndx]() {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
 }
 
@@ -132,11 +111,12 @@
       "\x0d"            // Value length (13)
       "custom-header";  // Value
   DecodeBuffer b(input, sizeof input - 1);
-  NoArgValidator do_check =
-      base::Bind(&HpackEntryDecoderTest::ValidateForIndexedLiteralValue_Literal,
-                 base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
+        HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header"));
+  };
   EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) {
@@ -148,45 +128,29 @@
       "custom-header";  // Value
 
   DecodeBuffer b(input, sizeof input - 1);
-  NoArgValidator do_check = base::Bind(
-      &HpackEntryDecoderTest::ValidateForIndexedLiteralNameValue_Literal,
-      base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
+        HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false,
+        "custom-header"));
+  };
   EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) {
   // Size update, length 31.
   const char input[] = "\x3f\x00";
   DecodeBuffer b(input, 2);
-  NoArgValidator do_check = base::Bind(
-      &HpackEntryDecoderTest::ValidateForDynamicTableSizeUpdate_Literal,
-      base::Unretained(this));
+  NoArgValidator do_check = [this]() {
+    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31));
+  };
   EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check)));
-  EXPECT_TRUE(do_check.Run());
+  EXPECT_TRUE(do_check());
 }
 
 class HpackLiteralEntryDecoderTest
     : public HpackEntryDecoderTest,
       public ::testing::WithParamInterface<HpackEntryType> {
- public:
-  AssertionResult ValidateForRandNameIndexAndLiteralValue(
-      uint32_t ndx,
-      bool value_is_huffman_encoded,
-      const string& value) {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
-        entry_type_, ndx, value_is_huffman_encoded, value));
-  }
-
-  AssertionResult ValidateForRandLiteralNameAndValue(
-      bool name_is_huffman_encoded,
-      const string& name,
-      bool value_is_huffman_encoded,
-      const string& value) {
-    VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
-        entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded,
-        value));
-  }
 
  protected:
   HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {}
@@ -209,12 +173,14 @@
     HpackBlockBuilder hbb;
     hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx,
                                        value_is_huffman_encoded, value);
-    NoArgValidator do_check = base::Bind(
-        &HpackLiteralEntryDecoderTest::ValidateForRandNameIndexAndLiteralValue,
-        base::Unretained(this), ndx, value_is_huffman_encoded, value);
+    NoArgValidator do_check = [this, ndx, value_is_huffman_encoded,
+                               value]() -> AssertionResult {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader(
+          entry_type_, ndx, value_is_huffman_encoded, value));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
 }
 
@@ -229,13 +195,16 @@
     HpackBlockBuilder hbb;
     hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name,
                                   value_is_huffman_encoded, value);
-    NoArgValidator do_check = base::Bind(
-        &HpackLiteralEntryDecoderTest::ValidateForRandLiteralNameAndValue,
-        base::Unretained(this), name_is_huffman_encoded, name,
-        value_is_huffman_encoded, value);
+    NoArgValidator do_check = [this, name_is_huffman_encoded, name,
+                               value_is_huffman_encoded,
+                               value]() -> AssertionResult {
+      VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader(
+          entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded,
+          value));
+    };
     EXPECT_TRUE(
         DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check)));
-    EXPECT_TRUE(do_check.Run());
+    EXPECT_TRUE(do_check());
   }
 }
 
diff --git a/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc b/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
index 0abf0c9..9f72eb6 100644
--- a/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
+++ b/net/http2/hpack/decoder/hpack_entry_type_decoder_test.cc
@@ -6,8 +6,6 @@
 
 #include <vector>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "net/http2/hpack/tools/hpack_block_builder.h"
 #include "net/http2/tools/failure.h"
@@ -24,19 +22,6 @@
 const bool kReturnNonZeroOnFirst = true;
 
 class HpackEntryTypeDecoderTest : public RandomDecoderTest {
- public:
-  AssertionResult ValidatorForDynamicTableSizeUpdate(uint32_t size) {
-    VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type());
-    VERIFY_EQ(size, decoder_.varint());
-    return AssertionSuccess();
-  }
-
-  AssertionResult ValidatorForHeaderWithIndex(const HpackEntryType entry_type,
-                                              uint32_t index) {
-    VERIFY_EQ(entry_type, decoder_.entry_type());
-    VERIFY_EQ(index, decoder_.varint());
-    return AssertionSuccess();
-  }
 
  protected:
   DecodeStatus StartDecoding(DecodeBuffer* b) override {
@@ -56,15 +41,17 @@
     HpackBlockBuilder bb;
     bb.AppendDynamicTableSizeUpdate(size);
     DecodeBuffer db(bb.buffer());
-    NoArgValidator validator = base::Bind(
-        &HpackEntryTypeDecoderTest::ValidatorForDynamicTableSizeUpdate,
-        base::Unretained(this), size);
+    NoArgValidator validator = [size, this]() -> AssertionResult {
+      VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type());
+      VERIFY_EQ(size, decoder_.varint());
+      return AssertionSuccess();
+    };
     EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
                                              ValidateDoneAndEmpty(validator)))
         << "\nentry_type=kDynamicTableSizeUpdate, size=" << size;
     // Run the validator again to make sure that DecodeAndValidateSeveralWays
     // did the right thing.
-    EXPECT_TRUE(validator.Run());
+    EXPECT_TRUE(validator());
   }
 }
 
@@ -80,15 +67,18 @@
       HpackBlockBuilder bb;
       bb.AppendEntryTypeAndVarint(entry_type, index);
       DecodeBuffer db(bb.buffer());
-      NoArgValidator validator =
-          base::Bind(&HpackEntryTypeDecoderTest::ValidatorForHeaderWithIndex,
-                     base::Unretained(this), entry_type, index);
+      NoArgValidator validator = [entry_type, index,
+                                  this]() -> AssertionResult {
+        VERIFY_EQ(entry_type, decoder_.entry_type());
+        VERIFY_EQ(index, decoder_.varint());
+        return AssertionSuccess();
+      };
       EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst,
                                                ValidateDoneAndEmpty(validator)))
           << "\nentry_type=" << entry_type << ", index=" << index;
       // Run the validator again to make sure that DecodeAndValidateSeveralWays
       // did the right thing.
-      EXPECT_TRUE(validator.Run());
+      EXPECT_TRUE(validator());
     }
   }
 }
diff --git a/net/http2/hpack/decoder/hpack_string_decoder_test.cc b/net/http2/hpack/decoder/hpack_string_decoder_test.cc
index e4afc61..614fa0d 100644
--- a/net/http2/hpack/decoder/hpack_string_decoder_test.cc
+++ b/net/http2/hpack/decoder/hpack_string_decoder_test.cc
@@ -6,8 +6,6 @@
 
 // Tests of HpackStringDecoder.
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/hpack/decoder/hpack_string_collector.h"
 #include "net/http2/hpack/decoder/hpack_string_decoder_listener.h"
@@ -74,32 +72,27 @@
     return collector_.Collected(s, huffman_encoded);
   }
 
-  // Note that base::Bind() makes a copy of |expected_str| even though it is
-  // taken as a constant reference, so even if MakeValidator is called with a
-  // C-style string that is cast to a temporary std::string that gets destroyed
-  // after the call to MakeValidator, |expected_str| is still valid later when
-  // the Validator is run.
-  AssertionResult StringValidator(const string& expected_str,
-                                  bool expected_huffman,
-                                  const DecodeBuffer& input,
-                                  DecodeStatus status) {
-    AssertionResult result = Collected(expected_str, expected_huffman);
-    if (result) {
-      VERIFY_EQ(collector_,
-                HpackStringCollector(expected_str, expected_huffman));
-    } else {
-      VERIFY_NE(collector_,
-                HpackStringCollector(expected_str, expected_huffman));
-    }
-    VLOG(2) << collector_.ToString();
-    collector_.Clear();
-    VLOG(2) << collector_;
-    return result;
-  }
+  // expected_str is a string rather than a const string& or StringPiece so that
+  // the lambda makes a copy of the string, and thus the string to be passed to
+  // Collected outlives the call to MakeValidator.
 
   Validator MakeValidator(const string& expected_str, bool expected_huffman) {
-    return base::Bind(&HpackStringDecoderTest::StringValidator,
-                      base::Unretained(this), expected_str, expected_huffman);
+    return
+        [expected_str, expected_huffman, this](
+            const DecodeBuffer& input, DecodeStatus status) -> AssertionResult {
+          AssertionResult result = Collected(expected_str, expected_huffman);
+          if (result) {
+            VERIFY_EQ(collector_,
+                      HpackStringCollector(expected_str, expected_huffman));
+          } else {
+            VERIFY_NE(collector_,
+                      HpackStringCollector(expected_str, expected_huffman));
+          }
+          VLOG(2) << collector_.ToString();
+          collector_.Clear();
+          VLOG(2) << collector_;
+          return result;
+        };
   }
 
   const StartMethod start_method_;
diff --git a/net/http2/hpack/decoder/hpack_varint_decoder_test.cc b/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
index e63e9f0..7cdc872 100644
--- a/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
+++ b/net/http2/hpack/decoder/hpack_varint_decoder_test.cc
@@ -15,8 +15,6 @@
 #include <sstream>
 #include <vector>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -38,16 +36,6 @@
 namespace {
 
 class HpackVarintDecoderTest : public RandomDecoderTest {
- public:
-  AssertionResult ValidatorForValueTooLarge(bool* validated,
-                                            uint32_t expected_offset,
-                                            const DecodeBuffer& db,
-                                            DecodeStatus status) {
-    *validated = true;
-    VERIFY_EQ(DecodeStatus::kDecodeError, status);
-    VERIFY_EQ(expected_offset, db.Offset());
-    return AssertionSuccess();
-  }
 
  protected:
   DecodeStatus StartDecoding(DecodeBuffer* b) override {
@@ -61,24 +49,19 @@
     return decoder_.Resume(b);
   }
 
-  AssertionResult ValidatorForDecodeSeveralWays(uint32_t expected_value,
-                                                const DecodeBuffer& db,
-                                                DecodeStatus status) {
-    if (decoder_.value() != expected_value) {
-      return AssertionFailure()
-             << "Value doesn't match expected: " << decoder_.value()
-             << " != " << expected_value;
-    }
-    return AssertionSuccess();
-  }
-
   void DecodeSeveralWays(uint32_t expected_value, uint32_t expected_offset) {
     // The validator is called after each of the several times that the input
     // DecodeBuffer is decoded, each with a different segmentation of the input.
     // Validate that decoder_.value() matches the expected value.
-    Validator validator =
-        base::Bind(&HpackVarintDecoderTest::ValidatorForDecodeSeveralWays,
-                   base::Unretained(this), expected_value);
+    Validator validator = [expected_value, this](
+        const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+      if (decoder_.value() != expected_value) {
+        return AssertionFailure()
+               << "Value doesn't match expected: " << decoder_.value()
+               << " != " << expected_value;
+      }
+      return AssertionSuccess();
+    };
 
     // First validate that decoding is done and that we've advanced the cursor
     // the expected amount.
@@ -375,9 +358,13 @@
     // DecodeBuffer is decoded, each with a different segmentation of the input.
     // Validate that decoder_.value() matches the expected value.
     bool validated = false;
-    Validator validator =
-        base::Bind(&HpackVarintDecoderTest::ValidatorForValueTooLarge,
-                   base::Unretained(this), &validated, expected_offset);
+    Validator validator = [&validated, expected_offset](
+        const DecodeBuffer& db, DecodeStatus status) -> AssertionResult {
+      validated = true;
+      VERIFY_EQ(DecodeStatus::kDecodeError, status);
+      VERIFY_EQ(expected_offset, db.Offset());
+      return AssertionSuccess();
+    };
 
     // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
     // can call Start with the prefix byte.
diff --git a/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc b/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
index e062046..0b5564f 100644
--- a/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
+++ b/net/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc
@@ -7,6 +7,8 @@
 // Tests of HpackWholeEntryBuffer: does it buffer correctly, and does it
 // detect Huffman decoding errors and oversize string errors?
 
+#include "net/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -15,7 +17,6 @@
 using ::testing::HasSubstr;
 using ::testing::InSequence;
 using ::testing::Property;
-using ::testing::SaveArg;
 using ::testing::StrictMock;
 using ::testing::_;
 
@@ -25,6 +26,15 @@
 
 constexpr size_t kMaxStringSize = 20;
 
+// Define HasSubstr() for base::StringPiece arguments.
+// This shadows ::testing::HasSubstr(), which only works on argument types
+// that can be implicilty converted to a std::string.
+inline ::testing::PolymorphicMatcher<StringPieceHasSubstrMatcher> HasSubstr(
+    const std::string& substring) {
+  return ::testing::MakePolymorphicMatcher(
+      StringPieceHasSubstrMatcher(substring));
+}
+
 class MockHpackWholeEntryListener : public HpackWholeEntryListener {
  public:
   ~MockHpackWholeEntryListener() override {}
@@ -157,21 +167,15 @@
 // Verify that a name longer than the allowed size generates an error.
 TEST_F(HpackWholeEntryBufferTest, NameTooLong) {
   entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0);
-  StringPiece error_message;
-  EXPECT_CALL(listener_, OnHpackDecodeError(_))
-      .WillOnce(SaveArg<0>(&error_message));
+  EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name")));
   entry_buffer_.OnNameStart(false, kMaxStringSize + 1);
-  EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry name"));
 }
 
 // Verify that a name longer than the allowed size generates an error.
 TEST_F(HpackWholeEntryBufferTest, ValueTooLong) {
   entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 1);
-  StringPiece error_message;
-  EXPECT_CALL(listener_, OnHpackDecodeError(_))
-      .WillOnce(SaveArg<0>(&error_message));
+  EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value")));
   entry_buffer_.OnValueStart(false, kMaxStringSize + 1);
-  EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry value"));
 }
 
 // Verify that a Huffman encoded name with an explicit EOS generates an error
@@ -183,12 +187,9 @@
   entry_buffer_.OnNameStart(true, 4);
   entry_buffer_.OnNameData(data, 3);
 
-  StringPiece error_message;
-  EXPECT_CALL(listener_, OnHpackDecodeError(_))
-      .WillOnce(SaveArg<0>(&error_message));
+  EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name")));
 
   entry_buffer_.OnNameData(data, 1);
-  EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry name"));
 
   // After an error is reported, the listener is not called again.
   EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(8096)).Times(0);
@@ -204,12 +205,9 @@
   entry_buffer_.OnValueStart(true, 3);
   entry_buffer_.OnValueData(data, 3);
 
-  StringPiece error_message;
-  EXPECT_CALL(listener_, OnHpackDecodeError(_))
-      .WillOnce(SaveArg<0>(&error_message));
+  EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value")));
 
   entry_buffer_.OnValueEnd();
-  EXPECT_THAT(error_message.as_string(), HasSubstr("HPACK entry value"));
 
   // After an error is reported, the listener is not called again.
   EXPECT_CALL(listener_, OnIndexedHeader(17)).Times(0);
diff --git a/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc b/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
index 3ad47351..3eb52adc 100644
--- a/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
+++ b/net/http2/hpack/huffman/http2_hpack_huffman_decoder_test.cc
@@ -9,8 +9,6 @@
 #include <iostream>
 #include <string>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
 #include "net/http2/decoder/decode_buffer.h"
@@ -202,25 +200,19 @@
     return false;
   }
 
-  AssertionResult ValidatorForHuffmanDecodeAndValidateSeveralWays(
-      StringPiece expected_plain) {
-    VERIFY_EQ(output_buffer_.size(), expected_plain.size());
-    VERIFY_EQ(output_buffer_, expected_plain);
-    return AssertionSuccess();
-  }
-
   AssertionResult HuffmanDecodeAndValidateSeveralWays(
       StringPiece encoded,
       StringPiece expected_plain) {
     input_bytes_expected_ = encoded.size();
+    NoArgValidator validator = [expected_plain, this]() -> AssertionResult {
+      VERIFY_EQ(output_buffer_.size(), expected_plain.size());
+      VERIFY_EQ(output_buffer_, expected_plain);
+      return AssertionSuccess();
+    };
     DecodeBuffer db(encoded);
     bool return_non_zero_on_first = false;
-    return DecodeAndValidateSeveralWays(
-        &db, return_non_zero_on_first,
-        ValidateDoneAndEmpty(
-            base::Bind(&HpackHuffmanDecoderTest::
-                           ValidatorForHuffmanDecodeAndValidateSeveralWays,
-                       base::Unretained(this), expected_plain)));
+    return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first,
+                                        ValidateDoneAndEmpty(validator));
   }
 
   HpackHuffmanDecoder decoder_;
diff --git a/net/http2/tools/random_decoder_test.cc b/net/http2/tools/random_decoder_test.cc
index 9a646e3..224a825 100644
--- a/net/http2/tools/random_decoder_test.cc
+++ b/net/http2/tools/random_decoder_test.cc
@@ -127,8 +127,7 @@
     DecodeBuffer input(original->cursor(), original_remaining);
     VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom";
     VERIFY_SUCCESS(DecodeSegmentsAndValidate(
-        &input, RandomDecoderTest::SelectRandom(return_non_zero_on_first),
-        validator))
+        &input, SelectRandom(return_non_zero_on_first), validator))
         << "\nFailed with SelectRandom; input.Offset=" << input.Offset()
         << "; input.Remaining=" << input.Remaining();
     VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom";
diff --git a/net/http2/tools/random_decoder_test.h b/net/http2/tools/random_decoder_test.h
index 7402173..5cb10f6 100644
--- a/net/http2/tools/random_decoder_test.h
+++ b/net/http2/tools/random_decoder_test.h
@@ -12,12 +12,11 @@
 
 #include <stddef.h>
 
+#include <functional>
 #include <memory>
 #include <string>
 #include <type_traits>
 
-#include "base/bind.h"
-#include "base/callback.h"
 #include "base/logging.h"
 #include "base/strings/string_piece.h"
 #include "base/template_util.h"
@@ -71,10 +70,10 @@
   // Validator returns an AssertionResult so test can do:
   // EXPECT_THAT(DecodeAndValidate(..., validator));
   typedef ::testing::AssertionResult AssertionResult;
-  typedef base::Callback<AssertionResult(const DecodeBuffer& input,
-                                         DecodeStatus status)>
+  typedef std::function<AssertionResult(const DecodeBuffer& input,
+                                        DecodeStatus status)>
       Validator;
-  typedef base::Callback<AssertionResult()> NoArgValidator;
+  typedef std::function<AssertionResult()> NoArgValidator;
 
   RandomDecoderTest();
 
@@ -120,7 +119,7 @@
       const SelectSize& select_size,
       const Validator& validator) {
     DecodeStatus status = DecodeSegments(original, select_size);
-    VERIFY_AND_RETURN_SUCCESS(validator.Run(*original, status));
+    VERIFY_AND_RETURN_SUCCESS(validator(*original, status));
   }
 
   // Returns a SelectSize function for fast decoding, i.e. passing all that
@@ -152,21 +151,26 @@
                                                bool return_non_zero_on_first,
                                                const Validator& validator);
 
-  static AssertionResult SucceedingValidator(const DecodeBuffer& input,
-                                             DecodeStatus status) {
-    return ::testing::AssertionSuccess();
+  static Validator ToValidator(std::nullptr_t) {
+    return [](const DecodeBuffer& input, DecodeStatus status) {
+      return ::testing::AssertionSuccess();
+    };
   }
 
-  static Validator ToValidator(const Validator& validator) { return validator; }
-
-  static AssertionResult RunNoArgValidator(const NoArgValidator& validator,
-                                           const DecodeBuffer& input,
-                                           DecodeStatus status) {
-    return validator.Run();
+  static Validator ToValidator(const Validator& validator) {
+    if (validator == nullptr) {
+      return ToValidator(nullptr);
+    }
+    return validator;
   }
 
   static Validator ToValidator(const NoArgValidator& validator) {
-    return base::Bind(&RunNoArgValidator, validator);
+    if (validator == nullptr) {
+      return ToValidator(nullptr);
+    }
+    return [validator](const DecodeBuffer& input, DecodeStatus status) {
+      return validator();
+    };
   }
 
   // Wraps a validator with another validator
@@ -175,29 +179,31 @@
   // TODO(jamessynge): Replace this overload with the next, as using this method
   // usually means that the wrapped function doesn't need to be passed the
   // DecodeBuffer nor the DecodeStatus.
-  static AssertionResult ValidateDoneAndEmptyImpl(const Validator& wrapped,
-                                                  const DecodeBuffer& input,
-                                                  DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeDone);
-    VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
-    return wrapped.Run(input, status);
-  }
   static Validator ValidateDoneAndEmpty(const Validator& wrapped) {
-    return base::Bind(&ValidateDoneAndEmptyImpl, wrapped);
+    return [wrapped](const DecodeBuffer& input,
+                     DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+      VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
+      if (wrapped) {
+        return wrapped(input, status);
+      }
+      return ::testing::AssertionSuccess();
+    };
   }
-  static AssertionResult ValidateDoneAndEmptyNoArgImpl(
-      const NoArgValidator& wrapped,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeDone);
-    VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
-    return wrapped.Run();
-  }
-  static Validator ValidateDoneAndEmpty(const NoArgValidator& wrapped) {
-    return base::Bind(&ValidateDoneAndEmptyNoArgImpl, wrapped);
+  static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) {
+    return [wrapped](const DecodeBuffer& input,
+                     DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+      VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
+      if (wrapped) {
+        return wrapped();
+      }
+      return ::testing::AssertionSuccess();
+    };
   }
   static Validator ValidateDoneAndEmpty() {
-    return ValidateDoneAndEmpty(base::Bind(&SucceedingValidator));
+    NoArgValidator validator;
+    return ValidateDoneAndEmpty(validator);
   }
 
   // Wraps a validator with another validator
@@ -206,39 +212,32 @@
   // TODO(jamessynge): Replace this overload with the next, as using this method
   // usually means that the wrapped function doesn't need to be passed the
   // DecodeBuffer nor the DecodeStatus.
-  static AssertionResult ValidateDoneAndOffsetImpl(uint32_t offset,
-                                                   const Validator& wrapped,
-                                                   const DecodeBuffer& input,
-                                                   DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeDone);
-    VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
-    return wrapped.Run(input, status);
+  static Validator ValidateDoneAndOffset(uint32_t offset, Validator wrapped) {
+    return [wrapped, offset](const DecodeBuffer& input,
+                             DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+      VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
+      if (wrapped) {
+        return wrapped(input, status);
+      }
+      return ::testing::AssertionSuccess();
+    };
   }
   static Validator ValidateDoneAndOffset(uint32_t offset,
-                                         const Validator& wrapped) {
-    // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
-    // issues if this method is called with a temporary Validator.
-    return base::Bind(&ValidateDoneAndOffsetImpl, offset, wrapped);
-  }
-  static AssertionResult ValidateDoneAndOffsetNoArgImpl(
-      uint32_t offset,
-      const NoArgValidator& wrapped,
-      const DecodeBuffer& input,
-      DecodeStatus status) {
-    VERIFY_EQ(status, DecodeStatus::kDecodeDone);
-    VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
-    return wrapped.Run();
-  }
-  static Validator ValidateDoneAndOffset(uint32_t offset,
-                                         const NoArgValidator& wrapped) {
-    // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
-    // issues if this method is called with a temporary Validator.
-    return base::Bind(&ValidateDoneAndOffsetNoArgImpl, offset, wrapped);
+                                         NoArgValidator wrapped) {
+    return [wrapped, offset](const DecodeBuffer& input,
+                             DecodeStatus status) -> AssertionResult {
+      VERIFY_EQ(status, DecodeStatus::kDecodeDone);
+      VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
+      if (wrapped) {
+        return wrapped();
+      }
+      return ::testing::AssertionSuccess();
+    };
   }
   static Validator ValidateDoneAndOffset(uint32_t offset) {
-    // Make a copy of |wrapped| (by not using base::ConstRef) to avoid lifetime
-    // issues if this method is called with a temporary Validator.
-    return ValidateDoneAndOffset(offset, base::Bind(&SucceedingValidator));
+    NoArgValidator validator;
+    return ValidateDoneAndOffset(offset, validator);
   }
 
   // Expose |random_| as RandomBase so callers do not have to care about which
diff --git a/net/spdy/spdy_flags.cc b/net/spdy/spdy_flags.cc
index c3a7f8e..fa380d4 100644
--- a/net/spdy/spdy_flags.cc
+++ b/net/spdy/spdy_flags.cc
@@ -9,6 +9,9 @@
 // Log compressed size of HTTP/2 requests.
 bool FLAGS_chromium_http2_flag_log_compressed_size = true;
 
+// If true, remove use of SpdyFrameBuilder::OverwriteLength().
+bool FLAGS_chromium_http2_flag_remove_rewritelength = true;
+
 // Use //net/http2/hpack/decoder as HPACK decoder.
 bool FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2 = false;
 
diff --git a/net/spdy/spdy_flags.h b/net/spdy/spdy_flags.h
index 9c90639..d44cb9de 100644
--- a/net/spdy/spdy_flags.h
+++ b/net/spdy/spdy_flags.h
@@ -10,6 +10,7 @@
 namespace net {
 
 NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_log_compressed_size;
+NET_EXPORT_PRIVATE extern bool FLAGS_chromium_http2_flag_remove_rewritelength;
 NET_EXPORT_PRIVATE extern bool
     FLAGS_chromium_http2_flag_spdy_use_hpack_decoder2;
 NET_EXPORT_PRIVATE extern bool
diff --git a/net/spdy/spdy_frame_builder.cc b/net/spdy/spdy_frame_builder.cc
index 5f14f78..39f0c296 100644
--- a/net/spdy/spdy_frame_builder.cc
+++ b/net/spdy/spdy_frame_builder.cc
@@ -65,6 +65,29 @@
   return success;
 }
 
+bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer,
+                                     SpdyFrameType type,
+                                     uint8_t flags,
+                                     SpdyStreamId stream_id,
+                                     size_t length) {
+  DCHECK(IsValidFrameType(SerializeFrameType(type)));
+  DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
+  bool success = true;
+  SPDY_BUG_IF(framer.GetFrameMaximumSize() < length_)
+      << "Frame length  " << length_
+      << " is longer than the maximum allowed length.";
+
+  offset_ += length_;
+  length_ = 0;
+
+  success &= WriteUInt24(length);
+  success &= WriteUInt8(SerializeFrameType(type));
+  success &= WriteUInt8(flags);
+  success &= WriteUInt32(stream_id);
+  DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_);
+  return success;
+}
+
 bool SpdyFrameBuilder::WriteStringPiece16(const base::StringPiece& value) {
   if (value.size() > 0xffff) {
     DCHECK(false) << "Tried to write string with length > 16bit.";
diff --git a/net/spdy/spdy_frame_builder.h b/net/spdy/spdy_frame_builder.h
index 743e0f3..b48ef20 100644
--- a/net/spdy/spdy_frame_builder.h
+++ b/net/spdy/spdy_frame_builder.h
@@ -58,6 +58,14 @@
                      uint8_t flags,
                      SpdyStreamId stream_id);
 
+  // Populates this frame with a HTTP2 frame prefix with length information.
+  // The given type must be a control frame type.
+  bool BeginNewFrame(const SpdyFramer& framer,
+                     SpdyFrameType type,
+                     uint8_t flags,
+                     SpdyStreamId stream_id,
+                     size_t length);
+
   // Takes the buffer from the SpdyFrameBuilder.
   SpdySerializedFrame take() {
     SPDY_BUG_IF(kMaxFrameSizeLimit < length_)
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index b5cd187..38861b3f 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -159,6 +159,7 @@
   if (adapter_factory != nullptr) {
     decoder_adapter_ = adapter_factory(this);
   }
+  skip_rewritelength_ = FLAGS_chromium_http2_flag_remove_rewritelength;
 }
 
 SpdyFramer::SpdyFramer(CompressionOption option)
@@ -1860,12 +1861,21 @@
   }
 
   SpdyFrameBuilder builder(frame_size);
-  builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
-  if (data_ir.padded()) {
-    builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
+  if (!skip_rewritelength_) {
+    builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id());
+    if (data_ir.padded()) {
+      builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
+    }
+    builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
+                                       data_ir.padding_payload_len());
+  } else {
+    builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id(),
+                          num_padding_fields + data_ir.data_len() +
+                              data_ir.padding_payload_len());
+    if (data_ir.padded()) {
+      builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
+    }
   }
-  builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
-                                     data_ir.padding_payload_len());
   DCHECK_EQ(frame_size, builder.length());
   return builder.take();
 }
@@ -1993,7 +2003,29 @@
   }
 
   SpdyFrameBuilder builder(size);
-  builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id());
+
+  if (!skip_rewritelength_) {
+    builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id());
+  } else {
+    // Compute frame length field.
+    size_t length_field = 0;
+    if (headers.padded()) {
+      length_field += 1;  // Padding length field.
+    }
+    if (headers.has_priority()) {
+      length_field += 4;  // Dependency field.
+      length_field += 1;  // Weight field.
+    }
+    length_field += headers.padding_payload_len();
+    length_field += hpack_encoding.size();
+    // If the HEADERS frame with payload would exceed the max frame size, then
+    // WritePayloadWithContinuation() will serialize CONTINUATION frames as
+    // necessary.
+    length_field =
+        std::min(length_field, kMaxControlFrameSize - GetFrameHeaderSize());
+    builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(),
+                          length_field);
+  }
   DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
 
   int padding_payload_len = 0;
@@ -2066,10 +2098,13 @@
   }
 
   SpdyFrameBuilder builder(size);
-  builder.BeginNewFrame(*this,
-                        PUSH_PROMISE,
-                        flags,
-                        push_promise.stream_id());
+  if (!skip_rewritelength_) {
+    builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id());
+  } else {
+    size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize();
+    builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id(),
+                          length);
+  }
   int padding_payload_len = 0;
   if (push_promise.padded()) {
     builder.WriteUInt8(push_promise.padding_payload_len());
@@ -2399,7 +2434,7 @@
     string padding = string(padding_payload_len, 0);
     builder->WriteBytes(padding.data(), padding.length());
   }
-  if (bytes_remaining > 0) {
+  if (bytes_remaining > 0 && !skip_rewritelength_) {
     builder->OverwriteLength(*this,
                              kMaxControlFrameSize - GetFrameHeaderSize());
   }
@@ -2412,7 +2447,12 @@
     if (bytes_remaining == bytes_to_write) {
       flags |= end_flag;
     }
-    builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
+    if (!skip_rewritelength_) {
+      builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
+    } else {
+      builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id,
+                             bytes_to_write);
+    }
     // Write payload fragment.
     builder->WriteBytes(
         &hpack_encoding[hpack_encoding.size() - bytes_remaining],
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index fff856a30..b686746 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -765,6 +765,9 @@
   // If true, then ProcessInput returns after processing a full frame,
   // rather than reading all available input.
   bool process_single_input_frame_ = false;
+
+  // Latched value of FLAGS_chromium_http2_flag_remove_rewritelength.
+  bool skip_rewritelength_ = false;
 };
 
 }  // namespace net
diff --git a/net/spdy/spdy_header_block.cc b/net/spdy/spdy_header_block.cc
index 4e36b89..6cbd6ba6 100644
--- a/net/spdy/spdy_header_block.cc
+++ b/net/spdy/spdy_header_block.cc
@@ -19,6 +19,7 @@
 using base::StringPiece;
 using std::dec;
 using std::hex;
+using std::make_pair;
 using std::max;
 using std::min;
 using std::string;
@@ -30,6 +31,16 @@
 const size_t kDefaultStorageBlockSize = 2048;
 
 const char kCookieKey[] = "cookie";
+const char kNullSeparator = 0;
+
+StringPiece SeparatorForKey(StringPiece key) {
+  if (key == kCookieKey) {
+    static StringPiece cookie_separator = "; ";
+    return cookie_separator;
+  } else {
+    return StringPiece(&kNullSeparator, 1);
+  }
+}
 
 }  // namespace
 
@@ -50,24 +61,6 @@
     return StringPiece(arena_.Memdup(s.data(), s.size()), s.size());
   }
 
-  // Given value, a string already in the arena, perform a realloc and append
-  // separator and more to the end of the value's new location. If value is the
-  // most recently added string (via Write), then UnsafeArena will not copy the
-  // existing value but instead will increase the space reserved for value.
-  StringPiece Realloc(StringPiece value,
-                      StringPiece separator,
-                      StringPiece more) {
-    size_t total_length = value.size() + separator.size() + more.size();
-    char* ptr = const_cast<char*>(value.data());
-    ptr = arena_.Realloc(ptr, value.size(), total_length);
-    StringPiece result(ptr, total_length);
-    ptr += value.size();
-    memcpy(ptr, separator.data(), separator.size());
-    ptr += separator.size();
-    memcpy(ptr, more.data(), more.size());
-    return result;
-  }
-
   // If |s| points to the most recent allocation from arena_, the arena will
   // reclaim the memory. Otherwise, this method is a no-op.
   void Rewind(const StringPiece s) {
@@ -76,10 +69,77 @@
 
   void Clear() { arena_.Reset(); }
 
+  // Given a list of fragments and a separator, writes the fragments joined by
+  // the separator to a contiguous region of memory. Returns a StringPiece
+  // pointing to the region of memory.
+  StringPiece WriteFragments(const std::vector<StringPiece>& fragments,
+                             StringPiece separator) {
+    if (fragments.empty()) {
+      return StringPiece();
+    }
+    size_t total_size = separator.size() * (fragments.size() - 1);
+    for (const auto fragment : fragments) {
+      total_size += fragment.size();
+    }
+    char* dst = arena_.Alloc(total_size);
+    size_t written = Join(dst, fragments, separator);
+    DCHECK_EQ(written, total_size);
+    return StringPiece(dst, total_size);
+  }
+
+  size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
+
  private:
   UnsafeArena arena_;
 };
 
+SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
+                                          StringPiece key,
+                                          StringPiece initial_value)
+    : storage_(storage), fragments_({initial_value}), pair_({key, {}}) {}
+
+SpdyHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other)
+    : storage_(other.storage_),
+      fragments_(std::move(other.fragments_)),
+      pair_(std::move(other.pair_)) {}
+
+SpdyHeaderBlock::HeaderValue& SpdyHeaderBlock::HeaderValue::operator=(
+    HeaderValue&& other) {
+  storage_ = other.storage_;
+  fragments_ = std::move(other.fragments_);
+  pair_ = std::move(other.pair_);
+  return *this;
+}
+
+SpdyHeaderBlock::HeaderValue::~HeaderValue() {}
+
+StringPiece SpdyHeaderBlock::HeaderValue::ConsolidatedValue() const {
+  if (fragments_.empty()) {
+    return StringPiece();
+  }
+  if (fragments_.size() > 1) {
+    fragments_ = {
+        storage_->WriteFragments(fragments_, SeparatorForKey(pair_.first))};
+  }
+  return fragments_[0];
+}
+
+void SpdyHeaderBlock::HeaderValue::Append(StringPiece fragment) {
+  fragments_.push_back(fragment);
+}
+
+const std::pair<StringPiece, StringPiece>&
+SpdyHeaderBlock::HeaderValue::as_pair() const {
+  pair_.second = ConsolidatedValue();
+  return pair_;
+}
+
+SpdyHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {}
+
+SpdyHeaderBlock::iterator::iterator(const iterator& other) : it_(other.it_) {}
+
+SpdyHeaderBlock::iterator::~iterator() {}
+
 SpdyHeaderBlock::ValueProxy::ValueProxy(
     SpdyHeaderBlock::MapType* block,
     SpdyHeaderBlock::Storage* storage,
@@ -89,8 +149,7 @@
       storage_(storage),
       lookup_result_(lookup_result),
       key_(key),
-      valid_(true) {
-}
+      valid_(true) {}
 
 SpdyHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other)
     : block_(other.block_),
@@ -127,10 +186,14 @@
   if (lookup_result_ == block_->end()) {
     DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
     lookup_result_ =
-        block_->insert(std::make_pair(key_, storage_->Write(value))).first;
+        block_
+            ->emplace(make_pair(
+                key_, HeaderValue(storage_, key_, storage_->Write(value))))
+            .first;
   } else {
     DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
-    lookup_result_->second = storage_->Write(value);
+    lookup_result_->second =
+        HeaderValue(storage_, key_, storage_->Write(value));
   }
   return *this;
 }
@@ -139,7 +202,7 @@
   if (lookup_result_ == block_->end()) {
     return "";
   } else {
-    return lookup_result_->second.as_string();
+    return lookup_result_->second.value().as_string();
   }
 }
 
@@ -160,8 +223,8 @@
 
 SpdyHeaderBlock SpdyHeaderBlock::Clone() const {
   SpdyHeaderBlock copy;
-  for (auto iter : *this) {
-    copy.AppendHeader(iter.first, iter.second);
+  for (const auto& p : *this) {
+    copy.AppendHeader(p.first, p.second);
   }
   return copy;
 }
@@ -181,7 +244,7 @@
   string output = "\n{\n";
   for (auto it = begin(); it != end(); ++it) {
     output +=
-        "  " + it->first.as_string() + ":" + it->second.as_string() + "\n";
+        "  " + it->first.as_string() + " " + it->second.as_string() + "\n";
   }
   output.append("}\n");
   return output;
@@ -192,8 +255,7 @@
   storage_.reset();
 }
 
-void SpdyHeaderBlock::insert(
-    const SpdyHeaderBlock::MapType::value_type& value) {
+void SpdyHeaderBlock::insert(const SpdyHeaderBlock::value_type& value) {
   // TODO(birenroy): Write new value in place of old value, if it fits.
   auto iter = block_.find(value.first);
   if (iter == block_.end()) {
@@ -202,7 +264,9 @@
   } else {
     DVLOG(1) << "Updating key: " << iter->first
              << " with value: " << value.second;
-    iter->second = GetStorage()->Write(value.second);
+    auto storage = GetStorage();
+    iter->second =
+        HeaderValue(storage, iter->first, storage->Write(value.second));
   }
 }
 
@@ -232,16 +296,15 @@
     return;
   }
   DVLOG(1) << "Updating key: " << iter->first << "; appending value: " << value;
-  StringPiece separator("", 1);
-  if (key == kCookieKey) {
-    separator = "; ";
-  }
-  iter->second = GetStorage()->Realloc(iter->second, separator, value);
+  iter->second.Append(GetStorage()->Write(value));
 }
 
 void SpdyHeaderBlock::AppendHeader(const StringPiece key,
                                    const StringPiece value) {
-  block_.emplace(GetStorage()->Write(key), GetStorage()->Write(value));
+  auto storage = GetStorage();
+  auto backed_key = storage->Write(key);
+  block_.emplace(make_pair(
+      backed_key, HeaderValue(storage, backed_key, storage->Write(value))));
 }
 
 SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() {
@@ -293,4 +356,31 @@
   return true;
 }
 
+size_t SpdyHeaderBlock::bytes_allocated() const {
+  if (storage_ == nullptr) {
+    return 0;
+  } else {
+    return storage_->bytes_allocated();
+  }
+}
+
+size_t Join(char* dst,
+            const std::vector<StringPiece>& fragments,
+            StringPiece separator) {
+  if (fragments.empty()) {
+    return 0;
+  }
+  auto original_dst = dst;
+  auto it = fragments.begin();
+  memcpy(dst, it->data(), it->size());
+  dst += it->size();
+  for (++it; it != fragments.end(); ++it) {
+    memcpy(dst, separator.data(), separator.size());
+    dst += separator.size();
+    memcpy(dst, it->data(), it->size());
+    dst += it->size();
+  }
+  return dst - original_dst;
+}
+
 }  // namespace net
diff --git a/net/spdy/spdy_header_block.h b/net/spdy/spdy_header_block.h
index fef27e8f..fe8827f5 100644
--- a/net/spdy/spdy_header_block.h
+++ b/net/spdy/spdy_header_block.h
@@ -11,6 +11,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
@@ -27,6 +28,7 @@
 class NetLogCaptureMode;
 
 namespace test {
+class SpdyHeaderBlockPeer;
 class ValueProxyPeer;
 }
 
@@ -43,16 +45,93 @@
 // It's expected that keys are rarely deleted from a SpdyHeaderBlock.
 class NET_EXPORT SpdyHeaderBlock {
  private:
-  using MapType = linked_hash_map<base::StringPiece,
-                                  base::StringPiece,
-                                  base::StringPieceHash>;
   class Storage;
 
+  // Stores a list of value fragments that can be joined later with a
+  // key-dependent separator.
+  class NET_EXPORT HeaderValue {
+   public:
+    HeaderValue(Storage* storage,
+                base::StringPiece key,
+                base::StringPiece initial_value);
+
+    // Moves are allowed.
+    HeaderValue(HeaderValue&& other);
+    HeaderValue& operator=(HeaderValue&& other);
+
+    // Copies are not.
+    HeaderValue(const HeaderValue& other) = delete;
+    HeaderValue& operator=(const HeaderValue& other) = delete;
+
+    ~HeaderValue();
+
+    // Consumes at most |fragment.size()| bytes of memory.
+    void Append(base::StringPiece fragment);
+
+    base::StringPiece value() const { return as_pair().second; }
+    const std::pair<base::StringPiece, base::StringPiece>& as_pair() const;
+
+   private:
+    // May allocate a large contiguous region of memory to hold the concatenated
+    // fragments and separators.
+    base::StringPiece ConsolidatedValue() const;
+
+    mutable Storage* storage_;
+    mutable std::vector<base::StringPiece> fragments_;
+    // The first element is the key; the second is the consolidated value.
+    mutable std::pair<base::StringPiece, base::StringPiece> pair_;
+  };
+
+  typedef linked_hash_map<base::StringPiece, HeaderValue, base::StringPieceHash>
+      MapType;
+
  public:
-  using iterator = MapType::iterator;
-  using const_iterator = MapType::const_iterator;
-  using value_type = MapType::value_type;
-  using reverse_iterator = MapType::reverse_iterator;
+  typedef std::pair<base::StringPiece, base::StringPiece> value_type;
+
+  // Provides iteration over a sequence of std::pair<StringPiece, StringPiece>,
+  // even though the underlying MapType::value_type is different. Dereferencing
+  // the iterator will result in memory allocation for multi-value headers.
+  class NET_EXPORT iterator {
+   public:
+    // The following type definitions fulfill the requirements for iterator
+    // implementations.
+    typedef std::pair<base::StringPiece, base::StringPiece> value_type;
+    typedef value_type& reference;
+    typedef value_type* pointer;
+    typedef std::forward_iterator_tag iterator_category;
+    typedef MapType::iterator::difference_type difference_type;
+
+    // In practice, this iterator only offers access to const value_type.
+    typedef const value_type& const_reference;
+    typedef const value_type* const_pointer;
+
+    explicit iterator(MapType::const_iterator it);
+    iterator(const iterator& other);
+    ~iterator();
+
+    // This will result in memory allocation if the value consists of multiple
+    // fragments.
+    const_reference operator*() const { return it_->second.as_pair(); }
+
+    const_pointer operator->() const { return &(this->operator*()); }
+    bool operator==(const iterator& it) const { return it_ == it.it_; }
+    bool operator!=(const iterator& it) const { return !(*this == it); }
+
+    iterator& operator++() {
+      it_++;
+      return *this;
+    }
+
+    iterator operator++(int) {
+      auto ret = *this;
+      this->operator++();
+      return ret;
+    }
+
+   private:
+    MapType::const_iterator it_;
+  };
+  typedef iterator const_iterator;
 
   class ValueProxy;
 
@@ -72,16 +151,16 @@
   // keys and values.
   std::string DebugString() const;
 
-  // These methods delegate to our MapType member.
-  iterator begin() { return block_.begin(); }
-  iterator end() { return block_.end(); }
-  const_iterator begin() const { return block_.begin(); }
-  const_iterator end() const { return block_.end(); }
+  iterator begin() { return iterator(block_.begin()); }
+  iterator end() { return iterator(block_.end()); }
+  const_iterator begin() const { return const_iterator(block_.begin()); }
+  const_iterator end() const { return const_iterator(block_.end()); }
   bool empty() const { return block_.empty(); }
   size_t size() const { return block_.size(); }
-  iterator find(base::StringPiece key) { return block_.find(key); }
-  const_iterator find(base::StringPiece key) const { return block_.find(key); }
-  reverse_iterator rbegin() { return block_.rbegin(); }
+  iterator find(base::StringPiece key) { return iterator(block_.find(key)); }
+  const_iterator find(base::StringPiece key) const {
+    return const_iterator(block_.find(key));
+  }
   void erase(base::StringPiece key) { block_.erase(key); }
 
   // Clears both our MapType member and the memory used to hold headers.
@@ -91,7 +170,7 @@
 
   // If key already exists in the block, replaces the value of that key. Else
   // adds a new header to the end of the block.
-  void insert(const MapType::value_type& value);
+  void insert(const value_type& value);
 
   // If a header with the key is already present, then append the value to the
   // existing header value, NUL ("\0") separated unless the key is cookie, in
@@ -140,8 +219,11 @@
   };
 
  private:
+  friend class test::SpdyHeaderBlockPeer;
+
   void AppendHeader(const base::StringPiece key, const base::StringPiece value);
   Storage* GetStorage();
+  size_t bytes_allocated() const;
 
   // StringPieces held by |block_| point to memory owned by |*storage_|.
   // |storage_| might be nullptr as long as |block_| is empty.
@@ -149,6 +231,12 @@
   std::unique_ptr<Storage> storage_;
 };
 
+// Writes |fragments| to |dst|, joined by |separator|. |dst| must be large
+// enough to hold the result. Returns the number of bytes written.
+NET_EXPORT size_t Join(char* dst,
+                       const std::vector<base::StringPiece>& fragments,
+                       base::StringPiece separator);
+
 // Converts a SpdyHeaderBlock into NetLog event parameters.
 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
     const SpdyHeaderBlock* headers,
diff --git a/net/spdy/spdy_header_block_test.cc b/net/spdy/spdy_header_block_test.cc
index 5f4429d..c2c4a8f 100644
--- a/net/spdy/spdy_header_block_test.cc
+++ b/net/spdy/spdy_header_block_test.cc
@@ -13,8 +13,10 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using base::StringPiece;
 using std::make_pair;
 using std::string;
+using std::vector;
 using ::testing::ElementsAre;
 
 namespace net {
@@ -22,13 +24,10 @@
 
 class ValueProxyPeer {
  public:
-  static base::StringPiece key(SpdyHeaderBlock::ValueProxy* p) {
-    return p->key_;
-  }
+  static StringPiece key(SpdyHeaderBlock::ValueProxy* p) { return p->key_; }
 };
 
-std::pair<base::StringPiece, base::StringPiece> Pair(base::StringPiece k,
-                                                     base::StringPiece v) {
+std::pair<StringPiece, StringPiece> Pair(StringPiece k, StringPiece v) {
   return make_pair(k, v);
 }
 
@@ -46,12 +45,12 @@
 
 TEST(SpdyHeaderBlockTest, KeyMemoryReclaimedOnLookup) {
   SpdyHeaderBlock block;
-  base::StringPiece copied_key1;
+  StringPiece copied_key1;
   {
     auto proxy1 = block["some key name"];
     copied_key1 = ValueProxyPeer::key(&proxy1);
   }
-  base::StringPiece copied_key2;
+  StringPiece copied_key2;
   {
     auto proxy2 = block["some other key name"];
     copied_key2 = ValueProxyPeer::key(&proxy2);
@@ -187,12 +186,40 @@
   block.AppendValueOrAddHeader("h1", "h1v3");
   block.AppendValueOrAddHeader("h2", "h2v3");
   block.AppendValueOrAddHeader("h3", "h3v3");
+  block.AppendValueOrAddHeader("h4", "singleton");
 
   EXPECT_EQ("key1=value1; key2=value2; key3=value3", block["cookie"]);
   EXPECT_EQ("baz", block["foo"]);
   EXPECT_EQ(string("h1v1\0h1v2\0h1v3", 14), block["h1"]);
   EXPECT_EQ(string("h2v1\0h2v2\0h2v3", 14), block["h2"]);
   EXPECT_EQ(string("h3v2\0h3v3", 9), block["h3"]);
+  EXPECT_EQ("singleton", block["h4"]);
+}
+
+TEST(JoinTest, JoinEmpty) {
+  vector<StringPiece> empty;
+  StringPiece separator = ", ";
+  char buf[10] = "";
+  size_t written = Join(buf, empty, separator);
+  EXPECT_EQ(0u, written);
+}
+
+TEST(JoinTest, JoinOne) {
+  vector<StringPiece> v = {"one"};
+  StringPiece separator = ", ";
+  char buf[15];
+  size_t written = Join(buf, v, separator);
+  EXPECT_EQ(3u, written);
+  EXPECT_EQ("one", StringPiece(buf, written));
+}
+
+TEST(JoinTest, JoinMultiple) {
+  vector<StringPiece> v = {"one", "two", "three"};
+  StringPiece separator = ", ";
+  char buf[15];
+  size_t written = Join(buf, v, separator);
+  EXPECT_EQ(15u, written);
+  EXPECT_EQ("one, two, three", StringPiece(buf, written));
 }
 
 }  // namespace test
diff --git a/net/spdy/spdy_protocol.cc b/net/spdy/spdy_protocol.cc
index adf76ef..1c9254e30 100644
--- a/net/spdy/spdy_protocol.cc
+++ b/net/spdy/spdy_protocol.cc
@@ -46,54 +46,13 @@
 }
 
 bool IsValidFrameType(int frame_type_field) {
-  // Check for recognized extensions.
-  if (frame_type_field == SerializeFrameType(ALTSVC) ||
-      frame_type_field == SerializeFrameType(BLOCKED)) {
-    return true;
-  }
-
-  // DATA is the first valid frame.
-  if (frame_type_field < SerializeFrameType(DATA)) {
-    return false;
-  }
-
-  // CONTINUATION is the last valid frame.
-  if (frame_type_field > SerializeFrameType(CONTINUATION)) {
-    return false;
-  }
-
-  return true;
+  return frame_type_field >= MIN_FRAME_TYPE &&
+         frame_type_field <= MAX_FRAME_TYPE;
 }
 
 SpdyFrameType ParseFrameType(int frame_type_field) {
-  switch (frame_type_field) {
-    case 0:
-      return DATA;
-    case 1:
-      return HEADERS;
-    case 2:
-      return PRIORITY;
-    case 3:
-      return RST_STREAM;
-    case 4:
-      return SETTINGS;
-    case 5:
-      return PUSH_PROMISE;
-    case 6:
-      return PING;
-    case 7:
-      return GOAWAY;
-    case 8:
-      return WINDOW_UPDATE;
-    case 9:
-      return CONTINUATION;
-    case 10:
-      return ALTSVC;
-    case 11:
-      return BLOCKED;
-  }
-  SPDY_BUG << "Unhandled frame type " << frame_type_field;
-  return DATA;
+  SPDY_BUG_IF(!IsValidFrameType(frame_type_field)) << "Invalid frame type.";
+  return static_cast<SpdyFrameType>(frame_type_field);
 }
 
 int SerializeFrameType(SpdyFrameType frame_type) {
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
index 62b08b80..c5ab564 100644
--- a/net/spdy/spdy_protocol.h
+++ b/net/spdy/spdy_protocol.h
@@ -74,19 +74,21 @@
 
 // Types of HTTP2 frames.
 enum SpdyFrameType {
-  DATA,
-  RST_STREAM,
-  SETTINGS,
-  PING,
-  GOAWAY,
-  HEADERS,
-  WINDOW_UPDATE,
-  PUSH_PROMISE,
-  CONTINUATION,
-  PRIORITY,
-  // BLOCKED and ALTSVC are recognized extensions.
-  BLOCKED,
-  ALTSVC,
+  DATA = 0x00,
+  MIN_FRAME_TYPE = DATA,
+  HEADERS = 0x01,
+  PRIORITY = 0x02,
+  RST_STREAM = 0x03,
+  SETTINGS = 0x04,
+  PUSH_PROMISE = 0x05,
+  PING = 0x06,
+  GOAWAY = 0x07,
+  WINDOW_UPDATE = 0x08,
+  CONTINUATION = 0x09,
+  // ALTSVC and BLOCKED are recognized extensions.
+  ALTSVC = 0x0a,
+  BLOCKED = 0x0b,
+  MAX_FRAME_TYPE = BLOCKED
 };
 
 // Flags on data packets.
diff --git a/net/test/gtest_util.h b/net/test/gtest_util.h
index 22d82b0..dec0bb9 100644
--- a/net/test/gtest_util.h
+++ b/net/test/gtest_util.h
@@ -7,9 +7,14 @@
 #ifndef NET_TEST_GTEST_UTIL_H_
 #define NET_TEST_GTEST_UTIL_H_
 
+#include <string>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
 #include "base/test/mock_log.h"
 #include "net/base/net_errors.h"
 #include "net/test/scoped_disable_exit_on_dfatal.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -36,6 +41,34 @@
   return arg == net::OK;
 }
 
+// A gMock matcher for base::StringPiece arguments.
+// gMock's built-in HasSubstrMatcher does not work,
+// because base::StringPiece cannot be implicitly converted to std::string.
+class StringPieceHasSubstrMatcher {
+ public:
+  explicit StringPieceHasSubstrMatcher(const std::string& substring)
+      : substring_(substring) {}
+
+  bool MatchAndExplain(base::StringPiece s,
+                       ::testing::MatchResultListener* listener) const {
+    return s.as_string().find(substring_) != std::string::npos;
+  }
+
+  // Describe what this matcher matches.
+  void DescribeTo(std::ostream* os) const {
+    *os << "has substring " << substring_;
+  }
+
+  void DescribeNegationTo(std::ostream* os) const {
+    *os << "has no substring " << substring_;
+  }
+
+ private:
+  const std::string substring_;
+
+  DISALLOW_ASSIGN(StringPieceHasSubstrMatcher);
+};
+
 // Internal implementation for the EXPECT_DFATAL and ASSERT_DFATAL
 // macros.  Do not use this directly.
 #define GTEST_DFATAL_(statement, severity, matcher, fail)                    \
diff --git a/net/tools/testserver/testserver.pydeps b/net/tools/testserver/testserver.pydeps
index 8deef4a..b3b97fa0 100644
--- a/net/tools/testserver/testserver.pydeps
+++ b/net/tools/testserver/testserver.pydeps
@@ -1,5 +1,5 @@
 # Generated by running:
-#   build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps net/tools/testserver/testserver.py
+#   build/print_python_deps.py --root net/tools/testserver --output net/tools/testserver/testserver.pydeps --whitelist third_party/tlslite/tlslite/utils net/tools/testserver/testserver.py
 ../../../third_party/pyftpdlib/src/pyftpdlib/__init__.py
 ../../../third_party/pyftpdlib/src/pyftpdlib/ftpserver.py
 ../../../third_party/pywebsocket/src/mod_pywebsocket/__init__.py
@@ -53,7 +53,12 @@
 ../../../third_party/tlslite/tlslite/utils/codec.py
 ../../../third_party/tlslite/tlslite/utils/compat.py
 ../../../third_party/tlslite/tlslite/utils/cryptomath.py
+../../../third_party/tlslite/tlslite/utils/datefuncs.py
 ../../../third_party/tlslite/tlslite/utils/keyfactory.py
+../../../third_party/tlslite/tlslite/utils/openssl_aes.py
+../../../third_party/tlslite/tlslite/utils/openssl_rc4.py
+../../../third_party/tlslite/tlslite/utils/openssl_rsakey.py
+../../../third_party/tlslite/tlslite/utils/openssl_tripledes.py
 ../../../third_party/tlslite/tlslite/utils/p256.py
 ../../../third_party/tlslite/tlslite/utils/pem.py
 ../../../third_party/tlslite/tlslite/utils/pycrypto_aes.py
diff --git a/remoting/client/plugin/pepper_video_renderer_2d.cc b/remoting/client/plugin/pepper_video_renderer_2d.cc
index 96fc9cf..4a605cb 100644
--- a/remoting/client/plugin/pepper_video_renderer_2d.cc
+++ b/remoting/client/plugin/pepper_video_renderer_2d.cc
@@ -176,7 +176,7 @@
 
   if (!done.is_null()) {
     pending_frames_done_callbacks_.push_back(
-        new base::ScopedClosureRunner(done));
+        base::MakeUnique<base::ScopedClosureRunner>(done));
   }
 
   need_flush_ = true;
diff --git a/remoting/client/plugin/pepper_video_renderer_2d.h b/remoting/client/plugin/pepper_video_renderer_2d.h
index 74fa15f..4663cdd6 100644
--- a/remoting/client/plugin/pepper_video_renderer_2d.h
+++ b/remoting/client/plugin/pepper_video_renderer_2d.h
@@ -6,11 +6,12 @@
 #define REMOTING_CLIENT_PLUGIN_PEPPER_VIDEO_RENDERER_2D_H_
 
 #include <list>
+#include <memory>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "ppapi/cpp/graphics_2d.h"
@@ -84,10 +85,12 @@
   webrtc::DesktopSize source_size_;
 
   // Done callbacks for the frames that have been painted but not flushed.
-  ScopedVector<base::ScopedClosureRunner> pending_frames_done_callbacks_;
+  std::vector<std::unique_ptr<base::ScopedClosureRunner>>
+      pending_frames_done_callbacks_;
 
   // Done callbacks for the frames that are currently being flushed.
-  ScopedVector<base::ScopedClosureRunner> flushing_frames_done_callbacks_;
+  std::vector<std::unique_ptr<base::ScopedClosureRunner>>
+      flushing_frames_done_callbacks_;
 
   // True if there paint operations that need to be flushed.
   bool need_flush_ = false;
diff --git a/remoting/client/software_video_renderer_unittest.cc b/remoting/client/software_video_renderer_unittest.cc
index 7aa113c..b9541a97 100644
--- a/remoting/client/software_video_renderer_unittest.cc
+++ b/remoting/client/software_video_renderer_unittest.cc
@@ -6,12 +6,12 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <utility>
 #include <vector>
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
@@ -156,7 +156,7 @@
 TEST_F(SoftwareVideoRendererTest, DecodeFrame) {
   const int kFrameCount = 5;
 
-  ScopedVector<DesktopFrame> test_frames;
+  std::vector<std::unique_ptr<DesktopFrame>> test_frames;
 
   // std::vector<bool> doesn't allow to get pointer to individual values, so
   // int needs to be used instead.
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc
index 6572713..238b618c 100644
--- a/remoting/host/chromoting_host.cc
+++ b/remoting/host/chromoting_host.cc
@@ -125,7 +125,7 @@
 }
 
 void ChromotingHost::AddExtension(std::unique_ptr<HostExtension> extension) {
-  extensions_.push_back(extension.release());
+  extensions_.push_back(std::move(extension));
 }
 
 void ChromotingHost::SetAuthenticatorFactory(
@@ -259,9 +259,12 @@
   DesktopEnvironmentOptions options = desktop_environment_options_;
   // TODO(zijiehe): Apply HostSessionOptions to options.
   // Create a ClientSession object.
+  std::vector<HostExtension*> extension_ptrs;
+  for (const auto& extension : extensions_)
+    extension_ptrs.push_back(extension.get());
   clients_.push_back(base::MakeUnique<ClientSession>(
       this, std::move(connection), desktop_environment_factory_, options,
-      max_session_duration_, pairing_registry_, extensions_.get()));
+      max_session_duration_, pairing_registry_, extension_ptrs));
 }
 
 }  // namespace remoting
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h
index 7009f6e..d9d34ea 100644
--- a/remoting/host/chromoting_host.h
+++ b/remoting/host/chromoting_host.h
@@ -11,7 +11,6 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/threading/non_thread_safe.h"
@@ -142,8 +141,6 @@
  private:
   friend class ChromotingHostTest;
 
-  typedef ScopedVector<HostExtension> HostExtensionList;
-
   // Unless specified otherwise all members of this class must be
   // used on the network thread only.
 
@@ -176,7 +173,7 @@
   scoped_refptr<protocol::PairingRegistry> pairing_registry_;
 
   // List of host extensions.
-  HostExtensionList extensions_;
+  std::vector<std::unique_ptr<HostExtension>> extensions_;
 
   base::WeakPtrFactory<ChromotingHost> weak_factory_;
 
diff --git a/remoting/host/host_extension_session_manager.cc b/remoting/host/host_extension_session_manager.cc
index 8940cb66b..ac06b4f 100644
--- a/remoting/host/host_extension_session_manager.cc
+++ b/remoting/host/host_extension_session_manager.cc
@@ -4,6 +4,7 @@
 
 #include "remoting/host/host_extension_session_manager.h"
 
+#include "base/logging.h"
 #include "remoting/base/capabilities.h"
 #include "remoting/host/client_session_details.h"
 #include "remoting/host/host_extension.h"
@@ -12,7 +13,7 @@
 namespace remoting {
 
 HostExtensionSessionManager::HostExtensionSessionManager(
-    const std::vector<HostExtension*>& extensions,
+    const HostExtensions& extensions,
     ClientSessionDetails* client_session_details)
     : client_session_details_(client_session_details),
       client_stub_(nullptr),
@@ -22,9 +23,8 @@
 
 std::string HostExtensionSessionManager::GetCapabilities() const {
   std::string capabilities;
-  for (HostExtensions::const_iterator extension = extensions_.begin();
-       extension != extensions_.end(); ++extension) {
-    const std::string& capability = (*extension)->capability();
+  for (const auto& extension : extensions_) {
+    const std::string& capability = extension->capability();
     if (capability.empty()) {
       continue;
     }
@@ -44,30 +44,28 @@
 
   client_stub_ = client_stub;
 
-  for (HostExtensions::const_iterator extension = extensions_.begin();
-       extension != extensions_.end(); ++extension) {
+  for (const auto& extension : extensions_) {
     // If the extension requires a capability that was not negotiated then do
     // not instantiate it.
-    if (!(*extension)->capability().empty() &&
-        !HasCapability(capabilities, (*extension)->capability())) {
+    if (!extension->capability().empty() &&
+        !HasCapability(capabilities, extension->capability())) {
       continue;
     }
 
     std::unique_ptr<HostExtensionSession> extension_session =
-        (*extension)
-            ->CreateExtensionSession(client_session_details_, client_stub_);
+        extension->CreateExtensionSession(client_session_details_,
+                                          client_stub_);
     DCHECK(extension_session);
 
-    extension_sessions_.push_back(extension_session.release());
+    extension_sessions_.push_back(std::move(extension_session));
   }
 }
 
 bool HostExtensionSessionManager::OnExtensionMessage(
     const protocol::ExtensionMessage& message) {
-  for(HostExtensionSessions::const_iterator it = extension_sessions_.begin();
-      it != extension_sessions_.end(); ++it) {
-    if ((*it)->OnExtensionMessage(client_session_details_, client_stub_,
-                                  message)) {
+  for (const auto& session : extension_sessions_) {
+    if (session->OnExtensionMessage(client_session_details_, client_stub_,
+                                    message)) {
       return true;
     }
   }
diff --git a/remoting/host/host_extension_session_manager.h b/remoting/host/host_extension_session_manager.h
index 6925b8df..e26ec08f 100644
--- a/remoting/host/host_extension_session_manager.h
+++ b/remoting/host/host_extension_session_manager.h
@@ -5,11 +5,11 @@
 #ifndef REMOTING_HOST_HOST_EXTENSION_SESSION_MANAGER_H_
 #define REMOTING_HOST_HOST_EXTENSION_SESSION_MANAGER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 
 namespace remoting {
 
@@ -27,7 +27,7 @@
 // set of capabilities negotiated between client and host.
 class HostExtensionSessionManager {
  public:
-  typedef std::vector<HostExtension*> HostExtensions;
+  using HostExtensions = std::vector<HostExtension*>;
 
   // Creates an extension manager for the specified |extensions|.
   HostExtensionSessionManager(const HostExtensions& extensions,
@@ -48,7 +48,8 @@
   bool OnExtensionMessage(const protocol::ExtensionMessage& message);
 
  private:
-  typedef ScopedVector<HostExtensionSession> HostExtensionSessions;
+  using HostExtensionSessions =
+      std::vector<std::unique_ptr<HostExtensionSession>>;
 
   // Passed to HostExtensionSessions to allow them to send messages,
   // disconnect the session, etc.
diff --git a/remoting/protocol/audio_pump_unittest.cc b/remoting/protocol/audio_pump_unittest.cc
index 67ce2ac..806cd0a 100644
--- a/remoting/protocol/audio_pump_unittest.cc
+++ b/remoting/protocol/audio_pump_unittest.cc
@@ -6,11 +6,12 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <utility>
+#include <vector>
 
 #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/run_loop.h"
 #include "remoting/codec/audio_encoder.h"
@@ -69,7 +70,7 @@
 
   std::unique_ptr<AudioPump> pump_;
 
-  ScopedVector<AudioPacket> sent_packets_;
+  std::vector<std::unique_ptr<AudioPacket>> sent_packets_;
   std::vector<base::Closure> done_closures_;
 
  private:
diff --git a/remoting/protocol/client_video_dispatcher_unittest.cc b/remoting/protocol/client_video_dispatcher_unittest.cc
index e26ca45..d4722f4 100644
--- a/remoting/protocol/client_video_dispatcher_unittest.cc
+++ b/remoting/protocol/client_video_dispatcher_unittest.cc
@@ -4,8 +4,10 @@
 
 #include "remoting/protocol/client_video_dispatcher.h"
 
+#include <memory>
+#include <vector>
+
 #include "base/bind.h"
-#include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "remoting/base/buffered_socket_writer.h"
@@ -58,10 +60,10 @@
   MessageReader reader_;
   BufferedSocketWriter writer_;
 
-  ScopedVector<VideoPacket> video_packets_;
+  std::vector<std::unique_ptr<VideoPacket>> video_packets_;
   std::vector<base::Closure> packet_done_callbacks_;
 
-  ScopedVector<VideoAck> ack_messages_;
+  std::vector<std::unique_ptr<VideoAck>> ack_messages_;
 };
 
 ClientVideoDispatcherTest::ClientVideoDispatcherTest()
@@ -88,7 +90,7 @@
 void ClientVideoDispatcherTest::ProcessVideoPacket(
     std::unique_ptr<VideoPacket> video_packet,
     const base::Closure& done) {
-  video_packets_.push_back(video_packet.release());
+  video_packets_.push_back(std::move(video_packet));
   packet_done_callbacks_.push_back(done);
 }
 
@@ -112,7 +114,7 @@
     std::unique_ptr<CompoundBuffer> buffer) {
   std::unique_ptr<VideoAck> ack = ParseMessage<VideoAck>(buffer.get());
   EXPECT_TRUE(ack);
-  ack_messages_.push_back(ack.release());
+  ack_messages_.push_back(std::move(ack));
 }
 
 void ClientVideoDispatcherTest::OnReadError(int error) {
diff --git a/remoting/protocol/video_frame_pump.cc b/remoting/protocol/video_frame_pump.cc
index 8cb30e4..68324ec 100644
--- a/remoting/protocol/video_frame_pump.cc
+++ b/remoting/protocol/video_frame_pump.cc
@@ -238,8 +238,9 @@
 
   // Send next packet if any.
   if (!pending_packets_.empty()) {
-    std::unique_ptr<PacketWithTimestamps> next(pending_packets_.front());
-    pending_packets_.weak_erase(pending_packets_.begin());
+    std::unique_ptr<PacketWithTimestamps> next =
+        std::move(pending_packets_.front());
+    pending_packets_.erase(pending_packets_.begin());
     SendPacket(std::move(next));
   }
 }
diff --git a/remoting/protocol/video_frame_pump.h b/remoting/protocol/video_frame_pump.h
index 6fe57e8..925b9bc5 100644
--- a/remoting/protocol/video_frame_pump.h
+++ b/remoting/protocol/video_frame_pump.h
@@ -9,9 +9,9 @@
 #include <stdint.h>
 
 #include <memory>
+#include <vector>
 
 #include "base/macros.h"
-#include "base/memory/scoped_vector.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -179,7 +179,7 @@
 
   bool send_pending_ = false;
 
-  ScopedVector<PacketWithTimestamps> pending_packets_;
+  std::vector<std::unique_ptr<PacketWithTimestamps>> pending_packets_;
 
   base::ThreadChecker thread_checker_;
 
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc
index e4ce98ae..c9c88c4e 100644
--- a/remoting/protocol/webrtc_transport.cc
+++ b/remoting/protocol/webrtc_transport.cc
@@ -680,8 +680,8 @@
 
   if (peer_connection()->signaling_state() ==
       webrtc::PeerConnectionInterface::kStable) {
-    for (auto* candidate : pending_incoming_candidates_) {
-      if (!peer_connection()->AddIceCandidate(candidate)) {
+    for (const auto& candidate : pending_incoming_candidates_) {
+      if (!peer_connection()->AddIceCandidate(candidate.get())) {
         LOG(ERROR) << "Failed to add incoming candidate";
         Close(INCOMPATIBLE_PROTOCOL);
         return;
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h
index 8e5fb1b..faf72be 100644
--- a/remoting/protocol/webrtc_transport.h
+++ b/remoting/protocol/webrtc_transport.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
@@ -141,7 +141,8 @@
   std::unique_ptr<buzz::XmlElement> pending_transport_info_message_;
   base::OneShotTimer transport_info_timer_;
 
-  ScopedVector<webrtc::IceCandidateInterface> pending_incoming_candidates_;
+  std::vector<std::unique_ptr<webrtc::IceCandidateInterface>>
+      pending_incoming_candidates_;
 
   base::WeakPtrFactory<WebrtcTransport> weak_factory_;
 
diff --git a/remoting/signaling/xmpp_signal_strategy_unittest.cc b/remoting/signaling/xmpp_signal_strategy_unittest.cc
index 53147bc..99d8f84d5 100644
--- a/remoting/signaling/xmpp_signal_strategy_unittest.cc
+++ b/remoting/signaling/xmpp_signal_strategy_unittest.cc
@@ -4,7 +4,9 @@
 
 #include "remoting/signaling/xmpp_signal_strategy.h"
 
+#include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/base64.h"
 #include "base/memory/ptr_util.h"
@@ -160,7 +162,7 @@
   std::unique_ptr<XmppSignalStrategy> signal_strategy_;
 
   std::vector<SignalStrategy::State> state_history_;
-  ScopedVector<buzz::XmlElement> received_messages_;
+  std::vector<std::unique_ptr<buzz::XmlElement>> received_messages_;
 };
 
 void XmppSignalStrategyTest::Connect(bool success) {
diff --git a/remoting/signaling/xmpp_stream_parser_unittest.cc b/remoting/signaling/xmpp_stream_parser_unittest.cc
index 299d9f7..22e341f9 100644
--- a/remoting/signaling/xmpp_stream_parser_unittest.cc
+++ b/remoting/signaling/xmpp_stream_parser_unittest.cc
@@ -4,10 +4,11 @@
 
 #include "remoting/signaling/xmpp_stream_parser.h"
 
+#include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
-#include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -43,7 +44,7 @@
   base::MessageLoop message_loop_;
 
   std::unique_ptr<XmppStreamParser> parser_;
-  ScopedVector<buzz::XmlElement> received_stanzas_;
+  std::vector<std::unique_ptr<buzz::XmlElement>> received_stanzas_;
   bool error_;
 };
 
diff --git a/remoting/test/test_video_renderer_unittest.cc b/remoting/test/test_video_renderer_unittest.cc
index 30ab30c..0d6f53e 100644
--- a/remoting/test/test_video_renderer_unittest.cc
+++ b/remoting/test/test_video_renderer_unittest.cc
@@ -7,11 +7,12 @@
 #include <stdint.h>
 
 #include <cmath>
+#include <memory>
 #include <utility>
+#include <vector>
 
 #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/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -399,7 +400,7 @@
   // more than one task on the video decode thread, while not too large to wait
   // for too long for the unit test to complete.
   const int task_num = 20;
-  ScopedVector<VideoPacket> video_packets;
+  std::vector<std::unique_ptr<VideoPacket>> video_packets;
   for (int i = 0; i < task_num; ++i) {
     std::unique_ptr<webrtc::DesktopFrame> original_frame =
         CreateDesktopFrameWithGradient(kDefaultScreenWidthPx,
@@ -407,11 +408,8 @@
     video_packets.push_back(encoder_->Encode(*original_frame.get()));
   }
 
-  for (int i = 0; i < task_num; ++i) {
-    // Transfer ownership of video packet.
-    VideoPacket* packet = video_packets[i];
-    video_packets[i] = nullptr;
-    test_video_renderer_->ProcessVideoPacket(base::WrapUnique(packet),
+  for (auto& packet : video_packets) {
+    test_video_renderer_->ProcessVideoPacket(std::move(packet),
                                              base::Bind(&base::DoNothing));
   }
 }
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc
index 660c471..a87c7cbe 100644
--- a/services/ui/gpu/gpu_main.cc
+++ b/services/ui/gpu/gpu_main.cc
@@ -14,6 +14,10 @@
 #include "services/ui/common/server_gpu_memory_buffer_manager.h"
 #include "services/ui/gpu/gpu_service.h"
 
+#if defined(OS_MACOSX)
+#include "base/message_loop/message_pump_mac.h"
+#endif
+
 namespace {
 
 #if defined(USE_X11)
@@ -104,14 +108,15 @@
 }
 
 void GpuMain::CreateGpuService(mojom::GpuServiceRequest request,
-                               mojom::GpuHostPtr gpu_host) {
+                               mojom::GpuHostPtr gpu_host,
+                               const gpu::GpuPreferences& preferences) {
   // |this| will outlive the gpu thread and so it's safe to use
   // base::Unretained here.
   gpu_thread_.task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&GpuMain::CreateGpuServiceOnGpuThread, base::Unretained(this),
                  base::Passed(std::move(request)),
-                 base::Passed(gpu_host.PassInterface())));
+                 base::Passed(gpu_host.PassInterface()), preferences));
 }
 
 void GpuMain::CreateDisplayCompositor(
@@ -211,10 +216,11 @@
 
 void GpuMain::CreateGpuServiceOnGpuThread(
     mojom::GpuServiceRequest request,
-    mojom::GpuHostPtrInfo gpu_host_info) {
+    mojom::GpuHostPtrInfo gpu_host_info,
+    const gpu::GpuPreferences& preferences) {
   mojom::GpuHostPtr gpu_host;
   gpu_host.Bind(std::move(gpu_host_info));
-  gpu_service_->InitializeWithHost(std::move(gpu_host));
+  gpu_service_->InitializeWithHost(std::move(gpu_host), preferences);
   gpu_service_->Bind(std::move(request));
 
   if (pending_display_compositor_request_.is_pending()) {
diff --git a/services/ui/gpu/gpu_main.h b/services/ui/gpu/gpu_main.h
index 031b5b9d..a5c859d 100644
--- a/services/ui/gpu/gpu_main.h
+++ b/services/ui/gpu/gpu_main.h
@@ -28,7 +28,8 @@
 
   // mojom::GpuMain implementation:
   void CreateGpuService(mojom::GpuServiceRequest request,
-                        mojom::GpuHostPtr gpu_host) override;
+                        mojom::GpuHostPtr gpu_host,
+                        const gpu::GpuPreferences& preferences) override;
   void CreateDisplayCompositor(
       cc::mojom::DisplayCompositorRequest request,
       cc::mojom::DisplayCompositorClientPtr client) override;
@@ -51,7 +52,8 @@
       cc::mojom::DisplayCompositorRequest request,
       cc::mojom::DisplayCompositorClientPtrInfo client_info);
   void CreateGpuServiceOnGpuThread(mojom::GpuServiceRequest request,
-                                   mojom::GpuHostPtrInfo gpu_host_info);
+                                   mojom::GpuHostPtrInfo gpu_host_info,
+                                   const gpu::GpuPreferences& preferences);
   void BindGpuInternalOnGpuThread(mojom::GpuServiceRequest request);
 
   void TearDownOnCompositorThread();
diff --git a/services/ui/gpu/gpu_service.cc b/services/ui/gpu/gpu_service.cc
index ac657e8..af091f3 100644
--- a/services/ui/gpu/gpu_service.cc
+++ b/services/ui/gpu/gpu_service.cc
@@ -60,10 +60,12 @@
   shutdown_event_.Signal();
 }
 
-void GpuService::InitializeWithHost(mojom::GpuHostPtr gpu_host) {
+void GpuService::InitializeWithHost(mojom::GpuHostPtr gpu_host,
+                                    const gpu::GpuPreferences& preferences) {
   DCHECK(CalledOnValidThread());
   DCHECK(!gpu_host_);
   gpu_host_ = std::move(gpu_host);
+  gpu_preferences_ = preferences;
   gpu_info_.video_decode_accelerator_capabilities =
       media::GpuVideoDecodeAccelerator::GetCapabilities(gpu_preferences_);
   gpu_info_.video_encode_accelerator_supported_profiles =
diff --git a/services/ui/gpu/gpu_service.h b/services/ui/gpu/gpu_service.h
index f2978fe..ae45e55 100644
--- a/services/ui/gpu/gpu_service.h
+++ b/services/ui/gpu/gpu_service.h
@@ -19,7 +19,6 @@
 #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
 #include "gpu/ipc/service/gpu_config.h"
 #include "gpu/ipc/service/x_util.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/ui/gpu/interfaces/gpu_host.mojom.h"
 #include "services/ui/gpu/interfaces/gpu_service.mojom.h"
@@ -53,9 +52,18 @@
 
   ~GpuService() override;
 
-  void InitializeWithHost(mojom::GpuHostPtr gpu_host);
+  void InitializeWithHost(mojom::GpuHostPtr gpu_host,
+                          const gpu::GpuPreferences& preferences);
   void Bind(mojom::GpuServiceRequest request);
 
+  media::MediaGpuChannelManager* media_gpu_channel_manager() {
+    return media_gpu_channel_manager_.get();
+  }
+
+  gpu::GpuChannelManager* gpu_channel_manager() {
+    return gpu_channel_manager_.get();
+  }
+
  private:
   friend class GpuMain;
 
diff --git a/services/ui/gpu/interfaces/gpu_host.mojom b/services/ui/gpu/interfaces/gpu_host.mojom
index b4baab5..1d2b8fb 100644
--- a/services/ui/gpu/interfaces/gpu_host.mojom
+++ b/services/ui/gpu/interfaces/gpu_host.mojom
@@ -9,6 +9,8 @@
 import "services/ui/gpu/interfaces/context_lost_reason.mojom";
 import "url/mojo/url.mojom";
 
+// Communication channel from the gpu process to the gpu host. This interface
+// should never have any sync function calls.
 interface GpuHost {
   DidInitialize(gpu.mojom.GpuInfo gpu_info);
   DidCreateOffscreenContext(url.mojom.Url url);
diff --git a/services/ui/gpu/interfaces/gpu_main.mojom b/services/ui/gpu/interfaces/gpu_main.mojom
index 9b932746..985b823 100644
--- a/services/ui/gpu/interfaces/gpu_main.mojom
+++ b/services/ui/gpu/interfaces/gpu_main.mojom
@@ -5,6 +5,7 @@
 module ui.mojom;
 
 import "cc/ipc/display_compositor.mojom";
+import "gpu/ipc/common/gpu_preferences.mojom";
 import "services/ui/gpu/interfaces/gpu_host.mojom";
 import "services/ui/gpu/interfaces/gpu_service.mojom";
 
@@ -16,5 +17,6 @@
     cc.mojom.DisplayCompositorClient display_compositor_client);
 
   CreateGpuService(GpuService& gpu_service,
-                   GpuHost gpu_host);
+                   GpuHost gpu_host,
+                   gpu.mojom.GpuPreferences preferences);
 };
diff --git a/services/ui/ws/gpu_host.cc b/services/ui/ws/gpu_host.cc
index 78304942..bfa771d 100644
--- a/services/ui/ws/gpu_host.cc
+++ b/services/ui/ws/gpu_host.cc
@@ -107,8 +107,13 @@
   //   connector->BindInterface("gpu", &gpu_main_);
   gpu_main_impl_ = base::MakeUnique<GpuMain>(MakeRequest(&gpu_main_));
   gpu_main_impl_->OnStart();
+
+  // TODO(sad): Correctly initialize gpu::GpuPreferences (like it is initialized
+  // in GpuProcessHost::Init()).
+  gpu::GpuPreferences preferences;
   gpu_main_->CreateGpuService(MakeRequest(&gpu_service_),
-                              gpu_host_binding_.CreateInterfacePtrAndBind());
+                              gpu_host_binding_.CreateInterfacePtrAndBind(),
+                              preferences);
   gpu_memory_buffer_manager_ = base::MakeUnique<ServerGpuMemoryBufferManager>(
       gpu_service_.get(), next_client_id_++);
 }
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 1306231c..25530a5c 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -41,10 +41,7 @@
     "//third_party/skia/include/utils",
   ]
 
-  defines = [
-    "SK_IGNORE_DW_GRAY_FIX",
-    "SK_LEGACY_FONTMGR_FACTORY",
-  ]
+  defines = [ "SK_IGNORE_DW_GRAY_FIX" ]
   defines += skia_for_chromium_defines
 
   defines += []
diff --git a/skia/ext/fontmgr_default_android.cc b/skia/ext/fontmgr_default_android.cc
index 668cb56..1bbd9d1d 100644
--- a/skia/ext/fontmgr_default_android.cc
+++ b/skia/ext/fontmgr_default_android.cc
@@ -8,14 +8,15 @@
 #include "third_party/skia/include/ports/SkFontMgr_android.h"
 
 namespace {
+// An owning leaky bare pointer.
 SkFontMgr* g_default_fontmgr;
 }  // namespace
 
-SK_API void SetDefaultSkiaFactory(SkFontMgr* fontmgr) {
-  g_default_fontmgr = fontmgr;
+SK_API void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) {
+  g_default_fontmgr = fontmgr.release();
 }
 
-SK_API SkFontMgr* SkFontMgr::Factory() {
-  return g_default_fontmgr ? SkRef(g_default_fontmgr)
+SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() {
+  return g_default_fontmgr ? sk_ref_sp(g_default_fontmgr)
                            : SkFontMgr_New_Android(nullptr);
 }
diff --git a/skia/ext/fontmgr_default_android.h b/skia/ext/fontmgr_default_android.h
index b774050..1dda9c6 100644
--- a/skia/ext/fontmgr_default_android.h
+++ b/skia/ext/fontmgr_default_android.h
@@ -8,7 +8,8 @@
 #include "third_party/skia/include/core/SkTypes.h"
 
 class SkFontMgr;
+template <typename T> class sk_sp;
 
-SK_API void SetDefaultSkiaFactory(SkFontMgr* fontmgr);
+SK_API void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr);
 
 #endif  // SKIA_EXT_FONTMGR_DEFAULT_ANDROID_H_
diff --git a/skia/ext/fontmgr_default_linux.cc b/skia/ext/fontmgr_default_linux.cc
index abb0dbe..22430e4 100644
--- a/skia/ext/fontmgr_default_linux.cc
+++ b/skia/ext/fontmgr_default_linux.cc
@@ -13,13 +13,14 @@
 SkFontMgr* g_default_fontmgr;
 }  // namespace
 
-void SetDefaultSkiaFactory(SkFontMgr* fontmgr) {
-  g_default_fontmgr = fontmgr;
+void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) {
+  SkASSERT(g_default_fontmgr == nullptr);
+  g_default_fontmgr = fontmgr.release();
 }
 
-SK_API SkFontMgr* SkFontMgr::Factory() {
+SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() {
   if (g_default_fontmgr) {
-    return SkRef(g_default_fontmgr);
+    return sk_ref_sp(g_default_fontmgr);
   }
   sk_sp<SkFontConfigInterface> fci(SkFontConfigInterface::RefGlobal());
   return fci ? SkFontMgr_New_FCI(std::move(fci)) : nullptr;
diff --git a/skia/ext/fontmgr_default_linux.h b/skia/ext/fontmgr_default_linux.h
index b0ab6e78..29420074 100644
--- a/skia/ext/fontmgr_default_linux.h
+++ b/skia/ext/fontmgr_default_linux.h
@@ -8,7 +8,8 @@
 #include "third_party/skia/include/core/SkTypes.h"
 
 class SkFontMgr;
+template <typename T> class sk_sp;
 
-void SK_API SetDefaultSkiaFactory(SkFontMgr* fontmgr);
+void SK_API SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr);
 
 #endif  // SKIA_EXT_FONTMGR_DEFAULT_LINUX_H_
diff --git a/skia/ext/fontmgr_default_win.cc b/skia/ext/fontmgr_default_win.cc
index 3b1031f..6c451fa 100644
--- a/skia/ext/fontmgr_default_win.cc
+++ b/skia/ext/fontmgr_default_win.cc
@@ -9,19 +9,21 @@
 
 namespace {
 
+// This is a leaky bare owning pointer.
 SkFontMgr* g_default_fontmgr;
 
 }  // namespace
 
-void SetDefaultSkiaFactory(SkFontMgr* fontmgr) {
-  g_default_fontmgr = fontmgr;
+void SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr) {
+  SkASSERT(g_default_fontmgr == nullptr);
+  g_default_fontmgr = fontmgr.release();
 }
 
-SK_API SkFontMgr* SkFontMgr::Factory() {
+SK_API sk_sp<SkFontMgr> SkFontMgr::Factory() {
   // This will be set when DirectWrite is in use, and an SkFontMgr has been
   // created with the pre-sandbox warmed up one. Otherwise, we fallback to a
   // GDI SkFontMgr which is used in the browser.
   if (g_default_fontmgr)
-    return SkRef(g_default_fontmgr);
+    return sk_ref_sp(g_default_fontmgr);
   return SkFontMgr_New_GDI();
 }
diff --git a/skia/ext/fontmgr_default_win.h b/skia/ext/fontmgr_default_win.h
index cea72c1b..a41d94ad 100644
--- a/skia/ext/fontmgr_default_win.h
+++ b/skia/ext/fontmgr_default_win.h
@@ -8,7 +8,8 @@
 #include "third_party/skia/include/core/SkTypes.h"
 
 class SkFontMgr;
+template <typename T> class sk_sp;
 
-void SK_API SetDefaultSkiaFactory(SkFontMgr* fontmgr);
+void SK_API SetDefaultSkiaFactory(sk_sp<SkFontMgr> fontmgr);
 
 #endif  // SKIA_EXT_FONTMGR_DEFAULT_WIN_H_
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index af896f0..2cfec2b 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -98243,6 +98243,25 @@
   "Win 7 Intel GPU Perf": {
     "isolated_scripts": [
       {
+        "args": [],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:041a",
+              "id": "build166-m1",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [
           "battor.power_cases",
           "-v",
@@ -100979,6 +100998,25 @@
         }
       },
       {
+        "args": [],
+        "isolate_name": "load_library_perf_tests",
+        "name": "load_library_perf_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:041a",
+              "id": "build166-m1",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [
           "loading.cluster_telemetry",
           "-v",
@@ -102860,6 +102898,25 @@
         }
       },
       {
+        "args": [],
+        "isolate_name": "performance_browser_tests",
+        "name": "performance_browser_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:041a",
+              "id": "build166-m1",
+              "os": "Windows-2008ServerR2-SP1",
+              "pool": "Chrome-perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 7200,
+          "io_timeout": 3600
+        }
+      },
+      {
         "args": [
           "power.android_acceptance",
           "-v",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
index fd45f85e..eaa5322 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -41,9 +41,6 @@
 crbug.com/551000 http/tests/inspector/network/network-initiator.html [ Failure ]
 crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-document-initiator.html [ Failure ]
 crbug.com/551000 virtual/mojo-loading/http/tests/inspector/network/network-initiator.html [ Failure ]
-#  We are missing several parameters in network har reports.
-crbug.com/551000 http/tests/inspector/resource-parameters.html [ Failure ]
-crbug.com/551000 virtual/mojo-loading/http/tests/inspector/resource-parameters.html [ Failure ]
 #  Duplicate started loading output.
 crbug.com/551000 inspector-protocol/page/frameAttachedDetached.html [ Failure ]
 crbug.com/551000 inspector-protocol/page/frameStartedLoading.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 673f204..cd0c1216 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -114,8 +114,8 @@
 webkit.org/b/90488 [ Debug ] virtual/mojo-loading/http/tests/inspector-enabled/ [ Slow ]
 webkit.org/b/90488 [ Debug ] inspector-protocol/ [ Slow ]
 crbug.com/451577 inspector/console [ Slow ]
-crbug.com/451577 [ Win ] http/tests/inspector/network/network-datareceived.html [ Slow ]
-crbug.com/451577 [ Win ] virtual/mojo-loading/http/tests/inspector/network/network-datareceived.html [ Slow ]
+crbug.com/679833 http/tests/inspector/network/network-datareceived.html [ Slow ]
+crbug.com/679833 virtual/mojo-loading/http/tests/inspector/network/network-datareceived.html [ Slow ]
 
 # Debugger and profiler tests are slow in Release as well.
 crbug.com/450493 inspector/sources/ [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html
new file mode 100644
index 0000000..3ec49e4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-constructor.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="resources/canvas-Float32ImageData.js"></script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html
new file mode 100644
index 0000000..b3c97567
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-Float32ImageData-workers.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+fetch_tests_from_worker(new Worker("resources/canvas-Float32ImageData-workers.js"));
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
index f1b473d..77d93449 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-constructor-expected.txt
@@ -18,16 +18,16 @@
 PASS new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
 PASS new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4..
-PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height)..
-PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4..
+PASS new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number..
+PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
 PASS new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
-PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS (new ImageData(new Uint8ClampedArray(28), 7)).height is 1
 PASS imageDataFromData.width is 100
 PASS imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
index 51185d7..8f444dd 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageData-workers-expected.txt
@@ -19,16 +19,16 @@
 PASS [Worker] new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
 PASS [Worker] new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4..
-PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not equal to (4 * width * height)..
-PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of 4..
+PASS [Worker] new ImageData(new Uint8ClampedArray(28), 7, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number..
+PASS [Worker] new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
 PASS [Worker] new ImageData(self, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS [Worker] new ImageData(null, 4, 4) threw exception TypeError: Failed to construct 'ImageData': parameter 1 is not of type 'Uint8ClampedArray'..
 PASS [Worker] new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
-PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
-PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
+PASS [Worker] new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
 PASS [Worker] (new ImageData(new Uint8ClampedArray(28), 7)).height is 1
 PASS [Worker] imageDataFromData.width is 100
 PASS [Worker] imageDataFromData.height is 50
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html
new file mode 100644
index 0000000..5731c30
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/float32ImageData-colorSpace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+
+// RGBA(255,0,0,255) -> LinearRGB(0x3c00, 0x0, 0x0, 0x3c00)
+var data = new Float32Array([0x00003c00, 0x0, 0x0, 0x00003c00]);
+
+test(function() {
+
+  assert_equals((new Float32ImageData(1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb.");
+  assert_equals((new Float32ImageData(1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(1, 1, "srgb");}, "SRGB is not supported in Float32ImageData.");
+  assert_throws(null, function() {fImageData = new Float32ImageData(1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor.");
+
+  assert_equals((new Float32ImageData(data, 1, 1)).colorSpace, "linear-rgb", "The default color space for Float32ImageData is linear-rgb.");
+  assert_equals((new Float32ImageData(data, 1, 1, "linear-rgb")).colorSpace, "linear-rgb", "The color space read from Float32ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "legacy-srgb");}, "Legacy SRGB is not supported in Float32ImageData.");
+  assert_throws("NotSupportedError", function() {fImageData = new Float32ImageData(data, 1, 1, "srgb");}, "SRGB is not supported in Float32ImageData.");
+  assert_throws(null, function() {fImageData = new Float32ImageData(data, 1, 1, "undefined");}, "Only members of ImageDataColorSpace enum are processed in Float32ImageData constructor.");
+
+}, 'This test examines the correct behavior of Float32ImageData API in setting and getting ImageDataColorSpace.');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html
new file mode 100644
index 0000000..a170bc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/color-space/imageData-colorSpace.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<body>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+
+var data = new Uint8ClampedArray([255, 0, 0, 255]);
+
+function createImageDataAndGetColorSpace(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(1, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+function createWithDataAndGetColorSpaceW(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(data, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+function createWithDataAndGetColorSpaceWH(colorSpace) {
+  experimental = new ImageData(1,1); 
+  imageData = experimental.createImageData(data, 1, 1, colorSpace)
+  return imageData.colorSpace;
+}
+
+test(function() {
+  assert_equals((new ImageData(1,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createImageDataAndGetColorSpace("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createImageDataAndGetColorSpace("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createImageDataAndGetColorSpace("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createImageDataAndGetColorSpace("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+  assert_equals((new ImageData(data,1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createWithDataAndGetColorSpaceW("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createWithDataAndGetColorSpaceW("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceW("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createWithDataAndGetColorSpaceW("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+  assert_equals((new ImageData(data,1, 1)).colorSpace, "legacy-srgb", "The default color space for ImageData is legacy-srgb.");
+  assert_equals(createWithDataAndGetColorSpaceWH("legacy-srgb"), "legacy-srgb", "The color space read from ImageData is the one that was set.");
+  assert_equals(createWithDataAndGetColorSpaceWH("srgb"), "srgb", "The color space read from ImageData is the one that was set.");
+  assert_throws("NotSupportedError", function() {createWithDataAndGetColorSpaceWH("linear-rgb");}, "Linear RGB is not supported in ImageData.");
+  assert_throws(null, function() {createWithDataAndGetColorSpaceWH("undefined");}, "Only members of ImageDataColorSpace enum are processed in ImageData constructor.");
+
+}, 'This test examines the correct behavior of createImageData API in setting and getting ImageData.colorSpace.');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js
new file mode 100644
index 0000000..7c872b55
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData-workers.js
@@ -0,0 +1,2 @@
+importScripts('../../../resources/testharness.js', 'canvas-Float32ImageData.js');
+done();
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js
new file mode 100644
index 0000000..838297b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/canvas/resources/canvas-Float32ImageData.js
@@ -0,0 +1,121 @@
+function setF16Color(float32ImageData, i, f16Color) {
+  var s = i * 4;
+  float32ImageData[s] = f16Color[0];
+  float32ImageData[s + 1] = f16Color[1];
+  float32ImageData[s + 2] = f16Color[2];
+  float32ImageData[s + 3] = f16Color[3];
+}
+
+function getF16Color(float32ImageData, i) {
+  var result = [];
+  var s = i * 4;
+  for (var j = 0; j < 4; j++) {
+    result[j] = float32ImageData[s + j];
+  }
+  return result;
+}
+
+function compareF16Colors(f16Color1, f16Color2) {
+  for (var j = 0; j < 4; j++)
+    if (f16Color1[j] != f16Color2[j])
+      return false;
+  return true;
+}
+
+test(function() {
+
+  float32ImageData = new Float32ImageData(100, 50);
+  assert_equals(float32ImageData.width, 100,
+      "The width of the float32ImageData should be the width we passed to the constructor.");
+  assert_equals(float32ImageData.height, 50,
+      "The height of the float32ImageData should be the height we passed to the constructor.");
+
+  var f16ColorData = getF16Color(float32ImageData.data, 4);
+  assert_equals(f16ColorData[0], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[1], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[2], 0,
+      "The default ImageData color is transparent black.");
+  assert_equals(f16ColorData[3], 0,
+      "The default ImageData color is transparent black.");
+
+  var testColor = new Float32Array([0x00003c00, 0x00003c01, 0x00003c02, 0x00003c03]);
+  setF16Color(float32ImageData.data, 4, testColor);
+  f16ColorData = getF16Color(float32ImageData.data, 4);
+  assert_equals(f16ColorData[0], 0x00003c00,
+      "The red component of f16 color is the value we set.");
+  assert_equals(f16ColorData[1], 0x00003c01,
+      "The green component of f16 color is the value we set.");
+  assert_equals(f16ColorData[2], 0x00003c02,
+      "The blue component of f16 color is the value we set.");
+  assert_equals(f16ColorData[3], 0x00003c03,
+      "The alpha component of f16 color is the value we set.");
+
+  assert_throws(null, function() {new Float32ImageData(10);},
+      "Float32ImageData constructor requires both width and height.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(0,10);},
+      "Float32ImageData width must be greater than zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(10,0);},
+      "Float32ImageData height must be greater than zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData('width', 'height');},
+      "Float32ImageData width and height must be numbers.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(1 << 31, 1 << 31);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+
+  assert_throws(null, function() {new Float32ImageData(new Float32Array(0));},
+      "The Float32Array passed to the constructor cannot have a length of zero.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(27), 2);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(new Float32Array(28), 7, 0);},
+      "The size of Float32Array passed to the constructor must be equal to 4 * width * height.");
+  assert_throws(null, function() {new Float32ImageData(self, 4, 4);},
+      "The object passed to the constructor as data array should be of type Float32Array.");
+  assert_throws(null, function() {new Float32ImageData(null, 4, 4);},
+      "The object passed to the constructor as data array should be of type Float32Array.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 0);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 13);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31);},
+      "The size of Float32Array passed to the constructor must be divisible by 4 * width.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 'biggish');},
+      "The width parameter must be a number.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 24, 1 << 31);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+  assert_throws("IndexSizeError", function() {new Float32ImageData(float32ImageData.data, 1 << 31, 1 << 24);},
+      "Float32ImageData width multiplied by height must be less than 2^30 to avoid buffer size overflow.");
+  assert_equals((new Float32ImageData(new Float32Array(28), 7)).height, 1,
+      "The height must be equal to size of the data array divided by 4 * width.");
+
+  float32ImageDataFromData = new Float32ImageData(float32ImageData.data, 100);
+  assert_equals(float32ImageDataFromData.width, 100,
+      "The width of the float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_equals(float32ImageDataFromData.height, 50,
+      "The height of the float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_true(float32ImageDataFromData.data == float32ImageData.data,
+      "The pixel data buffer of float32ImageDataFromData should be the same as that of float32ImageData.");
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10),
+                               getF16Color(float32ImageData.data, 10)),
+      "The color of a pixel from float32ImageDataFromData should be the same as that of float32ImageData.");
+  setF16Color(float32ImageData.data, 10, testColor);
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 10),
+                               getF16Color(float32ImageData.data, 10)),
+      "Setting the color of a pixel from float32ImageData must cascade to the same pixel of float32ImageDataFromData.");
+
+  var data = new Float32Array(400);
+  data[22] = 129;
+  float32ImageDataFromData = new Float32ImageData(data, 20, 5);
+  assert_equals(float32ImageDataFromData.width, 20,
+      "The width of the float32ImageData should be the width we passed to the constructor.");
+  assert_equals(float32ImageDataFromData.height, 5,
+      "The height of the Float32ImageData must be equal to size of the Float32Array divided by 4 * width.");
+  assert_true(float32ImageDataFromData.data == data,
+      "The pixel data buffer of float32ImageDataFromData should be the same buffer passed to the constructor.");
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)),
+      "The pixel data of float32ImageDataFromData should be the same as that of the buffer passed to the constructor.");
+  setF16Color(float32ImageDataFromData.data, 2, testColor);
+  assert_true(compareF16Colors(getF16Color(float32ImageDataFromData.data, 2), getF16Color(data, 2)),
+      "Setting the color of a pixel from float32ImageDataFromData must cascade to the same pixel of the buffer passed to the constructor.");
+
+}, 'This test examines the correct behavior of Float32ImageData API.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 27de9fc2..bfb9fb2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -240,6 +240,12 @@
     method readAsBinaryString
     method readAsDataURL
     method readAsText
+interface Float32ImageData
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface ForeignFetchEvent : ExtendableEvent
     getter origin
     getter request
@@ -406,9 +412,12 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InstallEvent : ExtendableEvent
     method constructor
     method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt
index db19d841..2712ad3 100644
--- a/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt
+++ b/third_party/WebKit/LayoutTests/imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions-expected.txt
@@ -10,7 +10,7 @@
 FAIL [[Delete]] Should throw on cross-origin objects assert_throws: Can't delete cross-origin indexed property function "function () { delete C[0]; }" did not throw
 FAIL [[DefineOwnProperty]] Should throw for cross-origin objects assert_throws: Can't define cross-origin value property length function "function () { Object.defineProperty(obj, prop, valueDesc); }" did not throw
 FAIL [[Enumerate]] should return an empty iterator assert_unreached: Shouldn't have been able to enumerate stop on cross-origin Window Reached unreachable code
-FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 873 got 13
+FAIL [[OwnPropertyKeys]] should return all properties from cross-origin objects assert_array_equals: Object.getOwnPropertyNames() gives the right answer for cross-origin Window lengths differ, expected 874 got 13
 PASS A and B jointly observe the same identity for cross-origin Window and Location 
 PASS Cross-origin functions get local Function.prototype 
 FAIL Cross-origin Window accessors get local Function.prototype Cannot read property 'name' of undefined
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
index ff2e741..f7d6294 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@
     getter minValue
     getter value
     method cancelScheduledValues
+    method cancelValuesAndHoldAtTime
     method constructor
     method exponentialRampToValueAtTime
     method linearRampToValueAtTime
@@ -3016,6 +3017,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png
index e6cdd360..df18a23 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt
index 916eb419..66f7e2f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/wicd/test-rightsizing-b-expected.txt
@@ -54,11 +54,11 @@
     layer at (0,0) size 295x295
       LayoutSVGRoot {svg} at (0,0) size 295x295
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGRect {rect} at (0,0) size 295x295 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
-        LayoutSVGEllipse {circle} at (0,0) size 295x295 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
-        LayoutSVGContainer {g} at (44,92) size 207x119
-          LayoutSVGText {text} at (29,62) size 141x81 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 141x80
+        LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
+        LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
+        LayoutSVGContainer {g} at (29.97,62.64) size 140.03x80
+          LayoutSVGText {text} at (29.97,62.64) size 140.03x80 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (29.97,62.64) size 140.03x80
               chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG"
 layer at (347,242) size 147x148
   LayoutEmbeddedObject {object} at (299.59,147) size 147.58x147.58 [bgcolor=#FF0000]
@@ -67,11 +67,11 @@
     layer at (0,0) size 148x148
       LayoutSVGRoot {svg} at (0,0) size 148x148
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGRect {rect} at (0,0) size 148x148 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
-        LayoutSVGEllipse {circle} at (0,0) size 148x148 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
-        LayoutSVGContainer {g} at (22,45) size 104x61
-          LayoutSVGText {text} at (29,61) size 141x82 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 141x82
+        LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
+        LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
+        LayoutSVGContainer {g} at (29.97,61.50) size 140.03x81.08
+          LayoutSVGText {text} at (29.97,61.50) size 140.03x81.08 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (29.97,61.50) size 140.03x81.08
               chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG"
 layer at (499,316) size 73x74
   LayoutEmbeddedObject {object} at (451.61,221) size 73.78x73.78 [bgcolor=#FF0000]
@@ -80,11 +80,11 @@
     layer at (0,0) size 74x74
       LayoutSVGRoot {svg} at (0,0) size 74x74
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGRect {rect} at (0,0) size 74x74 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
-        LayoutSVGEllipse {circle} at (0,0) size 74x74 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
-        LayoutSVGContainer {g} at (11,23) size 52x30
-          LayoutSVGText {text} at (29,62) size 141x80 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 141x79
+        LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
+        LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
+        LayoutSVGContainer {g} at (29.97,62.84) size 140.03x78.38
+          LayoutSVGText {text} at (29.97,62.84) size 140.03x78.38 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (29.97,62.84) size 140.03x78.38
               chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG"
 layer at (577,353) size 37x37
   LayoutEmbeddedObject {object} at (529.83,258) size 36.89x36.89 [bgcolor=#FF0000]
@@ -93,9 +93,9 @@
     layer at (0,0) size 37x37
       LayoutSVGRoot {svg} at (0,0) size 37x37
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
-        LayoutSVGRect {rect} at (0,0) size 37x37 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
-        LayoutSVGEllipse {circle} at (0,0) size 37x37 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
-        LayoutSVGContainer {g} at (5,11) size 27x16
-          LayoutSVGText {text} at (29,60) size 141x82 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (0,0) size 141x82
+        LayoutSVGRect {rect} at (-3000,-1000) size 6200x2200 [fill={[type=SOLID] [color=#5588FF]}] [x=-3000.00] [y=-1000.00] [width=6200.00] [height=2200.00]
+        LayoutSVGEllipse {circle} at (0,0) size 200x200 [fill={[type=SOLID] [color=#0000FF]}] [cx=100.00] [cy=100.00] [r=100.00]
+        LayoutSVGContainer {g} at (29.97,60.14) size 140.03x81.08
+          LayoutSVGText {text} at (29.97,60.14) size 140.03x81.08 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (29.97,60.14) size 140.03x81.08
               chunk 1 (middle anchor) text run 1 at (29.98,125.00) startOffset 0 endOffset 3 width 140.03: "SVG"
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index ff2e741..f7d6294 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@
     getter minValue
     getter value
     method cancelScheduledValues
+    method cancelValuesAndHoldAtTime
     method constructor
     method exponentialRampToValueAtTime
     method linearRampToValueAtTime
@@ -3016,6 +3017,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js b/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js
new file mode 100644
index 0000000..131d881
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/resources/set-foo.js
@@ -0,0 +1 @@
+foo = 1337;
diff --git a/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html b/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html
new file mode 100644
index 0000000..483cdfd1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/animations/script-href-no-animate.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>SVGScriptElement.href should not be animatable</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+var foo = 42;
+
+async_test(t => {
+  window.onload = () => {
+    var s = document.createElementNS('http://www.w3.org/2000/svg', 'script');
+    s.onload = t.unreached_func('Should not get a load event');
+    s.id = 'x';
+    document.querySelector('svg').appendChild(s);
+    requestAnimationFrame(_ => {
+      requestAnimationFrame(t.step_func_done(_ => {
+        assert_equals(foo, 42);
+      }));
+    });
+  };
+});
+</script>
+<svg xmlns:xlink="http://www.w3.org/1999/xlink">
+  <set href="#x" attributeName="href" to="resources/set-foo.js"/>
+  <set href="#x" attributeName="xlink:href" to="resources/set-foo.js"/>
+  <animate href="#x" attributeName="href" to="resources/set-foo.js" dur="0.01s"/>
+  <animate href="#x" attributeName="xlink:href" to="resources/set-foo.js" dur="0.01s"/>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index f7ca39b..eae06c6 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -241,6 +241,12 @@
     method readAsBinaryString
     method readAsDataURL
     method readAsText
+interface Float32ImageData
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface ForeignFetchEvent : ExtendableEvent
     getter origin
     getter request
@@ -407,9 +413,12 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InstallEvent : ExtendableEvent
     method constructor
     method registerForeignFetch
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 2452562e..179caa5 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -368,6 +368,8 @@
     method close
     method constructor
 interface ImageData
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 02dde09..d859f5d 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -387,6 +387,8 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 88ea189..8487d96 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -149,6 +149,7 @@
     getter minValue
     getter value
     method cancelScheduledValues
+    method cancelValuesAndHoldAtTime
     method constructor
     method exponentialRampToValueAtTime
     method linearRampToValueAtTime
@@ -3077,6 +3078,8 @@
     method transferFromImageBitmap
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index ebb785d..c644e8f 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -382,6 +382,8 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html
new file mode 100644
index 0000000..2e64ed08
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-cancel-and-hold.html
@@ -0,0 +1,516 @@
+<!doctype html>
+<html>
+  <head>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="../resources/audit.js"></script>
+    <title>Test CancelValuesAndHoldAtTime</title>
+  </head>
+
+  <body>
+    <script>
+      let sampleRate = 48000;
+      let renderDuration = 0.5;
+
+      let audit = Audit.createTaskRunner();
+
+      // The first few tasks test the cancellation of each relevant automation
+      // function.  For the test, a simple linear ramp from 0 to 1 is used to
+      // start things off.  Then the automation to be tested is scheduled and
+      // cancelled.
+
+      audit.define("linear", function (task, should) {
+        task.describe("Cancel linearRampToValueAtTime");
+        cancelTest(should, linearRampTest("linearRampToValueAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("exponential", function (task, should) {
+        task.describe("Cancel exponentialRampAtTime");
+        // Cancel an exponential ramp.  The thresholds are experimentally
+        // determined.
+        cancelTest(should, function (g, v0, t0, cancelTime) {
+          // Initialize values to 0.
+          g[0].gain.setValueAtTime(0, 0);
+          g[1].gain.setValueAtTime(0, 0);
+          // Schedule a short linear ramp to start things off.
+          g[0].gain.linearRampToValueAtTime(v0, t0);
+          g[1].gain.linearRampToValueAtTime(v0, t0);
+
+          // After the linear ramp, schedule an exponential ramp to the end.
+          // (This is the event that will be be cancelled.)
+          let v1 = 0.001;
+          let t1 = renderDuration;
+
+          g[0].gain.exponentialRampToValueAtTime(v1, t1);
+          g[1].gain.exponentialRampToValueAtTime(v1, t1);
+
+          expectedConstant = Math.fround(v0 * Math.pow(v1 / v0, (
+            cancelTime -
+            t0) / (t1 - t0)));
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "exponentialRampToValue(" + v1 + ", " + t1 + ")",
+            summary: "exponentialRampToValueAtTime",
+          };
+        }, {
+          valueThreshold: 1.8664e-6,
+          curveThreshold: 5.9605e-8
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("setTarget", function (task, should) {
+        task.describe("Cancel setTargetAtTime");
+        // Cancel a setTarget event.
+        cancelTest(should, function (g, v0, t0, cancelTime) {
+          // Initialize values to 0.
+          g[0].gain.setValueAtTime(0, 0);
+          g[1].gain.setValueAtTime(0, 0);
+          // Schedule a short linear ramp to start things off.
+          g[0].gain.linearRampToValueAtTime(v0, t0);
+          g[1].gain.linearRampToValueAtTime(v0, t0);
+
+          // At the end of the linear ramp, schedule a setTarget.  (This is the
+          // event that will be cancelled.)
+          let v1 = 0;
+          let t1 = t0;
+          let timeConstant = 0.05;
+
+          g[0].gain.setTargetAtTime(v1, t1, timeConstant);
+          g[1].gain.setTargetAtTime(v1, t1, timeConstant);
+
+          expectedConstant = Math.fround(v1 + (v0 - v1) * Math.exp(-(
+            cancelTime - t0) / timeConstant));
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "setTargetAtTime(" + v1 + ", " + t1 + ", " +
+              timeConstant + ")",
+            summary: "setTargetAtTime",
+          };
+        }, {
+          valueThreshold: 4.5267e-7, //1.1317e-7,
+          curveThreshold: 0
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("setValueCurve", function (task, should) {
+        task.describe("Cancel setValueCurveAtTime");
+        // Cancel a setValueCurve event.
+        cancelTest(should, function (g, v0, t0, cancelTime) {
+          // Initialize values to 0.
+          g[0].gain.setValueAtTime(0, 0);
+          g[1].gain.setValueAtTime(0, 0);
+          // Schedule a short linear ramp to start things off.
+          g[0].gain.linearRampToValueAtTime(v0, t0);
+          g[1].gain.linearRampToValueAtTime(v0, t0);
+
+          // After the linear ramp, schedule a setValuesCurve. (This is the
+          // event that will be cancelled.)
+          let v1 = 0;
+          let duration = renderDuration - t0;
+
+          // For simplicity, a 2-point curve so we get a linear interpolated result.
+          let curve = Float32Array.from([v0, 0]);
+
+          g[0].gain.setValueCurveAtTime(curve, t0, duration);
+          g[1].gain.setValueCurveAtTime(curve, t0, duration);
+
+          let index = Math.floor((curve.length - 1) / duration * (
+            cancelTime - t0));
+
+          let curvePointsPerFrame = (curve.length - 1) / duration /
+            sampleRate;
+          let virtualIndex = (cancelTime - t0) * sampleRate *
+            curvePointsPerFrame;
+
+          let delta = virtualIndex - index;
+          expectedConstant = curve[0] + (curve[1] - curve[0]) * delta;
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "setValueCurveAtTime([" + curve + "], " + t0 +
+              ", " + duration +
+              ")",
+            summary: "setValueCurveAtTime",
+          };
+        }, {
+          valueThreshold: 9.5368e-9,
+          curveThreshold: 0
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("setValueCurve after end", function (task, should) {
+        task.describe("Cancel setValueCurveAtTime after the end");
+        cancelTest(should, function (g, v0, t0, cancelTime) {
+          // Initialize values to 0.
+          g[0].gain.setValueAtTime(0, 0);
+          g[1].gain.setValueAtTime(0, 0);
+          // Schedule a short linear ramp to start things off.
+          g[0].gain.linearRampToValueAtTime(v0, t0);
+          g[1].gain.linearRampToValueAtTime(v0, t0);
+
+          // After the linear ramp, schedule a setValuesCurve. (This is the
+          // event that will be cancelled.)  Make sure the curve ends before the
+          // cancellation time.
+          let v1 = 0;
+          let duration = cancelTime - t0 - 0.125;
+
+          // For simplicity, a 2-point curve so we get a linear interpolated
+          // result.
+          let curve = Float32Array.from([v0, 0]);
+
+          g[0].gain.setValueCurveAtTime(curve, t0, duration);
+          g[1].gain.setValueCurveAtTime(curve, t0, duration);
+
+          expectedConstant = curve[1];
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "setValueCurveAtTime([" + curve + "], " + t0 +
+              ", " + duration +
+              ")",
+            summary: "setValueCurveAtTime",
+          };
+        }, {
+          valueThreshold: 0,
+          curveThreshold: 0
+        }).then(task.done.bind(task));
+      });
+
+      // Special case where we schedule a setTarget and there is no earlier
+      // automation event.  This tests that we pick up the starting point
+      // correctly from the last setting of the AudioParam value attribute.
+
+
+      audit.define("initial setTarget", function (task, should) {
+        task.describe("Cancel with initial setTargetAtTime");
+        cancelTest(should, function (g, v0, t0, cancelTime) {
+          let v1 = 0;
+          let timeConstant = 0.1;
+          g[0].gain.value = 1;
+          g[0].gain.setTargetAtTime(v1, t0, timeConstant);
+          g[1].gain.value = 1;
+          g[1].gain.setTargetAtTime(v1, t0, timeConstant);
+
+          let expectedConstant = Math.fround(v1 + (v0 - v1) * Math.exp(-
+            (cancelTime - t0) /
+            timeConstant));
+
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "setTargetAtTime(" + v1 + ", " + t0 + ", " +
+              timeConstant + ")",
+            summary: "Initial setTargetAtTime",
+          };
+        }, {
+          valueThreshold: 1.2320e-6,
+          curveThreshold: 0
+        }).then(task.done.bind(task));
+      });
+
+      // Test automations scheduled after the call to cancelValuesAndHoldAtTime.
+      // Very similar to the above tests, but we also schedule an event after
+      // cancelValuesAndHoldAtTime and verify that curve after cancellation has
+      // the correct values.
+
+      audit.define("post cancel: Linear", function (task, should) {
+        // Run the cancel test using a linearRamp as the event to be cancelled.
+        // Then schedule another linear ramp after the cancellation.
+        task.describe("LinearRamp after cancelling");
+        cancelTest(should, linearRampTest(
+          "Post cancellation linearRampToValueAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }, function (g, cancelTime, expectedConstant) {
+          // Schedule the linear ramp on g[0], and do the same for g[2], using the starting point
+          // given by expectedConstant.
+          let v2 = 2;
+          let t2 = cancelTime + 0.125;
+          g[0].gain.linearRampToValueAtTime(v2, t2);
+          g[2].gain.setValueAtTime(expectedConstant, cancelTime);
+          g[2].gain.linearRampToValueAtTime(v2, t2);
+          return {
+            constantEndTime: cancelTime,
+            message: "Post linearRamp(" + v2 + ", " + t2 + ")"
+          };
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("post cancel: Exponential", function (task, should) {
+        task.describe("ExponentialRamp after cancelling");
+        // Run the cancel test using a linearRamp as the event to be cancelled.
+        // Then schedule an exponential ramp after the cancellation.
+        cancelTest(should, linearRampTest(
+          "Post cancel exponentialRampToValueAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }, function (g, cancelTime, expectedConstant) {
+          // Schedule the exponential ramp on g[0], and do the same for g[2],
+          // using the starting point given by expectedConstant.
+          let v2 = 2;
+          let t2 = cancelTime + 0.125;
+          g[0].gain.exponentialRampToValueAtTime(v2, t2);
+          g[2].gain.setValueAtTime(expectedConstant, cancelTime);
+          g[2].gain.exponentialRampToValueAtTime(v2, t2);
+          return {
+            constantEndTime: cancelTime,
+            message: "Post exponentialRamp(" + v2 + ", " + t2 + ")"
+          };
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("post cancel: ValueCurve", function (task, should) {
+        // Run the cancel test using a linearRamp as the event to be cancelled.
+        // Then schedule a setValueCurve after the cancellation.
+        cancelTest(should, linearRampTest("Post cancel setValueCurveAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }, function (g, cancelTime, expectedConstant) {
+          // Schedule the exponential ramp on g[0], and do the same for g[2],
+          // using the starting point given by expectedConstant.
+          let t2 = cancelTime + 0.125;
+          let duration = 0.125;
+          let curve = Float32Array.from([.125, 2]);
+          g[0].gain.setValueCurveAtTime(curve, t2, duration);
+          g[2].gain.setValueAtTime(expectedConstant, cancelTime);
+          g[2].gain.setValueCurveAtTime(curve, t2, duration);
+          return {
+            constantEndTime: cancelTime,
+            message: "Post setValueCurve([" + curve + "], " + t2 + ", " +
+              duration + ")",
+            errorThreshold: 8.3998e-5
+          };
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("post cancel: setTarget", function (task, should) {
+        // Run the cancel test using a linearRamp as the event to be cancelled.
+        // Then schedule a setTarget after the cancellation.
+        cancelTest(should, linearRampTest("Post cancel setTargetAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }, function (g, cancelTime, expectedConstant) {
+          // Schedule the exponential ramp on g[0], and do the same for g[2],
+          // using the starting point given by expectedConstant.
+          let v2 = 0.125;
+          let t2 = cancelTime + 0.125;
+          let timeConstant = 0.1;
+          g[0].gain.setTargetAtTime(v2, t2, timeConstant);
+          g[2].gain.setValueAtTime(expectedConstant, cancelTime);
+          g[2].gain.setTargetAtTime(v2, t2, timeConstant);
+          return {
+            constantEndTime: cancelTime + 0.125,
+            message: "Post setTargetAtTime(" + v2 + ", " + t2 + ", " +
+              timeConstant + ")",
+            errorThreshold: 8.4037e-5
+          };
+        }).then(task.done.bind(task));
+      });
+
+      audit.define("post cancel: setValue", function (task, should) {
+        // Run the cancel test using a linearRamp as the event to be cancelled.
+        // Then schedule a setTarget after the cancellation.
+        cancelTest(should, linearRampTest("Post cancel setValueAtTime"), {
+          valueThreshold: 8.3998e-5,
+          curveThreshold: 0
+        }, function (g, cancelTime, expectedConstant) {
+          // Schedule the exponential ramp on g[0], and do the same for g[2],
+          // using the starting point given by expectedConstant.
+          let v2 = 0.125;
+          let t2 = cancelTime + 0.125;
+          g[0].gain.setValueAtTime(v2, t2);
+          g[2].gain.setValueAtTime(expectedConstant, cancelTime);
+          g[2].gain.setValueAtTime(v2, t2);
+          return {
+            constantEndTime: cancelTime + 0.125,
+            message: "Post setValueAtTime(" + v2 + ", " + t2 + ")"
+          };
+        }).then(task.done.bind(task));
+      });
+
+      audit.run();
+
+      // Common function for doing a linearRamp test.  This just does a linear
+      // ramp from 0 to v0 at from time 0 to t0.  Then another linear ramp is
+      // scheduled from v0 to 0 from time t0 to t1.  This is the ramp that is to
+      // be cancelled.
+      function linearRampTest(message) {
+        return function (g, v0, t0, cancelTime) {
+          g[0].gain.setValueAtTime(0, 0);
+          g[1].gain.setValueAtTime(0, 0);
+          g[0].gain.linearRampToValueAtTime(v0, t0);
+          g[1].gain.linearRampToValueAtTime(v0, t0);
+
+          let v1 = 0;
+          let t1 = renderDuration;
+          g[0].gain.linearRampToValueAtTime(v1, t1);
+          g[1].gain.linearRampToValueAtTime(v1, t1);
+
+          expectedConstant = Math.fround(v0 + (v1 - v0) * (cancelTime - t0) /
+            (t1 - t0));
+
+          return {
+            expectedConstant: expectedConstant,
+            autoMessage: "linearRampToValue(" + v1 + ", " + t1 + ")",
+            summary: message,
+          };
+        }
+      }
+
+      // Run the cancellation test. A set of automations is created and
+      // canceled.
+      //
+      // |testFunction| is a function that generates the automation to be
+      // tested.  It is given an array of 3 gain nodes, the value and time of an
+      // initial linear ramp, and the time where the cancellation should occur.
+      // The function must do the automations for the first two gain nodes.  It
+      // must return a dictionary with |expectedConstant| being the value at the
+      // cancellation time, |autoMessage| for message to describe the test, and
+      // |summary| for general summary message to be printed at the end of the
+      // test.
+      //
+      // |thresholdOptions| is a property bag that specifies the error threshold
+      // to use. |thresholdOptions.valueThreshold| is the error threshold for
+      // comparing the actual constant output after cancelling to the expected
+      // value.  |thresholdOptions.curveThreshold| is the error threshold for
+      // comparing the actual and expected automation curves before the
+      // cancelation point.
+      //
+      // For cancellation tests, |postCancelTest| is a function that schedules
+      // some automation after the cancellation.  It takes 3 arguments: an array
+      // of the gain nodes, the cancellation time, and the expected value at the
+      // cancellation time.  This function must return a dictionary consisting
+      // of |constantEndtime| indicating when the held constant from
+      // cancellation stops being constant, |message| giving a summary of what
+      // automation is being used, and |errorThreshold| that is the error
+      // threshold between the expected curve and the actual curve.
+      //
+      function cancelTest(should, testerFunction, thresholdOptions,
+        postCancelTest) {
+        // Create a context with three channels.  Channel 0 is the test channel
+        // containing the actual output that includes the cancellation of
+        // events.  Channel 1 is the expected data upto the cancellation so we
+        // can verify the cancellation produced the correct result.  Channel 2
+        // is for verifying events inserted after the cancellation so we can
+        // verify that automations are correctly generated after the
+        // cancellation point.
+        let context = new OfflineAudioContext(3, renderDuration * sampleRate,
+          sampleRate);
+
+        // Test source is a constant signal
+        let src = context.createBufferSource();
+        src.buffer = createConstantBuffer(context, 1, 1);
+        src.loop = true;
+
+        // We'll do the automation tests with three gain nodes.  One (g0) will
+        // have cancelValuesAndHoldAtTime and the other (g1) will not.  g1 is
+        // used as the expected result for that automation up to the
+        // cancellation point.  They should be the same.  The third node (g2) is
+        // used for testing automations inserted after the cancellation point,
+        // if any.  g2 is the expected result from the cancellation point to the
+        // end of the test.
+
+        let g0 = context.createGain();
+        let g1 = context.createGain();
+        let g2 = context.createGain();
+        let v0 = 1;
+        let t0 = 0.01;
+
+        let cancelTime = renderDuration / 2;
+
+        // Test automation here.  The tester function is responsible for setting
+        // up the gain nodes with the desired automation for testing.
+        autoResult = testerFunction([g0, g1, g2], v0, t0, cancelTime);
+        let expectedConstant = autoResult.expectedConstant;
+        let autoMessage = autoResult.autoMessage;
+        let summaryMessage = autoResult.summary;
+
+        // Cancel scheduled events somewhere in the middle of the test
+        // automation.
+        g0.gain.cancelValuesAndHoldAtTime(cancelTime);
+
+        let constantEndTime;
+        if (postCancelTest) {
+          postResult = postCancelTest([g0, g1, g2], cancelTime,
+            expectedConstant);
+          constantEndTime = postResult.constantEndTime;
+        }
+
+        // Connect everything together (with a merger to make a two-channel
+        // result).  Channel 0 is the test (with cancelValuesAndHoldAtTime) and
+        // channel 1 is the reference (without cancelValuesAndHoldAtTime).
+        // Channel 1 is used to verify that everything up to the cancellation
+        // has the correct values.
+        src.connect(g0);
+        src.connect(g1);
+        src.connect(g2);
+        let merger = context.createChannelMerger(3);
+        g0.connect(merger, 0, 0);
+        g1.connect(merger, 0, 1);
+        g2.connect(merger, 0, 2);
+        merger.connect(context.destination);
+
+        // Go!
+        src.start();
+
+        return context.startRendering().then(function (buffer) {
+          let actual = buffer.getChannelData(0);
+          let expected = buffer.getChannelData(1);
+
+          // The actual output should be a constant from the cancel time to the
+          // end.  We use the last value of the actual output as the constant,
+          // but we also want to compare that with what we thought it should
+          // really be.
+
+          let cancelFrame = Math.ceil(cancelTime * sampleRate);
+
+          // Verify that the curves up to the cancel time are "identical".  The
+          // should be but round-off may make them differ slightly due to the
+          // way cancelling is done.
+          let endFrame = Math.floor(cancelTime * sampleRate);
+          should(actual.slice(0, endFrame),
+              autoMessage + " up to time " + cancelTime)
+            .beCloseToArray(expected.slice(0, endFrame), {
+              absoluteThreshold: thresholdOptions.curveThreshold
+            });
+
+          // Verify the output after the cancellation is a constant.
+          let actualTail;
+          let constantEndFrame;
+
+          if (postCancelTest) {
+            constantEndFrame = Math.ceil(constantEndTime * sampleRate);
+            actualTail = actual.slice(cancelFrame, constantEndFrame);
+          } else {
+            actualTail = actual.slice(cancelFrame);
+          }
+
+          let actualConstant = actual[cancelFrame];
+
+          should(actualTail, "Cancelling " + autoMessage + " at time " +
+              cancelTime)
+            .beConstantValueOf(actualConstant);
+
+          // Verify that the constant is the value we expect.
+          should(actualConstant, "Expected value for cancelling " +
+              autoMessage + " at time " +
+              cancelTime)
+            .beCloseTo(expectedConstant, {
+              threshold: thresholdOptions.valueThreshold
+            });
+
+          // Verify the curve after the constantEndTime matches our
+          // expectations.
+          if (postCancelTest) {
+            let c2 = buffer.getChannelData(2);
+            should(actual.slice(constantEndFrame), postResult.message)
+              .beCloseToArray(c2.slice(constantEndFrame), {
+                absoluteThreshold: postResult.errorThreshold || 0
+              });
+          }
+        });
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index a71964a..90cea8fa 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -248,6 +248,13 @@
 [Worker]     method readAsBinaryString
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
+[Worker] interface Float32ImageData
+[Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
+[Worker]     getter height
+[Worker]     getter width
+[Worker]     method constructor
 [Worker] interface FormData
 [Worker]     attribute @@toStringTag
 [Worker]     method @@iterator
@@ -428,9 +435,12 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
+[Worker]     method createImageData
 [Worker] interface MessageChannel
 [Worker]     attribute @@toStringTag
 [Worker]     getter port1
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 1886d67..ecad6fe 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -214,6 +214,7 @@
     getter minValue
     getter value
     method cancelScheduledValues
+    method cancelValuesAndHoldAtTime
     method constructor
     method exponentialRampToValueAtTime
     method linearRampToValueAtTime
@@ -1837,6 +1838,13 @@
     setter onloadend
     setter onloadstart
     setter onprogress
+interface Float32ImageData
+    attribute @@toStringTag
+    getter colorSpace
+    getter data
+    getter height
+    getter width
+    method constructor
 interface FocusEvent : UIEvent
     attribute @@toStringTag
     getter relatedTarget
@@ -3657,9 +3665,12 @@
     method takePhoto
 interface ImageData
     attribute @@toStringTag
+    getter colorSpace
+    getter data
     getter height
     getter width
     method constructor
+    method createImageData
 interface InputDeviceCapabilities
     attribute @@toStringTag
     getter firesTouchEvents
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
index 0e9045a..5214a44 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -243,6 +243,13 @@
 [Worker]     method readAsBinaryString
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
+[Worker] interface Float32ImageData
+[Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
+[Worker]     getter height
+[Worker]     getter width
+[Worker]     method constructor
 [Worker] interface FormData
 [Worker]     attribute @@toStringTag
 [Worker]     method @@iterator
@@ -423,9 +430,12 @@
 [Worker]     method constructor
 [Worker] interface ImageData
 [Worker]     attribute @@toStringTag
+[Worker]     getter colorSpace
+[Worker]     getter data
 [Worker]     getter height
 [Worker]     getter width
 [Worker]     method constructor
+[Worker]     method createImageData
 [Worker] interface MessageChannel
 [Worker]     attribute @@toStringTag
 [Worker]     getter port1
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index b65c97c..0b930966 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -65,6 +65,8 @@
                     "core/v8/IDLDictionaryBase.cpp",
                     "core/v8/IDLDictionaryBase.h",
                     "core/v8/Iterable.h",
+                    "core/v8/LocalWindowProxy.cpp",
+                    "core/v8/LocalWindowProxy.h",
                     "core/v8/Maplike.h",
                     "core/v8/Microtask.cpp",
                     "core/v8/Microtask.h",
@@ -72,6 +74,8 @@
                     "core/v8/Nullable.h",
                     "core/v8/RejectedPromises.cpp",
                     "core/v8/RejectedPromises.h",
+                    "core/v8/RemoteWindowProxy.cpp",
+                    "core/v8/RemoteWindowProxy.h",
                     "core/v8/RetainedDOMInfo.cpp",
                     "core/v8/RetainedDOMInfo.h",
                     "core/v8/RetainedObjectInfo.h",
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
new file mode 100644
index 0000000..a0d7e39
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bindings/core/v8/LocalWindowProxy.h"
+
+#include "bindings/core/v8/ConditionalFeatures.h"
+#include "bindings/core/v8/DOMWrapperWorld.h"
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8DOMActivityLogger.h"
+#include "bindings/core/v8/V8HTMLDocument.h"
+#include "bindings/core/v8/V8HiddenValue.h"
+#include "bindings/core/v8/V8Initializer.h"
+#include "bindings/core/v8/V8PrivateProperty.h"
+#include "bindings/core/v8/V8Window.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
+#include "core/html/DocumentNameCollection.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/inspector/MainThreadDebugger.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "platform/Histogram.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/ScriptForbiddenScope.h"
+#include "platform/heap/Handle.h"
+#include "platform/instrumentation/tracing/TraceEvent.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "wtf/Assertions.h"
+#include <v8.h>
+
+namespace blink {
+
+void LocalWindowProxy::disposeContext(GlobalDetachmentBehavior behavior) {
+  if (m_lifecycle != Lifecycle::ContextInitialized)
+    return;
+
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Context> context = m_scriptState->context();
+  // The embedder could run arbitrary code in response to the
+  // willReleaseScriptContext callback, so all disposing should happen after
+  // it returns.
+  frame()->loader().client()->willReleaseScriptContext(context,
+                                                       m_world->worldId());
+  MainThreadDebugger::instance()->contextWillBeDestroyed(m_scriptState.get());
+
+  WindowProxy::disposeContext(behavior);
+}
+
+void LocalWindowProxy::initialize() {
+  TRACE_EVENT1("v8", "LocalWindowProxy::initialize", "isMainWindow",
+               frame()->isMainFrame());
+  SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
+      frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy"
+                             : "Blink.Binding.InitializeNonMainWindowProxy");
+
+  ScriptForbiddenScope::AllowUserAgentScript allowScript;
+
+  v8::HandleScope handleScope(isolate());
+
+  createContext();
+
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Context> context = m_scriptState->context();
+  if (m_globalProxy.isEmpty()) {
+    m_globalProxy.set(isolate(), context->Global());
+    CHECK(!m_globalProxy.isEmpty());
+  }
+
+  setupWindowPrototypeChain();
+
+  SecurityOrigin* origin = 0;
+  if (m_world->isMainWorld()) {
+    // ActivityLogger for main world is updated within updateDocument().
+    updateDocument();
+    origin = frame()->document()->getSecurityOrigin();
+    // FIXME: Can this be removed when CSP moves to browser?
+    ContentSecurityPolicy* csp = frame()->document()->contentSecurityPolicy();
+    context->AllowCodeGenerationFromStrings(
+        csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
+    context->SetErrorMessageForCodeGenerationFromStrings(
+        v8String(isolate(), csp->evalDisabledErrorMessage()));
+  } else {
+    updateActivityLogger();
+    origin = m_world->isolatedWorldSecurityOrigin();
+    setSecurityToken(origin);
+  }
+
+  MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame(),
+                                                 origin);
+  frame()->loader().client()->didCreateScriptContext(
+      context, m_world->extensionGroup(), m_world->worldId());
+  // If conditional features for window have been queued before the V8 context
+  // was ready, then inject them into the context now
+  if (m_world->isMainWorld()) {
+    installPendingConditionalFeaturesOnWindow(m_scriptState.get());
+  }
+
+  if (m_world->isMainWorld())
+    frame()->loader().dispatchDidClearWindowObjectInMainWorld();
+}
+
+void LocalWindowProxy::createContext() {
+  // Create a new v8::Context with the window object as the global object
+  // (aka the inner global).  Reuse the global proxy object (aka the outer
+  // global) if it already exists.  See the comments in
+  // setupWindowPrototypeChain for the structure of the prototype chain of
+  // the global object.
+  v8::Local<v8::ObjectTemplate> globalTemplate =
+      V8Window::domTemplate(isolate(), *m_world)->InstanceTemplate();
+  CHECK(!globalTemplate.IsEmpty());
+
+  // FIXME: It's not clear what the right thing to do for remote frames is.
+  // The extensions registered don't generally seem to make sense for remote
+  // frames, so skip it for now.
+  Vector<const char*> extensionNames;
+  // Dynamically tell v8 about our extensions now.
+  const V8Extensions& extensions = ScriptController::registeredExtensions();
+  extensionNames.reserveInitialCapacity(extensions.size());
+  int extensionGroup = m_world->extensionGroup();
+  int worldId = m_world->worldId();
+  for (const auto* extension : extensions) {
+    if (!frame()->loader().client()->allowScriptExtension(
+            extension->name(), extensionGroup, worldId))
+      continue;
+
+    extensionNames.push_back(extension->name());
+  }
+  v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(),
+                                                    extensionNames.data());
+
+  v8::Local<v8::Context> context;
+  {
+    V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(
+        V8PerIsolateData::from(isolate()));
+    context =
+        v8::Context::New(isolate(), &extensionConfiguration, globalTemplate,
+                         m_globalProxy.newLocal(isolate()));
+  }
+  CHECK(!context.IsEmpty());
+
+  m_scriptState = ScriptState::create(context, m_world);
+
+  // TODO(haraken): Currently we cannot enable the following DCHECK because
+  // an already detached window proxy can be re-initialized. This is wrong.
+  // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized);
+  m_lifecycle = Lifecycle::ContextInitialized;
+  DCHECK(m_scriptState->contextIsValid());
+}
+
+void LocalWindowProxy::updateDocumentProperty() {
+  DCHECK(m_world->isMainWorld());
+
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Context> context = m_scriptState->context();
+  v8::Local<v8::Value> documentWrapper =
+      ToV8(frame()->document(), context->Global(), isolate());
+  DCHECK(documentWrapper->IsObject());
+  // Update the cached accessor for window.document.
+  CHECK(V8PrivateProperty::getWindowDocumentCachedAccessor(isolate()).set(
+      context, context->Global(), documentWrapper));
+}
+
+void LocalWindowProxy::updateActivityLogger() {
+  m_scriptState->perContextData()->setActivityLogger(
+      V8DOMActivityLogger::activityLogger(
+          m_world->worldId(),
+          frame()->document() ? frame()->document()->baseURI() : KURL()));
+}
+
+void LocalWindowProxy::setSecurityToken(SecurityOrigin* origin) {
+  // If two tokens are equal, then the SecurityOrigins canAccess each other.
+  // If two tokens are not equal, then we have to call canAccess.
+  // Note: we can't use the HTTPOrigin if it was set from the DOM.
+  String token;
+  // If document.domain is modified, v8 needs to do a full canAccess check,
+  // so always use an empty security token in that case.
+  bool delaySet = m_world->isMainWorld() && origin->domainWasSetInDOM();
+  if (origin && !delaySet)
+    token = origin->toString();
+
+  // An empty or "null" token means we always have to call
+  // canAccess. The toString method on securityOrigins returns the
+  // string "null" for empty security origins and for security
+  // origins that should only allow access to themselves. In this
+  // case, we use the global object as the security token to avoid
+  // calling canAccess when a script accesses its own objects.
+  v8::HandleScope handleScope(isolate());
+  v8::Local<v8::Context> context = m_scriptState->context();
+  if (token.isEmpty() || token == "null") {
+    context->UseDefaultSecurityToken();
+    return;
+  }
+
+  if (m_world->isIsolatedWorld()) {
+    SecurityOrigin* frameSecurityOrigin =
+        frame()->document()->getSecurityOrigin();
+    String frameSecurityToken = frameSecurityOrigin->toString();
+    // We need to check the return value of domainWasSetInDOM() on the
+    // frame's SecurityOrigin because, if that's the case, only
+    // SecurityOrigin::m_domain would have been modified.
+    // m_domain is not used by SecurityOrigin::toString(), so we would end
+    // up generating the same token that was already set.
+    if (frameSecurityOrigin->domainWasSetInDOM() ||
+        frameSecurityToken.isEmpty() || frameSecurityToken == "null") {
+      context->UseDefaultSecurityToken();
+      return;
+    }
+    token = frameSecurityToken + token;
+  }
+
+  // NOTE: V8 does identity comparison in fast path, must use a symbol
+  // as the security token.
+  context->SetSecurityToken(v8AtomicString(isolate(), token));
+}
+
+void LocalWindowProxy::updateDocument() {
+  DCHECK(m_world->isMainWorld());
+  // For an uninitialized main window proxy, there's nothing we need
+  // to update. The update is done when the window proxy gets initialized later.
+  if (m_lifecycle == Lifecycle::ContextUninitialized)
+    return;
+  // TODO(yukishiino): Is it okay to not update document when the context
+  // is detached? It's not trivial to fix this because udpateDocumentProperty
+  // requires a not-yet-detached context to instantiate a document wrapper.
+  if (m_lifecycle == Lifecycle::ContextDetached)
+    return;
+
+  updateActivityLogger();
+  updateDocumentProperty();
+  updateSecurityOrigin(frame()->document()->getSecurityOrigin());
+}
+
+static v8::Local<v8::Value> getNamedProperty(
+    HTMLDocument* htmlDocument,
+    const AtomicString& key,
+    v8::Local<v8::Object> creationContext,
+    v8::Isolate* isolate) {
+  if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key))
+    return v8Undefined();
+
+  DocumentNameCollection* items = htmlDocument->documentNamedItems(key);
+  if (items->isEmpty())
+    return v8Undefined();
+
+  if (items->hasExactlyOneItem()) {
+    HTMLElement* element = items->item(0);
+    DCHECK(element);
+    Frame* frame = isHTMLIFrameElement(*element)
+                       ? toHTMLIFrameElement(*element).contentFrame()
+                       : 0;
+    if (frame)
+      return ToV8(frame->domWindow(), creationContext, isolate);
+    return ToV8(element, creationContext, isolate);
+  }
+  return ToV8(items, creationContext, isolate);
+}
+
+static void getter(v8::Local<v8::Name> property,
+                   const v8::PropertyCallbackInfo<v8::Value>& info) {
+  if (!property->IsString())
+    return;
+  // FIXME: Consider passing StringImpl directly.
+  AtomicString name = toCoreAtomicString(property.As<v8::String>());
+  HTMLDocument* htmlDocument = V8HTMLDocument::toImpl(info.Holder());
+  DCHECK(htmlDocument);
+  v8::Local<v8::Value> result =
+      getNamedProperty(htmlDocument, name, info.Holder(), info.GetIsolate());
+  if (!result.IsEmpty()) {
+    v8SetReturnValue(info, result);
+    return;
+  }
+  v8::Local<v8::Value> value;
+  if (info.Holder()
+          ->GetRealNamedPropertyInPrototypeChain(
+              info.GetIsolate()->GetCurrentContext(), property.As<v8::String>())
+          .ToLocal(&value))
+    v8SetReturnValue(info, value);
+}
+
+void LocalWindowProxy::namedItemAdded(HTMLDocument* document,
+                                      const AtomicString& name) {
+  DCHECK(m_world->isMainWorld());
+
+  // Context must be initialized before this point.
+  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
+  // TODO(yukishiino): Is it okay to not update named properties
+  // after the context gets detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
+    return;
+
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Object> documentWrapper =
+      m_world->domDataStore().get(document, isolate());
+  // TODO(yukishiino,peria): We should check if the own property with the same
+  // name already exists or not, and if it exists, we shouldn't define a new
+  // accessor property (it fails).
+  documentWrapper->SetAccessor(isolate()->GetCurrentContext(),
+                               v8String(isolate(), name), getter);
+}
+
+void LocalWindowProxy::namedItemRemoved(HTMLDocument* document,
+                                        const AtomicString& name) {
+  DCHECK(m_world->isMainWorld());
+
+  // Context must be initialized before this point.
+  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
+  // TODO(yukishiino): Is it okay to not update named properties
+  // after the context gets detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
+    return;
+
+  if (document->hasNamedItem(name) || document->hasExtraNamedItem(name))
+    return;
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Object> documentWrapper =
+      m_world->domDataStore().get(document, isolate());
+  documentWrapper
+      ->Delete(isolate()->GetCurrentContext(), v8String(isolate(), name))
+      .ToChecked();
+}
+
+void LocalWindowProxy::updateSecurityOrigin(SecurityOrigin* origin) {
+  // For an uninitialized main window proxy, there's nothing we need
+  // to update. The update is done when the window proxy gets initialized later.
+  if (m_lifecycle == Lifecycle::ContextUninitialized)
+    return;
+  // TODO(yukishiino): Is it okay to not update security origin when the context
+  // is detached?
+  if (m_lifecycle == Lifecycle::ContextDetached)
+    return;
+
+  setSecurityToken(origin);
+}
+
+LocalWindowProxy::LocalWindowProxy(v8::Isolate* isolate,
+                                   LocalFrame& frame,
+                                   RefPtr<DOMWrapperWorld> world)
+    : WindowProxy(isolate, frame, std::move(world)) {}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h
new file mode 100644
index 0000000..e92aea2
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LocalWindowProxy_h
+#define LocalWindowProxy_h
+
+#include "bindings/core/v8/DOMWrapperWorld.h"
+#include "bindings/core/v8/WindowProxy.h"
+#include "core/frame/LocalFrame.h"
+#include "wtf/RefPtr.h"
+#include "wtf/text/AtomicString.h"
+#include <v8.h>
+
+namespace blink {
+
+class HTMLDocument;
+class SecurityOrigin;
+
+// Subclass of WindowProxy that only handles LocalFrame.
+class LocalWindowProxy final : public WindowProxy {
+ public:
+  static LocalWindowProxy* create(v8::Isolate* isolate,
+                                  LocalFrame& frame,
+                                  RefPtr<DOMWrapperWorld> world) {
+    return new LocalWindowProxy(isolate, frame, std::move(world));
+  }
+
+  // Update document object of the frame.
+  void updateDocument();
+
+  void namedItemAdded(HTMLDocument*, const AtomicString&);
+  void namedItemRemoved(HTMLDocument*, const AtomicString&);
+
+  // Update the security origin of a document
+  // (e.g., after setting docoument.domain).
+  void updateSecurityOrigin(SecurityOrigin*);
+
+ private:
+  LocalWindowProxy(v8::Isolate*, LocalFrame&, RefPtr<DOMWrapperWorld>);
+
+  void initialize() override;
+  void disposeContext(GlobalDetachmentBehavior) override;
+
+  // Creates a new v8::Context with the window wrapper object as the global
+  // object (aka the inner global).  Note that the window wrapper and its
+  // prototype chain do not get fully initialized yet, e.g. the window
+  // wrapper is not yet associated with the native DOMWindow object.
+  void createContext();
+
+  void setSecurityToken(SecurityOrigin*);
+
+  // The JavaScript wrapper for the document object is cached on the global
+  // object for fast access. UpdateDocumentProperty sets the wrapper
+  // for the current document on the global object.
+  void updateDocumentProperty();
+
+  // Updates Activity Logger for the current context.
+  void updateActivityLogger();
+
+  LocalFrame* frame() const { return toLocalFrame(WindowProxy::frame()); }
+};
+
+}  // namespace blink
+
+#endif  // LocalWindowProxy_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
new file mode 100644
index 0000000..2bbdba3
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bindings/core/v8/WindowProxy.h"
+
+#include "bindings/core/v8/ConditionalFeatures.h"
+#include "bindings/core/v8/DOMWrapperWorld.h"
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8DOMActivityLogger.h"
+#include "bindings/core/v8/V8Document.h"
+#include "bindings/core/v8/V8GCForContextDispose.h"
+#include "bindings/core/v8/V8HTMLCollection.h"
+#include "bindings/core/v8/V8HTMLDocument.h"
+#include "bindings/core/v8/V8HiddenValue.h"
+#include "bindings/core/v8/V8Initializer.h"
+#include "bindings/core/v8/V8ObjectConstructor.h"
+#include "bindings/core/v8/V8PagePopupControllerBinding.h"
+#include "bindings/core/v8/V8PrivateProperty.h"
+#include "bindings/core/v8/V8Window.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
+#include "core/html/DocumentNameCollection.h"
+#include "core/html/HTMLCollection.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/MainThreadDebugger.h"
+#include "core/loader/DocumentLoader.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "platform/Histogram.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/ScriptForbiddenScope.h"
+#include "platform/heap/Handle.h"
+#include "platform/instrumentation/tracing/TraceEvent.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/Platform.h"
+#include "wtf/Assertions.h"
+#include "wtf/StringExtras.h"
+#include "wtf/text/CString.h"
+#include <algorithm>
+#include <utility>
+#include <v8-debug.h>
+#include <v8.h>
+
+namespace blink {
+
+RemoteWindowProxy::RemoteWindowProxy(v8::Isolate* isolate,
+                                     RemoteFrame& frame,
+                                     RefPtr<DOMWrapperWorld> world)
+    : WindowProxy(isolate, frame, std::move(world)) {}
+
+void RemoteWindowProxy::disposeContext(GlobalDetachmentBehavior behavior) {
+  if (m_lifecycle != Lifecycle::ContextInitialized)
+    return;
+
+  WindowProxy::disposeContext(behavior);
+}
+
+void RemoteWindowProxy::initialize() {
+  TRACE_EVENT1("v8", "RemoteWindowProxy::initialize", "isMainWindow",
+               frame()->isMainFrame());
+  SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
+      frame()->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy"
+                             : "Blink.Binding.InitializeNonMainWindowProxy");
+
+  ScriptForbiddenScope::AllowUserAgentScript allowScript;
+
+  v8::HandleScope handleScope(isolate());
+
+  createContext();
+
+  ScriptState::Scope scope(m_scriptState.get());
+  v8::Local<v8::Context> context = m_scriptState->context();
+  if (m_globalProxy.isEmpty()) {
+    m_globalProxy.set(isolate(), context->Global());
+    CHECK(!m_globalProxy.isEmpty());
+  }
+
+  setupWindowPrototypeChain();
+
+  // Remote frames always require a full canAccess() check.
+  context->UseDefaultSecurityToken();
+}
+
+void RemoteWindowProxy::createContext() {
+  // Create a new v8::Context with the window object as the global object
+  // (aka the inner global).  Reuse the global proxy object (aka the outer
+  // global) if it already exists.  See the comments in
+  // setupWindowPrototypeChain for the structure of the prototype chain of
+  // the global object.
+  v8::Local<v8::ObjectTemplate> globalTemplate =
+      V8Window::domTemplate(isolate(), *m_world)->InstanceTemplate();
+  CHECK(!globalTemplate.IsEmpty());
+
+  v8::Local<v8::Context> context;
+  {
+    V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(
+        V8PerIsolateData::from(isolate()));
+    context = v8::Context::New(isolate(), nullptr, globalTemplate,
+                               m_globalProxy.newLocal(isolate()));
+  }
+  CHECK(!context.IsEmpty());
+
+  m_scriptState = ScriptState::create(context, m_world);
+
+  // TODO(haraken): Currently we cannot enable the following DCHECK because
+  // an already detached window proxy can be re-initialized. This is wrong.
+  // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized);
+  m_lifecycle = Lifecycle::ContextInitialized;
+  DCHECK(m_scriptState->contextIsValid());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h
new file mode 100644
index 0000000..d85780f
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/RemoteWindowProxy.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RemoteWindowProxy_h
+#define RemoteWindowProxy_h
+
+#include "bindings/core/v8/DOMWrapperWorld.h"
+#include "core/frame/RemoteFrame.h"
+#include <v8.h>
+
+namespace blink {
+
+// Subclass of WindowProxy that only handles RemoteFrame.
+class RemoteWindowProxy final : public WindowProxy {
+ public:
+  static RemoteWindowProxy* create(v8::Isolate* isolate,
+                                   RemoteFrame& frame,
+
+                                   RefPtr<DOMWrapperWorld> world) {
+    return new RemoteWindowProxy(isolate, frame, std::move(world));
+  }
+
+ private:
+  RemoteWindowProxy(v8::Isolate*, RemoteFrame&, RefPtr<DOMWrapperWorld>);
+
+  void initialize() override;
+  void disposeContext(GlobalDetachmentBehavior) override;
+
+  // Creates a new v8::Context with the window wrapper object as the global
+  // object (aka the inner global).  Note that the window wrapper and its
+  // prototype chain do not get fully initialized yet, e.g. the window
+  // wrapper is not yet associated with the native DOMWindow object.
+  void createContext();
+};
+
+}  // namespace blink
+
+#endif  // RemoteWindowProxy_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
index e204731d..1f94c6f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -79,7 +79,7 @@
 namespace blink {
 
 ScriptController::ScriptController(LocalFrame* frame)
-    : m_windowProxyManager(WindowProxyManager::create(*frame)) {}
+    : m_windowProxyManager(LocalWindowProxyManager::create(*frame)) {}
 
 DEFINE_TRACE(ScriptController) {
   visitor->trace(m_windowProxyManager);
@@ -209,8 +209,8 @@
                        InspectorUpdateCountersEvent::data());
 }
 
-WindowProxy* ScriptController::windowProxy(DOMWrapperWorld& world) {
-  WindowProxy* windowProxy = m_windowProxyManager->windowProxy(world);
+LocalWindowProxy* ScriptController::windowProxy(DOMWrapperWorld& world) {
+  LocalWindowProxy* windowProxy = m_windowProxyManager->windowProxy(world);
   windowProxy->initializeIfNeeded();
   return windowProxy;
 }
@@ -441,7 +441,7 @@
 
   RefPtr<DOMWrapperWorld> world =
       DOMWrapperWorld::ensureIsolatedWorld(isolate(), worldID, extensionGroup);
-  WindowProxy* isolatedWorldWindowProxy = windowProxy(*world);
+  LocalWindowProxy* isolatedWorldWindowProxy = windowProxy(*world);
   ScriptState* scriptState = isolatedWorldWindowProxy->getScriptState();
   if (!scriptState->contextIsValid())
     return;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h
index 83a4cc9..747bea0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h
@@ -52,7 +52,6 @@
 class KURL;
 class ScriptSourceCode;
 class SecurityOrigin;
-class WindowProxy;
 class Widget;
 
 typedef WTF::Vector<v8::Extension*> V8Extensions;
@@ -80,7 +79,7 @@
 
   // This returns an initialized window proxy. (If the window proxy is not
   // yet initialized, it's implicitly initialized at the first access.)
-  WindowProxy* windowProxy(DOMWrapperWorld&);
+  LocalWindowProxy* windowProxy(DOMWrapperWorld&);
 
   // Evaluate JavaScript in the main world.
   void executeScriptInMainWorld(
@@ -148,22 +147,20 @@
 
   v8::Isolate* isolate() const { return m_windowProxyManager->isolate(); }
 
-  WindowProxyManager* getWindowProxyManager() const {
+  LocalWindowProxyManager* getWindowProxyManager() const {
     return m_windowProxyManager.get();
   }
 
  private:
   explicit ScriptController(LocalFrame*);
 
-  LocalFrame* frame() const {
-    return toLocalFrame(m_windowProxyManager->frame());
-  }
+  LocalFrame* frame() const { return m_windowProxyManager->frame(); }
 
   v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&,
                                                  AccessControlStatus,
                                                  ExecuteScriptPolicy);
 
-  Member<WindowProxyManager> m_windowProxyManager;
+  Member<LocalWindowProxyManager> m_windowProxyManager;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
index b49db8f4..347c27bc8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -392,9 +392,11 @@
   gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
                                  v8ExtrasMode, &arrayBufferAllocator);
 
+  // NOTE: Some threads (namely utility threads) don't have a scheduler.
   WebScheduler* scheduler = Platform::current()->currentThread()->scheduler();
-  v8::Isolate* isolate =
-      V8PerIsolateData::initialize(scheduler->timerTaskRunner());
+  v8::Isolate* isolate = V8PerIsolateData::initialize(
+      scheduler ? scheduler->timerTaskRunner()
+                : Platform::current()->currentThread()->getWebTaskRunner());
 
   initializeV8Common(isolate);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
index e6e7ce8..a5d8814 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -55,7 +55,7 @@
 
 V8PerIsolateData::V8PerIsolateData(WebTaskRunner* taskRunner)
     : m_isolateHolder(WTF::makeUnique<gin::IsolateHolder>(
-          taskRunner->toSingleThreadTaskRunner())),
+          taskRunner ? taskRunner->toSingleThreadTaskRunner() : nullptr)),
       m_stringCache(WTF::wrapUnique(new StringCache(isolate()))),
       m_hiddenValue(V8HiddenValue::create()),
       m_privateProperty(V8PrivateProperty::create()),
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
index 61471d3..b750f26 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -30,64 +30,18 @@
 
 #include "bindings/core/v8/WindowProxy.h"
 
-#include "bindings/core/v8/ConditionalFeatures.h"
-#include "bindings/core/v8/DOMWrapperWorld.h"
-#include "bindings/core/v8/ScriptController.h"
-#include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
-#include "bindings/core/v8/V8DOMActivityLogger.h"
-#include "bindings/core/v8/V8Document.h"
+#include "bindings/core/v8/V8DOMWrapper.h"
 #include "bindings/core/v8/V8GCForContextDispose.h"
-#include "bindings/core/v8/V8HTMLCollection.h"
-#include "bindings/core/v8/V8HTMLDocument.h"
-#include "bindings/core/v8/V8HiddenValue.h"
-#include "bindings/core/v8/V8Initializer.h"
-#include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8PagePopupControllerBinding.h"
-#include "bindings/core/v8/V8PrivateProperty.h"
-#include "bindings/core/v8/V8Window.h"
-#include "core/frame/LocalFrame.h"
-#include "core/frame/csp/ContentSecurityPolicy.h"
-#include "core/html/DocumentNameCollection.h"
-#include "core/html/HTMLCollection.h"
-#include "core/html/HTMLIFrameElement.h"
-#include "core/inspector/InspectorInstrumentation.h"
-#include "core/inspector/MainThreadDebugger.h"
-#include "core/loader/DocumentLoader.h"
-#include "core/loader/FrameLoader.h"
-#include "core/loader/FrameLoaderClient.h"
-#include "core/origin_trials/OriginTrialContext.h"
-#include "platform/Histogram.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "platform/ScriptForbiddenScope.h"
-#include "platform/heap/Handle.h"
-#include "platform/instrumentation/tracing/TraceEvent.h"
-#include "platform/weborigin/SecurityOrigin.h"
-#include "public/platform/Platform.h"
+#include "core/frame/DOMWindow.h"
+#include "core/frame/Frame.h"
 #include "wtf/Assertions.h"
-#include "wtf/StringExtras.h"
-#include "wtf/text/CString.h"
-#include <algorithm>
 #include <utility>
-#include <v8-debug.h>
 #include <v8.h>
 
 namespace blink {
 
-WindowProxy* WindowProxy::create(v8::Isolate* isolate,
-                                 Frame* frame,
-                                 DOMWrapperWorld& world) {
-  return new WindowProxy(frame, &world, isolate);
-}
-
-WindowProxy::WindowProxy(Frame* frame,
-                         PassRefPtr<DOMWrapperWorld> world,
-                         v8::Isolate* isolate)
-    : m_frame(frame),
-      m_isolate(isolate),
-      m_world(world),
-      m_lifecycle(Lifecycle::ContextUninitialized) {}
-
 WindowProxy::~WindowProxy() {
   // clearForClose() or clearForNavigation() must be invoked before destruction
   // starts.
@@ -98,23 +52,20 @@
   visitor->trace(m_frame);
 }
 
-void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) {
-  if (m_lifecycle != Lifecycle::ContextInitialized)
-    return;
+WindowProxy::WindowProxy(v8::Isolate* isolate,
+                         Frame& frame,
+                         RefPtr<DOMWrapperWorld> world)
+    : m_isolate(isolate),
+      m_frame(frame),
 
-  ScriptState::Scope scope(m_scriptState.get());
-  v8::Local<v8::Context> context = m_scriptState->context();
-  if (m_frame->isLocalFrame()) {
-    LocalFrame* frame = toLocalFrame(m_frame);
-    // The embedder could run arbitrary code in response to the
-    // willReleaseScriptContext callback, so all disposing should happen after
-    // it returns.
-    frame->loader().client()->willReleaseScriptContext(context,
-                                                       m_world->worldId());
-    MainThreadDebugger::instance()->contextWillBeDestroyed(m_scriptState.get());
-  }
+      m_world(std::move(world)),
+      m_lifecycle(Lifecycle::ContextUninitialized) {}
+
+void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) {
+  DCHECK(m_lifecycle == Lifecycle::ContextInitialized);
 
   if (behavior == DetachGlobal) {
+    v8::Local<v8::Context> context = m_scriptState->context();
     // Clean up state on the global proxy, which will be reused.
     if (!m_globalProxy.isEmpty()) {
       // TODO(yukishiino): This DCHECK failed on Canary (M57) and Dev (M56).
@@ -222,116 +173,9 @@
   // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'.
   if (m_lifecycle != Lifecycle::ContextInitialized) {
     initialize();
-    if (m_world->isMainWorld() && m_frame->isLocalFrame())
-      toLocalFrame(m_frame)->loader().dispatchDidClearWindowObjectInMainWorld();
   }
 }
 
-void WindowProxy::initialize() {
-  TRACE_EVENT1("v8", "WindowProxy::initialize", "isMainWindow",
-               m_frame->isMainFrame());
-  SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
-      m_frame->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy"
-                             : "Blink.Binding.InitializeNonMainWindowProxy");
-
-  ScriptForbiddenScope::AllowUserAgentScript allowScript;
-
-  v8::HandleScope handleScope(m_isolate);
-
-  createContext();
-
-  ScriptState::Scope scope(m_scriptState.get());
-  v8::Local<v8::Context> context = m_scriptState->context();
-  if (m_globalProxy.isEmpty()) {
-    m_globalProxy.set(m_isolate, context->Global());
-    CHECK(!m_globalProxy.isEmpty());
-  }
-
-  setupWindowPrototypeChain();
-
-  SecurityOrigin* origin = 0;
-  if (m_world->isMainWorld()) {
-    // ActivityLogger for main world is updated within updateDocument().
-    updateDocument();
-    origin = m_frame->securityContext()->getSecurityOrigin();
-    // FIXME: Can this be removed when CSP moves to browser?
-    ContentSecurityPolicy* csp =
-        m_frame->securityContext()->contentSecurityPolicy();
-    context->AllowCodeGenerationFromStrings(
-        csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
-    context->SetErrorMessageForCodeGenerationFromStrings(
-        v8String(m_isolate, csp->evalDisabledErrorMessage()));
-  } else {
-    updateActivityLogger();
-    origin = m_world->isolatedWorldSecurityOrigin();
-    setSecurityToken(origin);
-  }
-
-  if (m_frame->isLocalFrame()) {
-    LocalFrame* frame = toLocalFrame(m_frame);
-    MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame,
-                                                   origin);
-    frame->loader().client()->didCreateScriptContext(
-        context, m_world->extensionGroup(), m_world->worldId());
-  }
-  // If conditional features for window have been queued before the V8 context
-  // was ready, then inject them into the context now
-  if (m_world->isMainWorld()) {
-    installPendingConditionalFeaturesOnWindow(m_scriptState.get());
-  }
-}
-
-void WindowProxy::createContext() {
-  // Create a new v8::Context with the window object as the global object
-  // (aka the inner global).  Reuse the global proxy object (aka the outer
-  // global) if it already exists.  See the comments in
-  // setupWindowPrototypeChain for the structure of the prototype chain of
-  // the global object.
-  v8::Local<v8::ObjectTemplate> globalTemplate =
-      V8Window::domTemplate(m_isolate, *m_world)->InstanceTemplate();
-  CHECK(!globalTemplate.IsEmpty());
-
-  // FIXME: It's not clear what the right thing to do for remote frames is.
-  // The extensions registered don't generally seem to make sense for remote
-  // frames, so skip it for now.
-  Vector<const char*> extensionNames;
-  if (m_frame->isLocalFrame()) {
-    LocalFrame* frame = toLocalFrame(m_frame);
-    // Dynamically tell v8 about our extensions now.
-    const V8Extensions& extensions = ScriptController::registeredExtensions();
-    extensionNames.reserveInitialCapacity(extensions.size());
-    int extensionGroup = m_world->extensionGroup();
-    int worldId = m_world->worldId();
-    for (const auto* extension : extensions) {
-      if (!frame->loader().client()->allowScriptExtension(
-              extension->name(), extensionGroup, worldId))
-        continue;
-
-      extensionNames.push_back(extension->name());
-    }
-  }
-  v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(),
-                                                    extensionNames.data());
-
-  v8::Local<v8::Context> context;
-  {
-    V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(
-        V8PerIsolateData::from(m_isolate));
-    context =
-        v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate,
-                         m_globalProxy.newLocal(m_isolate));
-  }
-  CHECK(!context.IsEmpty());
-
-  m_scriptState = ScriptState::create(context, m_world);
-
-  // TODO(haraken): Currently we cannot enable the following DCHECK because
-  // an already detached window proxy can be re-initialized. This is wrong.
-  // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized);
-  m_lifecycle = Lifecycle::ContextInitialized;
-  DCHECK(m_scriptState->contextIsValid());
-}
-
 void WindowProxy::setupWindowPrototypeChain() {
   // Associate the window wrapper object and its prototype chain with the
   // corresponding native DOMWindow object.
@@ -399,198 +243,4 @@
                                                            windowWrapper);
 }
 
-void WindowProxy::updateDocumentProperty() {
-  DCHECK(m_world->isMainWorld());
-
-  if (m_frame->isRemoteFrame())
-    return;
-
-  ScriptState::Scope scope(m_scriptState.get());
-  v8::Local<v8::Context> context = m_scriptState->context();
-  LocalFrame* frame = toLocalFrame(m_frame);
-  v8::Local<v8::Value> documentWrapper =
-      ToV8(frame->document(), context->Global(), m_isolate);
-  DCHECK(documentWrapper->IsObject());
-  // Update the cached accessor for window.document.
-  CHECK(V8PrivateProperty::getWindowDocumentCachedAccessor(m_isolate).set(
-      context, context->Global(), documentWrapper));
-}
-
-void WindowProxy::updateActivityLogger() {
-  m_scriptState->perContextData()->setActivityLogger(
-      V8DOMActivityLogger::activityLogger(
-          m_world->worldId(),
-          m_frame->isLocalFrame() && toLocalFrame(m_frame)->document()
-              ? toLocalFrame(m_frame)->document()->baseURI()
-              : KURL()));
-}
-
-void WindowProxy::setSecurityToken(SecurityOrigin* origin) {
-  // If two tokens are equal, then the SecurityOrigins canAccess each other.
-  // If two tokens are not equal, then we have to call canAccess.
-  // Note: we can't use the HTTPOrigin if it was set from the DOM.
-  String token;
-  // There are two situations where v8 needs to do a full canAccess check,
-  // so set an empty security token instead:
-  // - document.domain was modified
-  // - the frame is remote
-  bool delaySet = m_frame->isRemoteFrame() ||
-                  (m_world->isMainWorld() && origin->domainWasSetInDOM());
-  if (origin && !delaySet)
-    token = origin->toString();
-
-  // An empty or "null" token means we always have to call
-  // canAccess. The toString method on securityOrigins returns the
-  // string "null" for empty security origins and for security
-  // origins that should only allow access to themselves. In this
-  // case, we use the global object as the security token to avoid
-  // calling canAccess when a script accesses its own objects.
-  v8::HandleScope handleScope(m_isolate);
-  v8::Local<v8::Context> context = m_scriptState->context();
-  if (token.isEmpty() || token == "null") {
-    context->UseDefaultSecurityToken();
-    return;
-  }
-
-  if (m_world->isIsolatedWorld()) {
-    SecurityOrigin* frameSecurityOrigin =
-        m_frame->securityContext()->getSecurityOrigin();
-    String frameSecurityToken = frameSecurityOrigin->toString();
-    // We need to check the return value of domainWasSetInDOM() on the
-    // frame's SecurityOrigin because, if that's the case, only
-    // SecurityOrigin::m_domain would have been modified.
-    // m_domain is not used by SecurityOrigin::toString(), so we would end
-    // up generating the same token that was already set.
-    if (frameSecurityOrigin->domainWasSetInDOM() ||
-        frameSecurityToken.isEmpty() || frameSecurityToken == "null") {
-      context->UseDefaultSecurityToken();
-      return;
-    }
-    token = frameSecurityToken + token;
-  }
-
-  // NOTE: V8 does identity comparison in fast path, must use a symbol
-  // as the security token.
-  context->SetSecurityToken(v8AtomicString(m_isolate, token));
-}
-
-void WindowProxy::updateDocument() {
-  DCHECK(m_world->isMainWorld());
-  // For an uninitialized main window proxy, there's nothing we need
-  // to update. The update is done when the window proxy gets initialized later.
-  if (m_lifecycle == Lifecycle::ContextUninitialized)
-    return;
-  // TODO(yukishiino): Is it okay to not update document when the context
-  // is detached? It's not trivial to fix this because udpateDocumentProperty
-  // requires a not-yet-detached context to instantiate a document wrapper.
-  if (m_lifecycle == Lifecycle::ContextDetached)
-    return;
-
-  updateActivityLogger();
-  updateDocumentProperty();
-  updateSecurityOrigin(m_frame->securityContext()->getSecurityOrigin());
-}
-
-static v8::Local<v8::Value> getNamedProperty(
-    HTMLDocument* htmlDocument,
-    const AtomicString& key,
-    v8::Local<v8::Object> creationContext,
-    v8::Isolate* isolate) {
-  if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key))
-    return v8Undefined();
-
-  DocumentNameCollection* items = htmlDocument->documentNamedItems(key);
-  if (items->isEmpty())
-    return v8Undefined();
-
-  if (items->hasExactlyOneItem()) {
-    HTMLElement* element = items->item(0);
-    ASSERT(element);
-    Frame* frame = isHTMLIFrameElement(*element)
-                       ? toHTMLIFrameElement(*element).contentFrame()
-                       : 0;
-    if (frame)
-      return ToV8(frame->domWindow(), creationContext, isolate);
-    return ToV8(element, creationContext, isolate);
-  }
-  return ToV8(items, creationContext, isolate);
-}
-
-static void getter(v8::Local<v8::Name> property,
-                   const v8::PropertyCallbackInfo<v8::Value>& info) {
-  if (!property->IsString())
-    return;
-  // FIXME: Consider passing StringImpl directly.
-  AtomicString name = toCoreAtomicString(property.As<v8::String>());
-  HTMLDocument* htmlDocument = V8HTMLDocument::toImpl(info.Holder());
-  ASSERT(htmlDocument);
-  v8::Local<v8::Value> result =
-      getNamedProperty(htmlDocument, name, info.Holder(), info.GetIsolate());
-  if (!result.IsEmpty()) {
-    v8SetReturnValue(info, result);
-    return;
-  }
-  v8::Local<v8::Value> value;
-  if (info.Holder()
-          ->GetRealNamedPropertyInPrototypeChain(
-              info.GetIsolate()->GetCurrentContext(), property.As<v8::String>())
-          .ToLocal(&value))
-    v8SetReturnValue(info, value);
-}
-
-void WindowProxy::namedItemAdded(HTMLDocument* document,
-                                 const AtomicString& name) {
-  DCHECK(m_world->isMainWorld());
-
-  // Context must be initialized before this point.
-  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
-  // TODO(yukishiino): Is it okay to not update named properties
-  // after the context gets detached?
-  if (m_lifecycle == Lifecycle::ContextDetached)
-    return;
-
-  ScriptState::Scope scope(m_scriptState.get());
-  v8::Local<v8::Object> documentWrapper =
-      m_world->domDataStore().get(document, m_isolate);
-  // TODO(yukishiino,peria): We should check if the own property with the same
-  // name already exists or not, and if it exists, we shouldn't define a new
-  // accessor property (it fails).
-  documentWrapper->SetAccessor(m_isolate->GetCurrentContext(),
-                               v8String(m_isolate, name), getter);
-}
-
-void WindowProxy::namedItemRemoved(HTMLDocument* document,
-                                   const AtomicString& name) {
-  DCHECK(m_world->isMainWorld());
-
-  // Context must be initialized before this point.
-  DCHECK(m_lifecycle >= Lifecycle::ContextInitialized);
-  // TODO(yukishiino): Is it okay to not update named properties
-  // after the context gets detached?
-  if (m_lifecycle == Lifecycle::ContextDetached)
-    return;
-
-  if (document->hasNamedItem(name) || document->hasExtraNamedItem(name))
-    return;
-  ScriptState::Scope scope(m_scriptState.get());
-  v8::Local<v8::Object> documentWrapper =
-      m_world->domDataStore().get(document, m_isolate);
-  documentWrapper
-      ->Delete(m_isolate->GetCurrentContext(), v8String(m_isolate, name))
-      .ToChecked();
-}
-
-void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin) {
-  // For an uninitialized main window proxy, there's nothing we need
-  // to update. The update is done when the window proxy gets initialized later.
-  if (m_lifecycle == Lifecycle::ContextUninitialized)
-    return;
-  // TODO(yukishiino): Is it okay to not update security origin when the context
-  // is detached?
-  if (m_lifecycle == Lifecycle::ContextDetached)
-    return;
-
-  setSecurityToken(origin);
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
index 9f074f2b..9089f01 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.h
@@ -35,55 +35,43 @@
 #include "bindings/core/v8/ScopedPersistent.h"
 #include "bindings/core/v8/ScriptState.h"
 #include "platform/heap/Handle.h"
-#include "platform/weborigin/SecurityOrigin.h"
-#include "wtf/HashMap.h"
-#include "wtf/PassRefPtr.h"
 #include "wtf/RefPtr.h"
-#include "wtf/text/AtomicString.h"
 #include <v8.h>
 
 namespace blink {
 
 class Frame;
-class HTMLDocument;
-class SecurityOrigin;
+class ScriptController;
 
 // WindowProxy represents all the per-global object state for a Frame that
 // persist between navigations.
-class WindowProxy final : public GarbageCollectedFinalized<WindowProxy> {
+class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
  public:
-  static WindowProxy* create(v8::Isolate*, Frame*, DOMWrapperWorld&);
+  virtual ~WindowProxy();
 
-  ~WindowProxy();
   DECLARE_TRACE();
 
   v8::Local<v8::Context> contextIfInitialized() const {
     return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>();
   }
-  ScriptState* getScriptState() const { return m_scriptState.get(); }
-
-  // Update document object of the frame.
-  void updateDocument();
-
-  void namedItemAdded(HTMLDocument*, const AtomicString&);
-  void namedItemRemoved(HTMLDocument*, const AtomicString&);
-
-  // Update the security origin of a document
-  // (e.g., after setting docoument.domain).
-  void updateSecurityOrigin(SecurityOrigin*);
-
   void initializeIfNeeded();
 
-  void clearForNavigation();
   void clearForClose();
+  void clearForNavigation();
 
   v8::Local<v8::Object> globalIfNotDetached();
   v8::Local<v8::Object> releaseGlobal();
   void setGlobal(v8::Local<v8::Object>);
 
+  // TODO(dcheng): Temporarily exposed to avoid include cycles. Remove the need
+  // for this and remove this getter.
   DOMWrapperWorld& world() { return *m_world; }
 
- private:
+ protected:
+  // TODO(dcheng): Remove this friend declaration once LocalWindowProxyManager
+  // and ScriptController are merged.
+  friend class ScriptController;
+
   // A valid transition is from ContextUninitialized to ContextInitialized,
   // and then ContextDetached. Other transitions are forbidden.
   enum class Lifecycle {
@@ -92,36 +80,31 @@
     ContextDetached,
   };
 
-  WindowProxy(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*);
-  void initialize();
+  WindowProxy(v8::Isolate*, Frame&, RefPtr<DOMWrapperWorld>);
+
+  virtual void initialize() = 0;
 
   enum GlobalDetachmentBehavior { DoNotDetachGlobal, DetachGlobal };
-  void disposeContext(GlobalDetachmentBehavior);
-
-  void setSecurityToken(SecurityOrigin*);
-
-  // The JavaScript wrapper for the document object is cached on the global
-  // object for fast access. UpdateDocumentProperty sets the wrapper
-  // for the current document on the global object.
-  void updateDocumentProperty();
-
-  // Updates Activity Logger for the current context.
-  void updateActivityLogger();
-
-  // Creates a new v8::Context with the window wrapper object as the global
-  // object (aka the inner global).  Note that the window wrapper and its
-  // prototype chain do not get fully initialized yet, e.g. the window
-  // wrapper is not yet associated with the native DOMWindow object.
-  void createContext();
+  virtual void disposeContext(GlobalDetachmentBehavior);
 
   // Associates the window wrapper and its prototype chain with the native
   // DOMWindow object.  Also does some more Window-specific initialization.
   void setupWindowPrototypeChain();
 
-  Member<Frame> m_frame;
-  v8::Isolate* m_isolate;
+  v8::Isolate* isolate() const { return m_isolate; }
+  Frame* frame() const { return m_frame.get(); }
+  ScriptState* getScriptState() const { return m_scriptState.get(); }
+
+ private:
+  v8::Isolate* const m_isolate;
+  const Member<Frame> m_frame;
+
+ protected:
+  // TODO(dcheng): Move this to LocalWindowProxy once RemoteWindowProxy uses
+  // remote contexts.
   RefPtr<ScriptState> m_scriptState;
-  RefPtr<DOMWrapperWorld> m_world;
+  // TODO(dcheng): Consider making these private and using getters.
+  const RefPtr<DOMWrapperWorld> m_world;
   ScopedPersistent<v8::Object> m_globalProxy;
   Lifecycle m_lifecycle;
 };
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
index d73a8213..8e7a752 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.cpp
@@ -5,22 +5,31 @@
 #include "bindings/core/v8/WindowProxyManager.h"
 
 #include "bindings/core/v8/DOMWrapperWorld.h"
-#include "bindings/core/v8/WindowProxy.h"
-#include "core/frame/Frame.h"
 
 namespace blink {
 
-WindowProxyManager* WindowProxyManager::create(Frame& frame) {
-  return new WindowProxyManager(frame);
+namespace {
+
+WindowProxy* createWindowProxyForFrame(v8::Isolate* isolate,
+                                       Frame& frame,
+
+                                       RefPtr<DOMWrapperWorld> world) {
+  if (frame.isLocalFrame()) {
+    return LocalWindowProxy::create(isolate, toLocalFrame(frame),
+                                    std::move(world));
+  }
+  return RemoteWindowProxy::create(isolate, toRemoteFrame(frame),
+                                   std::move(world));
+}
 }
 
-DEFINE_TRACE(WindowProxyManager) {
+DEFINE_TRACE(WindowProxyManagerBase) {
   visitor->trace(m_frame);
   visitor->trace(m_windowProxy);
   visitor->trace(m_isolatedWorlds);
 }
 
-WindowProxy* WindowProxyManager::windowProxy(DOMWrapperWorld& world) {
+WindowProxy* WindowProxyManagerBase::windowProxy(DOMWrapperWorld& world) {
   WindowProxy* windowProxy = nullptr;
   if (world.isMainWorld()) {
     windowProxy = m_windowProxy.get();
@@ -29,36 +38,26 @@
     if (iter != m_isolatedWorlds.end()) {
       windowProxy = iter->value.get();
     } else {
-      windowProxy = WindowProxy::create(m_isolate, m_frame, world);
+      windowProxy = createWindowProxyForFrame(m_isolate, *m_frame, &world);
       m_isolatedWorlds.set(world.worldId(), windowProxy);
     }
   }
   return windowProxy;
 }
 
-void WindowProxyManager::clearForClose() {
+void WindowProxyManagerBase::clearForClose() {
   m_windowProxy->clearForClose();
   for (auto& entry : m_isolatedWorlds)
     entry.value->clearForClose();
 }
 
-void WindowProxyManager::clearForNavigation() {
+void WindowProxyManagerBase::clearForNavigation() {
   m_windowProxy->clearForNavigation();
   for (auto& entry : m_isolatedWorlds)
     entry.value->clearForNavigation();
 }
 
-void WindowProxyManager::updateSecurityOrigin(SecurityOrigin* securityOrigin) {
-  m_windowProxy->updateSecurityOrigin(securityOrigin);
-  for (auto& entry : m_isolatedWorlds) {
-    WindowProxy* isolatedWindowProxy = entry.value.get();
-    SecurityOrigin* isolatedSecurityOrigin =
-        isolatedWindowProxy->world().isolatedWorldSecurityOrigin();
-    isolatedWindowProxy->updateSecurityOrigin(isolatedSecurityOrigin);
-  }
-}
-
-void WindowProxyManager::releaseGlobals(
+void WindowProxyManagerBase::releaseGlobals(
     HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>& map) {
   map.add(&m_windowProxy->world(), m_windowProxy->releaseGlobal());
   for (auto& entry : m_isolatedWorlds)
@@ -66,17 +65,30 @@
             windowProxy(entry.value->world())->releaseGlobal());
 }
 
-void WindowProxyManager::setGlobals(
+void WindowProxyManagerBase::setGlobals(
     const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>& map) {
   for (auto& entry : map)
     windowProxy(*entry.key)->setGlobal(entry.value);
 }
 
-WindowProxyManager::WindowProxyManager(Frame& frame)
-    : m_frame(&frame),
-      m_isolate(v8::Isolate::GetCurrent()),
-      m_windowProxy(WindowProxy::create(m_isolate,
-                                        &frame,
-                                        DOMWrapperWorld::mainWorld())) {}
+WindowProxyManagerBase::WindowProxyManagerBase(Frame& frame)
+    : m_isolate(v8::Isolate::GetCurrent()),
+      m_frame(&frame),
+      m_windowProxy(createWindowProxyForFrame(m_isolate,
+                                              frame,
+                                              &DOMWrapperWorld::mainWorld())) {}
+
+void LocalWindowProxyManager::updateSecurityOrigin(
+    SecurityOrigin* securityOrigin) {
+  static_cast<LocalWindowProxy*>(mainWorldProxy())
+      ->updateSecurityOrigin(securityOrigin);
+  for (auto& entry : isolatedWorlds()) {
+    auto* isolatedWindowProxy =
+        static_cast<LocalWindowProxy*>(entry.value.get());
+    SecurityOrigin* isolatedSecurityOrigin =
+        isolatedWindowProxy->world().isolatedWorldSecurityOrigin();
+    isolatedWindowProxy->updateSecurityOrigin(isolatedSecurityOrigin);
+  }
+}
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h
index e785aff..a70c384d 100644
--- a/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h
+++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h
@@ -5,52 +5,101 @@
 #ifndef WindowProxyManager_h
 #define WindowProxyManager_h
 
+#include "bindings/core/v8/LocalWindowProxy.h"
+#include "bindings/core/v8/RemoteWindowProxy.h"
 #include "core/CoreExport.h"
+#include "core/frame/LocalFrame.h"
+#include "core/frame/RemoteFrame.h"
 #include "platform/heap/Handle.h"
-#include "wtf/Vector.h"
 #include <utility>
 #include <v8.h>
 
 namespace blink {
 
 class DOMWrapperWorld;
-class Frame;
 class SecurityOrigin;
-class WindowProxy;
+class ScriptController;
 
-class CORE_EXPORT WindowProxyManager final
-    : public GarbageCollected<WindowProxyManager> {
+class WindowProxyManagerBase : public GarbageCollected<WindowProxyManagerBase> {
  public:
-  static WindowProxyManager* create(Frame&);
-
   DECLARE_TRACE();
 
-  Frame* frame() const { return m_frame.get(); }
   v8::Isolate* isolate() const { return m_isolate; }
-  WindowProxy* mainWorldProxy() const { return m_windowProxy.get(); }
-
-  WindowProxy* windowProxy(DOMWrapperWorld&);
 
   void clearForClose();
-  void clearForNavigation();
+  void CORE_EXPORT clearForNavigation();
+
+  void CORE_EXPORT
+  releaseGlobals(HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&);
+  void CORE_EXPORT
+  setGlobals(const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&);
+
+ protected:
+  using IsolatedWorldMap = HeapHashMap<int, Member<WindowProxy>>;
+
+  explicit WindowProxyManagerBase(Frame&);
+
+  Frame* frame() const { return m_frame; }
+  WindowProxy* mainWorldProxy() const { return m_windowProxy.get(); }
+  WindowProxy* windowProxy(DOMWrapperWorld&);
+
+  IsolatedWorldMap& isolatedWorlds() { return m_isolatedWorlds; }
+
+ private:
+  v8::Isolate* const m_isolate;
+  const Member<Frame> m_frame;
+  const Member<WindowProxy> m_windowProxy;
+  IsolatedWorldMap m_isolatedWorlds;
+};
+
+template <typename FrameType, typename ProxyType>
+class WindowProxyManagerImplHelper : public WindowProxyManagerBase {
+ private:
+  using Base = WindowProxyManagerBase;
+
+ public:
+  FrameType* frame() const { return static_cast<FrameType*>(Base::frame()); }
+  ProxyType* mainWorldProxy() const {
+    return static_cast<ProxyType*>(Base::mainWorldProxy());
+  }
+  ProxyType* windowProxy(DOMWrapperWorld& world) {
+    return static_cast<ProxyType*>(Base::windowProxy(world));
+  }
+
+ protected:
+  explicit WindowProxyManagerImplHelper(Frame& frame)
+      : WindowProxyManagerBase(frame) {}
+};
+
+class LocalWindowProxyManager
+    : public WindowProxyManagerImplHelper<LocalFrame, LocalWindowProxy> {
+ public:
+  static LocalWindowProxyManager* create(LocalFrame& frame) {
+    return new LocalWindowProxyManager(frame);
+  }
 
   // Sets the given security origin to the main world's context.  Also updates
   // the security origin of the context for each isolated world.
   void updateSecurityOrigin(SecurityOrigin*);
 
-  void releaseGlobals(HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&);
-  void setGlobals(const HashMap<DOMWrapperWorld*, v8::Local<v8::Object>>&);
+ private:
+  // TODO(dcheng): Merge LocalWindowProxyManager and ScriptController?
+  friend class ScriptController;
+
+  explicit LocalWindowProxyManager(LocalFrame& frame)
+      : WindowProxyManagerImplHelper<LocalFrame, LocalWindowProxy>(frame) {}
+};
+
+class RemoteWindowProxyManager
+    : public WindowProxyManagerImplHelper<RemoteFrame, RemoteWindowProxy> {
+ public:
+  static RemoteWindowProxyManager* create(RemoteFrame& frame) {
+    return new RemoteWindowProxyManager(frame);
+  }
 
  private:
-  typedef HeapHashMap<int, Member<WindowProxy>> IsolatedWorldMap;
-
-  explicit WindowProxyManager(Frame&);
-
-  Member<Frame> m_frame;
-  v8::Isolate* const m_isolate;
-
-  const Member<WindowProxy> m_windowProxy;
-  IsolatedWorldMap m_isolatedWorlds;
+  explicit RemoteWindowProxyManager(RemoteFrame& frame)
+      : WindowProxyManagerImplHelper<RemoteFrame, RemoteWindowProxy>(frame) {}
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index c8aeceb6..c72c8e2 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -254,6 +254,10 @@
     cpp_class_name_or_partial = cpp_name_or_partial(interface)
     v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface)
 
+    # TODO(peria): Generate the target list from 'Window' and 'HTMLDocument'.
+    needs_runtime_enabled_installer = v8_class_name in [
+        'V8Window', 'V8HTMLDocument', 'V8Document', 'V8Node', 'V8EventTarget']
+
     context = {
         'cpp_class': cpp_class_name,
         'cpp_class_or_partial': cpp_class_name_or_partial,
@@ -279,6 +283,7 @@
         'is_typed_array_type': is_typed_array_type,
         'lifetime': 'Dependent' if (has_visit_dom_wrapper or is_dependent_lifetime) else 'Independent',
         'measure_as': v8_utilities.measure_as(interface, None),  # [MeasureAs]
+        'needs_runtime_enabled_installer': needs_runtime_enabled_installer,
         'origin_trial_enabled_function': v8_utilities.origin_trial_enabled_function_name(interface),
         'parent_interface': parent_interface,
         'pass_cpp_type': cpp_name(interface) + '*',
diff --git a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
index 5fd5568..8f6e6d6 100644
--- a/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface.h.tmpl
@@ -150,6 +150,15 @@
   {% endfor %}
   {% endif %}
 
+  {% if needs_runtime_enabled_installer %}
+  {{exported}}static void installRuntimeEnabledFeatures(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Object> instance,
+      v8::Local<v8::Object> prototype,
+      v8::Local<v8::Function> interface);
+  {% endif %}
+
   {% for feature in origin_trial_features %}
 
   static void install{{feature.name}}(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface);
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
index 9c1cabcd..4f5907c 100644
--- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -527,6 +527,71 @@
 {% endif %}{# not is_array_buffer_or_view #}
 {% endblock %}
 {##############################################################################}
+{% block install_runtime_enabled %}
+{% if needs_runtime_enabled_installer %}
+{% from 'attributes.cpp.tmpl' import attribute_configuration with context %}
+{% from 'methods.cpp.tmpl' import install_custom_signature with context %}
+void {{v8_class_or_partial}}::installRuntimeEnabledFeatures(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface) {
+  {% if runtime_enabled_feature_name %}
+#error "We don't expect a runtime enabled interface {{v8_class_or_partial}} to have installRuntimeEnabledFeatures()."
+  {% endif %}
+
+  {% if is_partial %}
+  {{v8_class}}::installRuntimeEnabledFeatures(isolate, world, instance, prototype, interface);
+  {% endif %}
+
+  v8::Local<v8::FunctionTemplate> interfaceTemplate = {{v8_class}}::wrapperTypeInfo.domTemplate(isolate, world);
+  v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
+  ALLOW_UNUSED_LOCAL(signature);
+
+  {# TODO(peria): Generate code to install constants. It depends on runtime_enabled_feaure of this interface. #}
+
+  {% for feature_name, attrs in runtime_enabled_attributes | groupby('runtime_enabled_feature_name') %}
+  {% filter runtime_enabled(feature_name) %}
+  {% for attribute in attrs | unique_by('name') | sort %}
+  {% if attribute.is_data_type_property %}
+  const V8DOMConfiguration::AttributeConfiguration attribute{{attribute.name}}Configuration = {{attribute_configuration(attribute)}};
+  V8DOMConfiguration::installAttribute(isolate, world, instance, prototype, attribute{{attribute.name}}Configuration);
+  {% else %}
+  const V8DOMConfiguration::AccessorConfiguration accessor{{attribute.name}}Configuration = {{attribute_configuration(attribute)}};
+  V8DOMConfiguration::installAccessor(isolate, world, instance, prototype, interface, signature, accessor{{attribute.name}}Configuration);
+  {% endif %}
+  {% endfor %}
+  {% endfilter %}
+  {% endfor %}
+
+  {% if iterator_method and iterator_method.runtime_enabled_feature_name %}
+  {% filter exposed(iterator_method.exposed_test) %}
+  {% filter runtime_enabled(iterator_method.runtime_enabled_feature_name) %}
+  // Runtime enabled iterator (@@iterator)
+#error "{{v8_class_or_partial}} should not have runtime enabled iterators."
+  {% endfilter %}
+  {% endfilter %}
+  {% endif %}
+
+  {% if methods | custom_registration(is_partial) %}
+  {% for method in methods | custom_registration(is_partial) %}
+  {% filter exposed(method.overloads.exposed_test_all
+                    if method.overloads else method.exposed_test) %}
+  {% set feature_name = (method.overloads.runtime_enabled_all
+                         if method.overloads else method.runtime_enabled_feature_name) %}
+  {% if feature_name %}
+  {% filter runtime_enabled(feature_name) %}
+  {% if method.is_cross_origin %}
+#error "{{v8_class_or_partial}} should not have runtime enabled and cross origin methods."
+  {% else %}
+  {{install_custom_signature(method, 'instance', 'prototype', 'interface', 'signature') | indent(2)}}
+  {% endif %}
+  {% endfilter %}
+  {% endif %}
+  {% endfilter %}
+  {% endfor %}
+  {% endif %}
+}
+
+{% endif %}{# needs_runtime_enabled_installer #}
+{% endblock %}
+{##############################################################################}
 {% block origin_trials %}
 {% from 'attributes.cpp.tmpl' import attribute_configuration with context %}
 {% from 'constants.cpp.tmpl' import constant_configuration with context %}
diff --git a/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl b/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl
index 1359c46..0af2797 100644
--- a/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/partial_interface.h.tmpl
@@ -42,6 +42,15 @@
   {% endif %}
   {% endfor %}
 
+  {% if needs_runtime_enabled_installer %}
+  static void installRuntimeEnabledFeatures(
+      v8::Isolate* isolate,
+      const DOMWrapperWorld& world,
+      v8::Local<v8::Object> instance,
+      v8::Local<v8::Object> prototype,
+      v8::Local<v8::Function> interface);
+  {% endif %}
+
  private:
   static void install{{v8_class}}Template(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interfaceTemplate);
 };
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index 0a8ab8ee..8dfad6f 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -191,6 +191,7 @@
                                  "frame/ImageBitmap.idl",
                                  "frame/Location.idl",
                                  "frame/VisualViewport.idl",
+                                 "html/Float32ImageData.idl",
                                  "html/FormData.idl",
                                  "html/HTMLAllCollection.idl",
                                  "html/HTMLAnchorElement.idl",
diff --git a/third_party/WebKit/Source/core/dom/DOMTypedArray.h b/third_party/WebKit/Source/core/dom/DOMTypedArray.h
index 292003a..f4b6893 100644
--- a/third_party/WebKit/Source/core/dom/DOMTypedArray.h
+++ b/third_party/WebKit/Source/core/dom/DOMTypedArray.h
@@ -54,7 +54,8 @@
   }
 
   static ThisType* createOrNull(unsigned length) {
-    RefPtr<WTF::ArrayBuffer> buffer = WTF::ArrayBuffer::createOrNull(length, 1);
+    RefPtr<WTF::ArrayBuffer> buffer =
+        WTF::ArrayBuffer::createOrNull(length, sizeof(ThisType));
     return buffer ? create(buffer.release(), 0, length) : nullptr;
   }
 
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h
index 5f0aec9..ba5e83e 100644
--- a/third_party/WebKit/Source/core/frame/Frame.h
+++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -54,7 +54,7 @@
 class SecurityContext;
 class Settings;
 class WindowProxy;
-class WindowProxyManager;
+class WindowProxyManagerBase;
 struct FrameLoadRequest;
 
 enum class FrameDetachType { Remove, Swap };
@@ -143,7 +143,7 @@
   void setIsLoading(bool isLoading) { m_isLoading = isLoading; }
   bool isLoading() const { return m_isLoading; }
 
-  virtual WindowProxyManager* getWindowProxyManager() const = 0;
+  virtual WindowProxyManagerBase* getWindowProxyManager() const = 0;
 
   virtual void didChangeVisibilityState();
 
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index f6ba656..858f4d3 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -4,6 +4,7 @@
 
 #include "core/frame/ImageBitmap.h"
 
+#include "core/html/Float32ImageData.h"
 #include "core/html/HTMLCanvasElement.h"
 #include "core/html/HTMLVideoElement.h"
 #include "core/html/ImageData.h"
@@ -757,6 +758,8 @@
                                  resizedPixels.release().leakRef());
 }
 
+// TODO(zakerinasab): Fix this and the constructor from Float32ImageData
+// when the CL for Float32ImageData landed.
 ImageBitmap::ImageBitmap(ImageData* data,
                          Optional<IntRect> cropRect,
                          const ImageBitmapOptions& options) {
@@ -905,6 +908,10 @@
   m_image = StaticBitmapImage::create(std::move(skImage));
 }
 
+ImageBitmap::ImageBitmap(Float32ImageData* data,
+                         Optional<IntRect> cropRect,
+                         const ImageBitmapOptions& options) {}
+
 ImageBitmap::ImageBitmap(ImageBitmap* bitmap,
                          Optional<IntRect> cropRect,
                          const ImageBitmapOptions& options) {
@@ -989,6 +996,12 @@
   return new ImageBitmap(data, cropRect, options);
 }
 
+ImageBitmap* ImageBitmap::create(Float32ImageData* data,
+                                 Optional<IntRect> cropRect,
+                                 const ImageBitmapOptions& options) {
+  return new ImageBitmap(data, cropRect, options);
+}
+
 ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap,
                                  Optional<IntRect> cropRect,
                                  const ImageBitmapOptions& options) {
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h
index 99fd4d5..eab4930 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -21,6 +21,7 @@
 #include <memory>
 
 namespace blink {
+class Float32ImageData;
 class HTMLCanvasElement;
 class HTMLVideoElement;
 class ImageData;
@@ -65,6 +66,9 @@
   static ImageBitmap* create(ImageData*,
                              Optional<IntRect>,
                              const ImageBitmapOptions& = ImageBitmapOptions());
+  static ImageBitmap* create(Float32ImageData*,
+                             Optional<IntRect>,
+                             const ImageBitmapOptions& = ImageBitmapOptions());
   static ImageBitmap* create(ImageBitmap*,
                              Optional<IntRect>,
                              const ImageBitmapOptions& = ImageBitmapOptions());
@@ -150,6 +154,7 @@
   ImageBitmap(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(OffscreenCanvas*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(ImageData*, Optional<IntRect>, const ImageBitmapOptions&);
+  ImageBitmap(Float32ImageData*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions&);
   ImageBitmap(PassRefPtr<StaticBitmapImage>);
   ImageBitmap(PassRefPtr<StaticBitmapImage>,
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index f866542c..1d711cb 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -494,7 +494,7 @@
       ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message));
 }
 
-WindowProxyManager* LocalFrame::getWindowProxyManager() const {
+WindowProxyManagerBase* LocalFrame::getWindowProxyManager() const {
   return m_script->getWindowProxyManager();
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index da62177a..2b8671e 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -236,7 +236,7 @@
              InterfaceRegistry*);
 
   // Internal Frame helper overrides:
-  WindowProxyManager* getWindowProxyManager() const override;
+  WindowProxyManagerBase* getWindowProxyManager() const override;
   // Intentionally private to prevent redundant checks when the type is
   // already LocalFrame.
   bool isLocalFrame() const override { return true; }
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
index 558aed7e..c9c83df3 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -30,7 +30,7 @@
                                 FrameOwner* owner)
     : Frame(client, host, owner),
       m_securityContext(RemoteSecurityContext::create()),
-      m_windowProxyManager(WindowProxyManager::create(*this)) {
+      m_windowProxyManager(RemoteWindowProxyManager::create(*this)) {
   m_domWindow = RemoteDOMWindow::create(*this);
 }
 
@@ -187,6 +187,10 @@
   client()->advanceFocus(type, source);
 }
 
+WindowProxyManagerBase* RemoteFrame::getWindowProxyManager() const {
+  return m_windowProxyManager.get();
+}
+
 void RemoteFrame::detachChildren() {
   using FrameVector = HeapVector<Member<Frame>>;
   FrameVector childrenToDetach;
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h
index 777c92d9..412ec72e8 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrame.h
+++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -17,8 +17,8 @@
 class LocalFrame;
 class RemoteFrameClient;
 class RemoteFrameView;
+class RemoteWindowProxyManager;
 class WebLayer;
-class WindowProxyManager;
 struct FrameLoadRequest;
 
 class CORE_EXPORT RemoteFrame final : public Frame {
@@ -68,9 +68,8 @@
   RemoteFrame(RemoteFrameClient*, FrameHost*, FrameOwner*);
 
   // Internal Frame helper overrides:
-  WindowProxyManager* getWindowProxyManager() const override {
-    return m_windowProxyManager.get();
-  }
+  WindowProxyManagerBase* getWindowProxyManager() const override;
+
   // Intentionally private to prevent redundant checks when the type is
   // already RemoteFrame.
   bool isLocalFrame() const override { return false; }
@@ -80,7 +79,7 @@
 
   Member<RemoteFrameView> m_view;
   Member<RemoteSecurityContext> m_securityContext;
-  Member<WindowProxyManager> m_windowProxyManager;
+  Member<RemoteWindowProxyManager> m_windowProxyManager;
   WebLayer* m_webLayer = nullptr;
 };
 
diff --git a/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp b/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp
index e8104123..9e35cec 100644
--- a/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp
+++ b/third_party/WebKit/Source/core/frame/ScreenOrientationController.cpp
@@ -6,6 +6,9 @@
 
 namespace blink {
 
+ScreenOrientationController::ScreenOrientationController(LocalFrame& frame)
+    : Supplement<LocalFrame>(frame) {}
+
 // static
 ScreenOrientationController* ScreenOrientationController::from(
     LocalFrame& frame) {
diff --git a/third_party/WebKit/Source/core/frame/ScreenOrientationController.h b/third_party/WebKit/Source/core/frame/ScreenOrientationController.h
index 7c80e30..fbe0e274 100644
--- a/third_party/WebKit/Source/core/frame/ScreenOrientationController.h
+++ b/third_party/WebKit/Source/core/frame/ScreenOrientationController.h
@@ -19,7 +19,11 @@
 // module will implement and add a provider for.
 // Callers of ScreenOrientationController::from() should always assume the
 // returned pointer can be nullptr.
-class CORE_EXPORT ScreenOrientationController : public Supplement<LocalFrame> {
+class CORE_EXPORT ScreenOrientationController
+    : public GarbageCollectedFinalized<ScreenOrientationController>,
+      public Supplement<LocalFrame> {
+  USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationController);
+
  public:
   virtual ~ScreenOrientationController() = default;
 
@@ -38,6 +42,7 @@
   DECLARE_VIRTUAL_TRACE();
 
  protected:
+  explicit ScreenOrientationController(LocalFrame&);
   // To be called by an ScreenOrientationController to register its
   // implementation.
   static void provideTo(LocalFrame&, ScreenOrientationController*);
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn
index 63cfdfcb..0fab038 100644
--- a/third_party/WebKit/Source/core/html/BUILD.gn
+++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -17,6 +17,8 @@
     "CrossOriginAttribute.h",
     "DocumentNameCollection.cpp",
     "DocumentNameCollection.h",
+    "Float32ImageData.cpp",
+    "Float32ImageData.h",
     "FormAssociated.h",
     "FormData.cpp",
     "FormData.h",
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.cpp b/third_party/WebKit/Source/core/html/Float32ImageData.cpp
new file mode 100644
index 0000000..665a265
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2016 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/html/Float32ImageData.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/V8Float32Array.h"
+#include "core/dom/ExceptionCode.h"
+#include "core/frame/ImageBitmap.h"
+#include "core/imagebitmap/ImageBitmapOptions.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "wtf/CheckedNumeric.h"
+
+namespace blink {
+
+bool Float32ImageData::validateConstructorArguments(
+    const unsigned& paramFlags,
+    const IntSize* size,
+    const unsigned& width,
+    const unsigned& height,
+    const DOMFloat32Array* data,
+    const String* colorSpace,
+    ExceptionState* exceptionState) {
+  return ImageData::validateConstructorArguments(
+      paramFlags, size, width, height, data, colorSpace, exceptionState,
+      kFloat32ImageData);
+}
+
+DOMFloat32Array* Float32ImageData::allocateAndValidateFloat32Array(
+    const unsigned& length,
+    ExceptionState* exceptionState) {
+  if (!length)
+    return nullptr;
+  DOMFloat32Array* dataArray = DOMFloat32Array::createOrNull(length);
+  if (!dataArray || length != dataArray->length()) {
+    if (exceptionState) {
+      exceptionState->throwDOMException(
+          V8RangeError, "Out of memory at Float32ImageData creation");
+    }
+    return nullptr;
+  }
+  return dataArray;
+}
+
+Float32ImageData* Float32ImageData::create(const IntSize& size) {
+  if (!Float32ImageData::validateConstructorArguments(kParamSize, &size))
+    return nullptr;
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * size.width() *
+                                                        size.height());
+  return dataArray ? new Float32ImageData(size, dataArray) : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(const IntSize& size,
+                                           DOMFloat32Array* dataArray) {
+  if (!Float32ImageData::validateConstructorArguments(kParamSize | kParamData,
+                                                      &size, 0, 0, dataArray))
+    return nullptr;
+  return new Float32ImageData(size, dataArray);
+}
+
+Float32ImageData* Float32ImageData::create(unsigned width,
+                                           unsigned height,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight, nullptr, width, height, nullptr, nullptr,
+          &exceptionState))
+    return nullptr;
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * width * height,
+                                                        &exceptionState);
+  return dataArray ? new Float32ImageData(IntSize(width, height), dataArray)
+                   : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(kParamData | kParamWidth,
+                                                      nullptr, width, 0, data,
+                                                      nullptr, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new Float32ImageData(IntSize(width, height), data);
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           unsigned height,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
+          nullptr, &exceptionState))
+    return nullptr;
+  return new Float32ImageData(IntSize(width, height), data);
+}
+
+Float32ImageData* Float32ImageData::create(unsigned width,
+                                           unsigned height,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height,
+          nullptr, &colorSpace, &exceptionState))
+    return nullptr;
+
+  DOMFloat32Array* dataArray =
+      Float32ImageData::allocateAndValidateFloat32Array(4 * width * height,
+                                                        &exceptionState);
+  return dataArray ? new Float32ImageData(IntSize(width, height), dataArray,
+                                          colorSpace)
+                   : nullptr;
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data,
+          &colorSpace, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new Float32ImageData(IntSize(width, height), data, colorSpace);
+}
+
+Float32ImageData* Float32ImageData::create(DOMFloat32Array* data,
+                                           unsigned width,
+                                           unsigned height,
+                                           String colorSpace,
+                                           ExceptionState& exceptionState) {
+  if (!Float32ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr,
+          width, height, data, &colorSpace, &exceptionState))
+    return nullptr;
+  return new Float32ImageData(IntSize(width, height), data, colorSpace);
+}
+
+v8::Local<v8::Object> Float32ImageData::associateWithWrapper(
+    v8::Isolate* isolate,
+    const WrapperTypeInfo* wrapperType,
+    v8::Local<v8::Object> wrapper) {
+  wrapper =
+      ScriptWrappable::associateWithWrapper(isolate, wrapperType, wrapper);
+
+  if (!wrapper.IsEmpty() && m_data.get()) {
+    // Create a V8 Float32Array object and set the "data" property
+    // of the Float32ImageData object to the created v8 object, eliminating the
+    // C++ callback when accessing the "data" property.
+    v8::Local<v8::Value> pixelArray = ToV8(m_data.get(), wrapper, isolate);
+    if (pixelArray.IsEmpty() ||
+        !v8CallBoolean(wrapper->DefineOwnProperty(
+            isolate->GetCurrentContext(), v8AtomicString(isolate, "data"),
+            pixelArray, v8::ReadOnly)))
+      return v8::Local<v8::Object>();
+  }
+  return wrapper;
+}
+
+Float32ImageData::Float32ImageData(const IntSize& size,
+                                   DOMFloat32Array* dataArray,
+                                   String colorSpaceName)
+    : m_size(size),
+      m_colorSpace(ImageData::getImageDataColorSpace(colorSpaceName)),
+      m_data(dataArray) {
+  DCHECK_GE(size.width(), 0);
+  DCHECK_GE(size.height(), 0);
+  SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
+                 m_data->length());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.h b/third_party/WebKit/Source/core/html/Float32ImageData.h
new file mode 100644
index 0000000..361fb1d
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Float32ImageData_h
+#define Float32ImageData_h
+
+#include "bindings/core/v8/ScriptWrappable.h"
+#include "core/CoreExport.h"
+#include "core/dom/DOMTypedArray.h"
+#include "core/html/ImageData.h"
+#include "core/imagebitmap/ImageBitmapSource.h"
+#include "platform/geometry/IntRect.h"
+#include "platform/geometry/IntSize.h"
+#include "platform/heap/Handle.h"
+#include "wtf/Compiler.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+class ExceptionState;
+
+class CORE_EXPORT Float32ImageData final
+    : public GarbageCollectedFinalized<Float32ImageData>,
+      public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static Float32ImageData* create(const IntSize&);
+  static Float32ImageData* create(const IntSize&, DOMFloat32Array*);
+  static Float32ImageData* create(unsigned width,
+                                  unsigned height,
+                                  ExceptionState&);
+  static Float32ImageData* create(unsigned width,
+                                  unsigned height,
+                                  String colorSpace,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  String colorSpace,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  unsigned height,
+                                  ExceptionState&);
+  static Float32ImageData* create(DOMFloat32Array*,
+                                  unsigned width,
+                                  unsigned height,
+                                  String colorSpace,
+                                  ExceptionState&);
+
+  IntSize size() const { return m_size; }
+  int width() const { return m_size.width(); }
+  int height() const { return m_size.height(); }
+  String colorSpace() const {
+    return ImageData::getImageDataColorSpaceName(m_colorSpace);
+  }
+  ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; }
+  const DOMFloat32Array* data() const { return m_data.get(); }
+  DOMFloat32Array* data() { return m_data.get(); }
+
+  DEFINE_INLINE_TRACE() { visitor->trace(m_data); }
+
+  WARN_UNUSED_RESULT v8::Local<v8::Object> associateWithWrapper(
+      v8::Isolate*,
+      const WrapperTypeInfo*,
+      v8::Local<v8::Object> wrapper) override;
+
+ private:
+  Float32ImageData(const IntSize&,
+                   DOMFloat32Array*,
+                   String = kLinearRGBImageDataColorSpaceName);
+
+  IntSize m_size;
+  ImageDataColorSpace m_colorSpace;
+  Member<DOMFloat32Array> m_data;
+
+  static bool validateConstructorArguments(const unsigned&,
+                                           const IntSize* = nullptr,
+                                           const unsigned& = 0,
+                                           const unsigned& = 0,
+                                           const DOMFloat32Array* = nullptr,
+                                           const String* = nullptr,
+                                           ExceptionState* = nullptr);
+
+  static DOMFloat32Array* allocateAndValidateFloat32Array(
+      const unsigned&,
+      ExceptionState* = nullptr);
+};
+
+}  // namespace blink
+
+#endif  // Float32ImageData_h
diff --git a/third_party/WebKit/Source/core/html/Float32ImageData.idl b/third_party/WebKit/Source/core/html/Float32ImageData.idl
new file mode 100644
index 0000000..555e366
--- /dev/null
+++ b/third_party/WebKit/Source/core/html/Float32ImageData.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata
+
+[
+    Constructor(unsigned long sw, unsigned long sh),
+    Constructor(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace),
+    Constructor(Float32Array data, unsigned long sw),
+    Constructor(Float32Array data, unsigned long sw, unsigned long sh),
+    Constructor(Float32Array data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace),
+
+    Exposed=(Window,Worker),
+    RaisesException=Constructor,
+    RuntimeEnabled=ExperimentalCanvasFeatures,
+] interface Float32ImageData {
+    readonly attribute unsigned long width;
+    readonly attribute unsigned long height;
+    readonly attribute Float32Array data;
+    readonly attribute ImageDataColorSpace colorSpace;
+};
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp
index 355814b..1bc6d27f 100644
--- a/third_party/WebKit/Source/core/html/ImageData.cpp
+++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -34,11 +34,161 @@
 #include "core/frame/ImageBitmap.h"
 #include "core/imagebitmap/ImageBitmapOptions.h"
 #include "platform/RuntimeEnabledFeatures.h"
-#include "wtf/CheckedNumeric.h"
 
 namespace blink {
 
+bool ImageData::validateConstructorArguments(const unsigned& paramFlags,
+                                             const IntSize* size,
+                                             const unsigned& width,
+                                             const unsigned& height,
+                                             const DOMArrayBufferView* data,
+                                             const String* colorSpace,
+                                             ExceptionState* exceptionState,
+                                             ImageDataType imageDataType) {
+  if (paramFlags & kParamData) {
+    if (data->type() != DOMArrayBufferView::ViewType::TypeUint8Clamped &&
+        data->type() != DOMArrayBufferView::ViewType::TypeFloat32)
+      return false;
+    if (data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped &&
+        imageDataType != kUint8ClampedImageData)
+      imageDataType = kFloat32ImageData;
+  }
+
+  // ImageData::create parameters without ExceptionState
+  if (paramFlags & kParamSize) {
+    if (!size->width() || !size->height())
+      return false;
+    if (paramFlags & kParamData) {
+      DCHECK(data);
+      CheckedNumeric<unsigned> dataSize = 4;
+      dataSize *= size->width();
+      dataSize *= size->height();
+      unsigned length =
+          data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped
+              ? (const_cast<DOMUint8ClampedArray*>(
+                     static_cast<const DOMUint8ClampedArray*>(data)))
+                    ->length()
+              : (const_cast<DOMFloat32Array*>(
+                     static_cast<const DOMFloat32Array*>(data)))
+                    ->length();
+      if (!dataSize.IsValid() || dataSize.ValueOrDie() > length)
+        return false;
+    }
+    return true;
+  }
+
+  // ImageData::create parameters with ExceptionState
+  if ((paramFlags & kParamWidth) && !width) {
+    exceptionState->throwDOMException(
+        IndexSizeError, "The source width is zero or not a number.");
+    return false;
+  }
+  if ((paramFlags & kParamHeight) && !height) {
+    exceptionState->throwDOMException(
+        IndexSizeError, "The source height is zero or not a number.");
+    return false;
+  }
+  if (paramFlags & (kParamWidth | kParamHeight)) {
+    CheckedNumeric<unsigned> dataSize = 4;
+    dataSize *= width;
+    dataSize *= height;
+    if (!dataSize.IsValid()) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The requested image size exceeds the supported range.");
+      return false;
+    }
+  }
+  if (paramFlags & kParamData) {
+    DCHECK(data);
+    unsigned length =
+        data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped
+            ? (const_cast<DOMUint8ClampedArray*>(
+                   static_cast<const DOMUint8ClampedArray*>(data)))
+                  ->length()
+            : (const_cast<DOMFloat32Array*>(
+                   static_cast<const DOMFloat32Array*>(data)))
+                  ->length();
+    if (!length) {
+      exceptionState->throwDOMException(IndexSizeError,
+                                        "The input data has zero elements.");
+      return false;
+    }
+    if (length % 4) {
+      exceptionState->throwDOMException(
+          IndexSizeError, "The input data length is not a multiple of 4.");
+      return false;
+    }
+    length /= 4;
+    if (length % width) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The input data length is not a multiple of (4 * width).");
+      return false;
+    }
+    if ((paramFlags & kParamHeight) && height != length / width) {
+      exceptionState->throwDOMException(
+          IndexSizeError,
+          "The input data length is not equal to (4 * width * height).");
+      return false;
+    }
+  }
+  if (paramFlags & kParamColorSpace) {
+    if (!colorSpace || colorSpace->length() == 0) {
+      exceptionState->throwDOMException(
+          NotSupportedError, "The source color space is not defined.");
+      return false;
+    }
+    if (imageDataType == kUint8ClampedImageData &&
+        *colorSpace != kLegacyImageDataColorSpaceName &&
+        *colorSpace != kSRGBImageDataColorSpaceName) {
+      exceptionState->throwDOMException(NotSupportedError,
+                                        "The input color space is not "
+                                        "supported in "
+                                        "Uint8ClampedArray-backed ImageData.");
+      return false;
+    }
+    if (imageDataType == kFloat32ImageData &&
+        *colorSpace != kLinearRGBImageDataColorSpaceName) {
+      exceptionState->throwDOMException(NotSupportedError,
+                                        "The input color space is not "
+                                        "supported in "
+                                        "Float32Array-backed ImageData.");
+      return false;
+    }
+  }
+  return true;
+}
+
+DOMUint8ClampedArray* ImageData::allocateAndValidateUint8ClampedArray(
+    const unsigned& length,
+    ExceptionState* exceptionState) {
+  if (!length)
+    return nullptr;
+  DOMUint8ClampedArray* dataArray = DOMUint8ClampedArray::createOrNull(length);
+  if (!dataArray || length != dataArray->length()) {
+    if (exceptionState) {
+      exceptionState->throwDOMException(V8RangeError,
+                                        "Out of memory at ImageData creation");
+    }
+    return nullptr;
+  }
+  return dataArray;
+}
+
 ImageData* ImageData::create(const IntSize& size) {
+  if (!ImageData::validateConstructorArguments(kParamSize, &size))
+    return nullptr;
+  DOMUint8ClampedArray* byteArray =
+      ImageData::allocateAndValidateUint8ClampedArray(4 * size.width() *
+                                                      size.height());
+  if (!byteArray)
+    return nullptr;
+  return new ImageData(size, byteArray);
+}
+
+// This function accepts size (0, 0).
+ImageData* ImageData::createForTest(const IntSize& size) {
   CheckedNumeric<unsigned> dataSize = 4;
   dataSize *= size.width();
   dataSize *= size.height();
@@ -55,94 +205,33 @@
 
 ImageData* ImageData::create(const IntSize& size,
                              DOMUint8ClampedArray* byteArray) {
-  CheckedNumeric<unsigned> dataSize = 4;
-  dataSize *= size.width();
-  dataSize *= size.height();
-  if (!dataSize.IsValid())
+  if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size,
+                                               0, 0, byteArray))
     return nullptr;
-
-  if (!dataSize.IsValid() || dataSize.ValueOrDie() > byteArray->length())
-    return nullptr;
-
   return new ImageData(size, byteArray);
 }
 
 ImageData* ImageData::create(unsigned width,
                              unsigned height,
                              ExceptionState& exceptionState) {
-  if (!width || !height) {
-    exceptionState.throwDOMException(
-        IndexSizeError, String::format("The source %s is zero or not a number.",
-                                       width ? "height" : "width"));
+  if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight,
+                                               nullptr, width, height, nullptr,
+                                               nullptr, &exceptionState))
     return nullptr;
-  }
-
-  CheckedNumeric<unsigned> dataSize = 4;
-  dataSize *= width;
-  dataSize *= height;
-  if (!dataSize.IsValid() || static_cast<int>(width) < 0 ||
-      static_cast<int>(height) < 0) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The requested image size exceeds the supported range.");
-    return nullptr;
-  }
-
   DOMUint8ClampedArray* byteArray =
-      DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie());
-  if (!byteArray) {
-    exceptionState.throwDOMException(V8Error,
-                                     "Out of memory at ImageData creation");
-    return nullptr;
-  }
-
-  return new ImageData(IntSize(width, height), byteArray);
-}
-
-bool ImageData::validateConstructorArguments(DOMUint8ClampedArray* data,
-                                             unsigned width,
-                                             unsigned& lengthInPixels,
-                                             ExceptionState& exceptionState) {
-  if (!width) {
-    exceptionState.throwDOMException(
-        IndexSizeError, "The source width is zero or not a number.");
-    return false;
-  }
-  DCHECK(data);
-  unsigned length = data->length();
-  if (!length) {
-    exceptionState.throwDOMException(IndexSizeError,
-                                     "The input data has a zero byte length.");
-    return false;
-  }
-  if (length % 4) {
-    exceptionState.throwDOMException(
-        IndexSizeError, "The input data byte length is not a multiple of 4.");
-    return false;
-  }
-  length /= 4;
-  if (length % width) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The input data byte length is not a multiple of (4 * width).");
-    return false;
-  }
-  lengthInPixels = length;
-  return true;
+      ImageData::allocateAndValidateUint8ClampedArray(4 * width * height,
+                                                      &exceptionState);
+  return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr;
 }
 
 ImageData* ImageData::create(DOMUint8ClampedArray* data,
                              unsigned width,
                              ExceptionState& exceptionState) {
-  unsigned lengthInPixels = 0;
-  if (!validateConstructorArguments(data, width, lengthInPixels,
-                                    exceptionState)) {
-    DCHECK(exceptionState.hadException());
+  if (!ImageData::validateConstructorArguments(kParamData | kParamWidth,
+                                               nullptr, width, 0, data, nullptr,
+                                               &exceptionState))
     return nullptr;
-  }
-  DCHECK_GT(lengthInPixels, 0u);
-  DCHECK_GT(width, 0u);
-  unsigned height = lengthInPixels / width;
+  unsigned height = data->length() / (width * 4);
   return new ImageData(IntSize(width, height), data);
 }
 
@@ -150,23 +239,81 @@
                              unsigned width,
                              unsigned height,
                              ExceptionState& exceptionState) {
-  unsigned lengthInPixels = 0;
-  if (!validateConstructorArguments(data, width, lengthInPixels,
-                                    exceptionState)) {
-    DCHECK(exceptionState.hadException());
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
+          nullptr, &exceptionState))
     return nullptr;
-  }
-  DCHECK_GT(lengthInPixels, 0u);
-  DCHECK_GT(width, 0u);
-  if (height != lengthInPixels / width) {
-    exceptionState.throwDOMException(
-        IndexSizeError,
-        "The input data byte length is not equal to (4 * width * height).");
-    return nullptr;
-  }
   return new ImageData(IntSize(width, height), data);
 }
 
+ImageDataColorSpace ImageData::getImageDataColorSpace(String colorSpaceName) {
+  if (colorSpaceName == kLegacyImageDataColorSpaceName)
+    return kLegacyImageDataColorSpace;
+  if (colorSpaceName == kSRGBImageDataColorSpaceName)
+    return kSRGBImageDataColorSpace;
+  if (colorSpaceName == kLinearRGBImageDataColorSpaceName)
+    return kLinearRGBImageDataColorSpace;
+  NOTREACHED();
+  return kLegacyImageDataColorSpace;
+}
+
+String ImageData::getImageDataColorSpaceName(ImageDataColorSpace colorSpace) {
+  switch (colorSpace) {
+    case kLegacyImageDataColorSpace:
+      return kLegacyImageDataColorSpaceName;
+    case kSRGBImageDataColorSpace:
+      return kSRGBImageDataColorSpaceName;
+    case kLinearRGBImageDataColorSpace:
+      return kLinearRGBImageDataColorSpaceName;
+  }
+  NOTREACHED();
+  return String();
+}
+
+ImageData* ImageData::createImageData(unsigned width,
+                                      unsigned height,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height,
+          nullptr, &colorSpace, &exceptionState))
+    return nullptr;
+
+  DOMUint8ClampedArray* byteArray =
+      ImageData::allocateAndValidateUint8ClampedArray(4 * width * height,
+                                                      &exceptionState);
+  return byteArray
+             ? new ImageData(IntSize(width, height), byteArray, colorSpace)
+             : nullptr;
+}
+
+ImageData* ImageData::createImageData(DOMUint8ClampedArray* data,
+                                      unsigned width,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data,
+          &colorSpace, &exceptionState))
+    return nullptr;
+  unsigned height = data->length() / (width * 4);
+  return new ImageData(IntSize(width, height), data, colorSpace);
+}
+
+ImageData* ImageData::createImageData(DOMUint8ClampedArray* data,
+                                      unsigned width,
+                                      unsigned height,
+                                      String colorSpace,
+                                      ExceptionState& exceptionState) {
+  if (!ImageData::validateConstructorArguments(
+          kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr,
+          width, height, data, &colorSpace, &exceptionState))
+    return nullptr;
+  return new ImageData(IntSize(width, height), data, colorSpace);
+}
+
+// TODO(zakerinasab): Fix this when ImageBitmap color correction code is landed.
+// Tip: If the source Image Data has a color space, createImageBitmap must
+// respect this color space even when no color space tag is passed to it.
 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState,
                                            EventTarget& eventTarget,
                                            Optional<IntRect> cropRect,
@@ -211,8 +358,12 @@
   return wrapper;
 }
 
-ImageData::ImageData(const IntSize& size, DOMUint8ClampedArray* byteArray)
-    : m_size(size), m_data(byteArray) {
+ImageData::ImageData(const IntSize& size,
+                     DOMUint8ClampedArray* byteArray,
+                     String colorSpaceName)
+    : m_size(size),
+      m_colorSpace(getImageDataColorSpace(colorSpaceName)),
+      m_data(byteArray) {
   DCHECK_GE(size.width(), 0);
   DCHECK_GE(size.height(), 0);
   SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <=
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h
index 206671a..286092d 100644
--- a/third_party/WebKit/Source/core/html/ImageData.h
+++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -31,18 +31,44 @@
 
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "core/CoreExport.h"
+#include "core/dom/DOMArrayBufferView.h"
 #include "core/dom/DOMTypedArray.h"
 #include "core/imagebitmap/ImageBitmapSource.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/geometry/IntSize.h"
 #include "platform/heap/Handle.h"
+#include "wtf/CheckedNumeric.h"
 #include "wtf/Compiler.h"
+#include "wtf/text/WTFString.h"
 
 namespace blink {
 
 class ExceptionState;
 class ImageBitmapOptions;
 
+enum ConstructorParams {
+  kParamSize = 1,
+  kParamWidth = 1 << 1,
+  kParamHeight = 1 << 2,
+  kParamData = 1 << 3,
+  kParamColorSpace = 1 << 4,
+};
+
+enum ImageDataType {
+  kUint8ClampedImageData,
+  kFloat32ImageData,
+};
+
+enum ImageDataColorSpace {
+  kLegacyImageDataColorSpace,
+  kSRGBImageDataColorSpace,
+  kLinearRGBImageDataColorSpace,
+};
+
+const char* const kLinearRGBImageDataColorSpaceName = "linear-rgb";
+const char* const kSRGBImageDataColorSpaceName = "srgb";
+const char* const kLegacyImageDataColorSpaceName = "legacy-srgb";
+
 class CORE_EXPORT ImageData final : public GarbageCollectedFinalized<ImageData>,
                                     public ScriptWrappable,
                                     public ImageBitmapSource {
@@ -60,9 +86,30 @@
                            unsigned height,
                            ExceptionState&);
 
+  static ImageData* createForTest(const IntSize&);
+
+  ImageData* createImageData(unsigned width,
+                             unsigned height,
+                             String colorSpace,
+                             ExceptionState&);
+  ImageData* createImageData(DOMUint8ClampedArray*,
+                             unsigned width,
+                             String colorSpace,
+                             ExceptionState&);
+  ImageData* createImageData(DOMUint8ClampedArray*,
+                             unsigned width,
+                             unsigned height,
+                             String colorSpace,
+                             ExceptionState&);
+
+  static ImageDataColorSpace getImageDataColorSpace(String);
+  static String getImageDataColorSpaceName(ImageDataColorSpace);
+
   IntSize size() const { return m_size; }
   int width() const { return m_size.width(); }
   int height() const { return m_size.height(); }
+  String colorSpace() const { return getImageDataColorSpaceName(m_colorSpace); }
+  ImageDataColorSpace imageDataColorSpace() { return m_colorSpace; }
   const DOMUint8ClampedArray* data() const { return m_data.get(); }
   DOMUint8ClampedArray* data() { return m_data.get(); }
 
@@ -81,16 +128,28 @@
       const WrapperTypeInfo*,
       v8::Local<v8::Object> wrapper) override;
 
- private:
-  ImageData(const IntSize&, DOMUint8ClampedArray*);
+  static bool validateConstructorArguments(
+      const unsigned&,
+      const IntSize* = nullptr,
+      const unsigned& = 0,
+      const unsigned& = 0,
+      const DOMArrayBufferView* = nullptr,
+      const String* = nullptr,
+      ExceptionState* = nullptr,
+      ImageDataType = kUint8ClampedImageData);
 
-  static bool validateConstructorArguments(DOMUint8ClampedArray*,
-                                           unsigned width,
-                                           unsigned&,
-                                           ExceptionState&);
+ private:
+  ImageData(const IntSize&,
+            DOMUint8ClampedArray*,
+            String = kLegacyImageDataColorSpaceName);
 
   IntSize m_size;
+  ImageDataColorSpace m_colorSpace;
   Member<DOMUint8ClampedArray> m_data;
+
+  static DOMUint8ClampedArray* allocateAndValidateUint8ClampedArray(
+      const unsigned&,
+      ExceptionState* = nullptr);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/ImageData.idl b/third_party/WebKit/Source/core/html/ImageData.idl
index d52d253..38051b0 100644
--- a/third_party/WebKit/Source/core/html/ImageData.idl
+++ b/third_party/WebKit/Source/core/html/ImageData.idl
@@ -27,6 +27,9 @@
  */
 
 // https://html.spec.whatwg.org/#dom-imagedata
+// https://github.com/junov/CanvasColorSpace/blob/master/CanvasColorSpaceProposal.md#imagedata
+
+enum ImageDataColorSpace { "legacy-srgb", "srgb", "linear-rgb" };
 
 [
     Constructor(unsigned long sw, unsigned long sh),
@@ -34,8 +37,13 @@
     Exposed=(Window,Worker),
     RaisesException=Constructor,
 ] interface ImageData {
+
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace);
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, ImageDataColorSpace colorSpace);
+    [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] ImageData createImageData(Uint8ClampedArray data, unsigned long sw, unsigned long sh, ImageDataColorSpace colorSpace);
+
     readonly attribute unsigned long width;
     readonly attribute unsigned long height;
-    // TODO(foolip): Expose data.
-    // readonly attribute Uint8ClampedArray data;
+    readonly attribute Uint8ClampedArray data;
+    readonly attribute ImageDataColorSpace colorSpace;
 };
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
index 6a771c1..c5a39da 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
@@ -200,7 +200,7 @@
 
 void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailPng() {
   IntSize testSize(0, 0);
-  ImageData* imageData = ImageData::create(testSize);
+  ImageData* imageData = ImageData::createForTest(testSize);
 
   // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompletePng because
   // this test case is expected to fail at initialization step before
@@ -229,7 +229,7 @@
 
 void CanvasAsyncBlobCreatorTest::prepareMockCanvasAsyncBlobCreatorFailJpeg() {
   IntSize testSize(0, 0);
-  ImageData* imageData = ImageData::create(testSize);
+  ImageData* imageData = ImageData::createForTest(testSize);
 
   // We reuse the class MockCanvasAsyncBlobCreatorWithoutCompleteJpeg because
   // this test case is expected to fail at initialization step before
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp
index 6a80ef90..ad490be 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControlsOrientationLockDelegateTest.cpp
@@ -92,15 +92,13 @@
 };
 
 class MockScreenOrientationController final
-    : public GarbageCollectedFinalized<MockScreenOrientationController>,
-      public ScreenOrientationController {
-  USING_GARBAGE_COLLECTED_MIXIN(MockScreenOrientationController);
+    : public ScreenOrientationController {
   WTF_MAKE_NONCOPYABLE(MockScreenOrientationController);
 
  public:
   static MockScreenOrientationController* provideTo(LocalFrame& frame) {
     MockScreenOrientationController* controller =
-        new MockScreenOrientationController();
+        new MockScreenOrientationController(frame);
     ScreenOrientationController::provideTo(frame, controller);
     return controller;
   }
@@ -108,10 +106,11 @@
   MOCK_METHOD1(lock, void(WebScreenOrientationLockType));
   MOCK_METHOD0(mockUnlock, void());
 
-  DEFINE_INLINE_VIRTUAL_TRACE() { Supplement<LocalFrame>::trace(visitor); }
+  DEFINE_INLINE_VIRTUAL_TRACE() { ScreenOrientationController::trace(visitor); }
 
  private:
-  MockScreenOrientationController() = default;
+  explicit MockScreenOrientationController(LocalFrame& frame)
+      : ScreenOrientationController(frame) {}
 
   void lock(WebScreenOrientationLockType type,
             std::unique_ptr<WebLockOrientationCallback>) override {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
index 4fd0a6e6..93b7ec5 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorNetworkAgent.cpp
@@ -71,7 +71,7 @@
 #include "platform/weborigin/ReferrerPolicy.h"
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/WebCachePolicy.h"
-#include "public/platform/WebMixedContent.h"
+#include "public/platform/WebMixedContentContextType.h"
 #include "public/platform/WebURLLoaderClient.h"
 #include "public/platform/WebURLRequest.h"
 #include "wtf/CurrentTime.h"
@@ -211,15 +211,14 @@
   return result;
 }
 
-String mixedContentTypeForContextType(
-    WebMixedContent::ContextType contextType) {
+String mixedContentTypeForContextType(WebMixedContentContextType contextType) {
   switch (contextType) {
-    case WebMixedContent::ContextType::NotMixedContent:
+    case WebMixedContentContextType::NotMixedContent:
       return protocol::Network::Request::MixedContentTypeEnum::None;
-    case WebMixedContent::ContextType::Blockable:
+    case WebMixedContentContextType::Blockable:
       return protocol::Network::Request::MixedContentTypeEnum::Blockable;
-    case WebMixedContent::ContextType::OptionallyBlockable:
-    case WebMixedContent::ContextType::ShouldBeBlockable:
+    case WebMixedContentContextType::OptionallyBlockable:
+    case WebMixedContentContextType::ShouldBeBlockable:
       return protocol::Network::Request::MixedContentTypeEnum::
           OptionallyBlockable;
   }
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
index 21c313b2..51dfb21 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
+++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.cpp
@@ -43,6 +43,7 @@
 #include "platform/weborigin/SecurityOrigin.h"
 #include "public/platform/WebAddressSpace.h"
 #include "public/platform/WebInsecureRequestPolicy.h"
+#include "public/platform/WebMixedContent.h"
 #include "wtf/text/StringBuilder.h"
 
 namespace blink {
@@ -61,6 +62,81 @@
   return toLocalFrame(frame)->document()->url();
 }
 
+const char* requestContextName(WebURLRequest::RequestContext context) {
+  switch (context) {
+    case WebURLRequest::RequestContextAudio:
+      return "audio file";
+    case WebURLRequest::RequestContextBeacon:
+      return "Beacon endpoint";
+    case WebURLRequest::RequestContextCSPReport:
+      return "Content Security Policy reporting endpoint";
+    case WebURLRequest::RequestContextDownload:
+      return "download";
+    case WebURLRequest::RequestContextEmbed:
+      return "plugin resource";
+    case WebURLRequest::RequestContextEventSource:
+      return "EventSource endpoint";
+    case WebURLRequest::RequestContextFavicon:
+      return "favicon";
+    case WebURLRequest::RequestContextFetch:
+      return "resource";
+    case WebURLRequest::RequestContextFont:
+      return "font";
+    case WebURLRequest::RequestContextForm:
+      return "form action";
+    case WebURLRequest::RequestContextFrame:
+      return "frame";
+    case WebURLRequest::RequestContextHyperlink:
+      return "resource";
+    case WebURLRequest::RequestContextIframe:
+      return "frame";
+    case WebURLRequest::RequestContextImage:
+      return "image";
+    case WebURLRequest::RequestContextImageSet:
+      return "image";
+    case WebURLRequest::RequestContextImport:
+      return "HTML Import";
+    case WebURLRequest::RequestContextInternal:
+      return "resource";
+    case WebURLRequest::RequestContextLocation:
+      return "resource";
+    case WebURLRequest::RequestContextManifest:
+      return "manifest";
+    case WebURLRequest::RequestContextObject:
+      return "plugin resource";
+    case WebURLRequest::RequestContextPing:
+      return "hyperlink auditing endpoint";
+    case WebURLRequest::RequestContextPlugin:
+      return "plugin data";
+    case WebURLRequest::RequestContextPrefetch:
+      return "prefetch resource";
+    case WebURLRequest::RequestContextScript:
+      return "script";
+    case WebURLRequest::RequestContextServiceWorker:
+      return "Service Worker script";
+    case WebURLRequest::RequestContextSharedWorker:
+      return "Shared Worker script";
+    case WebURLRequest::RequestContextStyle:
+      return "stylesheet";
+    case WebURLRequest::RequestContextSubresource:
+      return "resource";
+    case WebURLRequest::RequestContextTrack:
+      return "Text Track";
+    case WebURLRequest::RequestContextUnspecified:
+      return "resource";
+    case WebURLRequest::RequestContextVideo:
+      return "video";
+    case WebURLRequest::RequestContextWorker:
+      return "Worker script";
+    case WebURLRequest::RequestContextXMLHttpRequest:
+      return "XMLHttpRequest endpoint";
+    case WebURLRequest::RequestContextXSLT:
+      return "XSLT";
+  }
+  NOTREACHED();
+  return "resource";
+}
+
 }  // namespace
 
 static void measureStricterVersionOfIsMixedContent(Frame* frame,
@@ -150,8 +226,7 @@
       "Mixed Content: The page at '%s' was loaded over HTTPS, but requested an "
       "insecure %s '%s'. %s",
       mainResourceUrl.elidedString().utf8().data(),
-      WebMixedContent::requestContextName(requestContext),
-      url.elidedString().utf8().data(),
+      requestContextName(requestContext), url.elidedString().utf8().data(),
       allowed ? "This content should also be served over HTTPS."
               : "This request has been blocked; the content must be served "
                 "over HTTPS.");
@@ -168,11 +243,11 @@
   // Roll blockable content up into a single counter, count unblocked types
   // individually so we can determine when they can be safely moved to the
   // blockable category:
-  WebMixedContent::ContextType contextType =
+  WebMixedContentContextType contextType =
       WebMixedContent::contextTypeFromRequestContext(
           requestContext,
           frame->settings()->getStrictMixedContentCheckingForPlugin());
-  if (contextType == WebMixedContent::ContextType::Blockable) {
+  if (contextType == WebMixedContentContextType::Blockable) {
     UseCounter::count(frame, UseCounter::MixedContentBlockable);
     return;
   }
@@ -245,7 +320,7 @@
                         kBlockAllMixedContent ||
                     settings->getStrictMixedContentChecking();
 
-  WebMixedContent::ContextType contextType =
+  WebMixedContentContextType contextType =
       WebMixedContent::contextTypeFromRequestContext(
           requestContext, settings->getStrictMixedContentCheckingForPlugin());
 
@@ -259,10 +334,10 @@
   // https://crbug.com/393481
   if (frameType == WebURLRequest::FrameTypeNested &&
       !SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(url.protocol()))
-    contextType = WebMixedContent::ContextType::OptionallyBlockable;
+    contextType = WebMixedContentContextType::OptionallyBlockable;
 
   switch (contextType) {
-    case WebMixedContent::ContextType::OptionallyBlockable:
+    case WebMixedContentContextType::OptionallyBlockable:
       allowed = !strictMode;
       if (allowed) {
         client->passiveInsecureContentFound(url);
@@ -270,7 +345,7 @@
       }
       break;
 
-    case WebMixedContent::ContextType::Blockable: {
+    case WebMixedContentContextType::Blockable: {
       // Strictly block subresources that are mixed with respect to their
       // subframes, unless all insecure content is allowed. This is to avoid the
       // following situation: https://a.com embeds https://b.com, which loads a
@@ -302,12 +377,12 @@
       break;
     }
 
-    case WebMixedContent::ContextType::ShouldBeBlockable:
+    case WebMixedContentContextType::ShouldBeBlockable:
       allowed = !strictMode;
       if (allowed)
         client->didDisplayInsecureContent();
       break;
-    case WebMixedContent::ContextType::NotMixedContent:
+    case WebMixedContentContextType::NotMixedContent:
       NOTREACHED();
       break;
   };
@@ -475,20 +550,20 @@
   bool strictMixedContentCheckingForPlugin =
       effectiveFrame->settings() &&
       effectiveFrame->settings()->getStrictMixedContentCheckingForPlugin();
-  WebMixedContent::ContextType contextType =
+  WebMixedContentContextType contextType =
       WebMixedContent::contextTypeFromRequestContext(
           requestContext, strictMixedContentCheckingForPlugin);
-  if (contextType == WebMixedContent::ContextType::Blockable) {
+  if (contextType == WebMixedContentContextType::Blockable) {
     client->didRunContentWithCertificateErrors(response.url());
   } else {
     // contextTypeFromRequestContext() never returns NotMixedContent (it
     // computes the type of mixed content, given that the content is mixed).
-    DCHECK_NE(contextType, WebMixedContent::ContextType::NotMixedContent);
+    DCHECK_NE(contextType, WebMixedContentContextType::NotMixedContent);
     client->didDisplayContentWithCertificateErrors(response.url());
   }
 }
 
-WebMixedContent::ContextType MixedContentChecker::contextTypeForInspector(
+WebMixedContentContextType MixedContentChecker::contextTypeForInspector(
     LocalFrame* frame,
     const ResourceRequest& request) {
   Frame* effectiveFrame =
@@ -497,14 +572,14 @@
   Frame* mixedFrame = inWhichFrameIsContentMixed(
       effectiveFrame, request.frameType(), request.url());
   if (!mixedFrame)
-    return WebMixedContent::ContextType::NotMixedContent;
+    return WebMixedContentContextType::NotMixedContent;
 
   // See comment in shouldBlockFetch() about loading the main resource of a
   // subframe.
   if (request.frameType() == WebURLRequest::FrameTypeNested &&
       !SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(
           request.url().protocol())) {
-    return WebMixedContent::ContextType::OptionallyBlockable;
+    return WebMixedContentContextType::OptionallyBlockable;
   }
 
   bool strictMixedContentCheckingForPlugin =
diff --git a/third_party/WebKit/Source/core/loader/MixedContentChecker.h b/third_party/WebKit/Source/core/loader/MixedContentChecker.h
index b1100e79..33e8a1a8 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentChecker.h
+++ b/third_party/WebKit/Source/core/loader/MixedContentChecker.h
@@ -35,7 +35,7 @@
 #include "core/CoreExport.h"
 #include "platform/heap/Handle.h"
 #include "platform/network/ResourceRequest.h"
-#include "public/platform/WebMixedContent.h"
+#include "public/platform/WebMixedContentContextType.h"
 #include "public/platform/WebURLRequest.h"
 #include "wtf/text/WTFString.h"
 
@@ -80,7 +80,7 @@
   static void checkMixedPrivatePublic(LocalFrame*,
                                       const AtomicString& resourceIPAddress);
 
-  static WebMixedContent::ContextType contextTypeForInspector(
+  static WebMixedContentContextType contextTypeForInspector(
       LocalFrame*,
       const ResourceRequest&);
 
diff --git a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
index 3323b62..831dfa1 100644
--- a/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
+++ b/third_party/WebKit/Source/core/loader/MixedContentCheckerTest.cpp
@@ -10,6 +10,8 @@
 #include "platform/network/ResourceResponse.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
+#include "public/platform/WebMixedContent.h"
+#include "public/platform/WebMixedContentContextType.h"
 #include "testing/gmock/include/gmock/gmock-generated-function-mockers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/RefPtr.h"
@@ -68,20 +70,20 @@
   ResourceRequest notMixedContent("https://example.test/foo.jpg");
   notMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary);
   notMixedContent.setRequestContext(WebURLRequest::RequestContextScript);
-  EXPECT_EQ(WebMixedContent::ContextType::NotMixedContent,
+  EXPECT_EQ(WebMixedContentContextType::NotMixedContent,
             MixedContentChecker::contextTypeForInspector(
                 &dummyPageHolder->frame(), notMixedContent));
 
   dummyPageHolder->frame().document()->setSecurityOrigin(
       SecurityOrigin::createFromString("https://example.test"));
-  EXPECT_EQ(WebMixedContent::ContextType::NotMixedContent,
+  EXPECT_EQ(WebMixedContentContextType::NotMixedContent,
             MixedContentChecker::contextTypeForInspector(
                 &dummyPageHolder->frame(), notMixedContent));
 
   ResourceRequest blockableMixedContent("http://example.test/foo.jpg");
   blockableMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary);
   blockableMixedContent.setRequestContext(WebURLRequest::RequestContextScript);
-  EXPECT_EQ(WebMixedContent::ContextType::Blockable,
+  EXPECT_EQ(WebMixedContentContextType::Blockable,
             MixedContentChecker::contextTypeForInspector(
                 &dummyPageHolder->frame(), blockableMixedContent));
 
@@ -89,7 +91,7 @@
       "http://example.test/foo.jpg");
   blockableMixedContent.setFrameType(WebURLRequest::FrameTypeAuxiliary);
   blockableMixedContent.setRequestContext(WebURLRequest::RequestContextImage);
-  EXPECT_EQ(WebMixedContent::ContextType::OptionallyBlockable,
+  EXPECT_EQ(WebMixedContentContextType::OptionallyBlockable,
             MixedContentChecker::contextTypeForInspector(
                 &dummyPageHolder->frame(), blockableMixedContent));
 }
@@ -126,7 +128,7 @@
   WebURLRequest::RequestContext requestContext =
       WebURLRequest::RequestContextImage;
   ASSERT_EQ(
-      WebMixedContent::ContextType::OptionallyBlockable,
+      WebMixedContentContextType::OptionallyBlockable,
       WebMixedContent::contextTypeFromRequestContext(
           requestContext, dummyPageHolder->frame()
                               .settings()
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
index a1028420..848d763 100644
--- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
@@ -192,6 +192,14 @@
                           ? cssPropertyID(attributeName().localName())
                           : CSSPropertyInvalid;
   }
+  // Blacklist <script> targets here for now to prevent unpleasantries. This
+  // also disallows the perfectly "valid" animation of 'className' on said
+  // element. If SVGScriptElement.href is transitioned off of SVGAnimatedHref,
+  // this can be removed.
+  if (isSVGScriptElement(*targetElement())) {
+    m_type = AnimatedUnknown;
+    m_cssPropertyId = CSSPropertyInvalid;
+  }
   DCHECK(m_type != AnimatedPoint && m_type != AnimatedStringList &&
          m_type != AnimatedTransform && m_type != AnimatedTransformList);
 }
diff --git a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
index 25dbc97..936f08e6 100644
--- a/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGScriptElement.cpp
@@ -22,6 +22,7 @@
 
 #include "bindings/core/v8/ScriptEventListener.h"
 #include "core/HTMLNames.h"
+#include "core/XLinkNames.h"
 #include "core/dom/Attribute.h"
 #include "core/dom/ScriptLoader.h"
 #include "core/dom/ScriptRunner.h"
@@ -146,9 +147,9 @@
 
 #if DCHECK_IS_ON()
 bool SVGScriptElement::isAnimatableAttribute(const QualifiedName& name) const {
-  if (name == SVGNames::typeAttr)
+  if (name == SVGNames::typeAttr || name == SVGNames::hrefAttr ||
+      name == XLinkNames::hrefAttr)
     return false;
-
   return SVGElement::isAnimatableAttribute(name);
 }
 #endif
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index 65b3bdc..337e37c 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -1041,7 +1041,9 @@
     if (m_upload)
       request.setReportUploadProgress(true);
 
-    DCHECK(!m_loader);
+    // TODO(yhirano): Turn this CHECK into DCHECK once https://crbug.com/667254
+    // is fixed.
+    CHECK(!m_loader);
     DCHECK(m_sendFlag);
     m_loader = ThreadableLoader::create(executionContext, this, options,
                                         resourceLoaderOptions);
@@ -1050,6 +1052,8 @@
     return;
   }
 
+  // TODO(yhirano): Remove this CHECK once https://crbug.com/667254 is fixed.
+  CHECK(!m_loader);
   // Use count for XHR synchronous requests.
   UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
   ThreadableLoader::loadResourceSynchronously(executionContext, request, *this,
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp
index 064a51a..ad9c003 100644
--- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp
+++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.cpp
@@ -40,7 +40,8 @@
 ScreenOrientationControllerImpl::ScreenOrientationControllerImpl(
     LocalFrame& frame,
     WebScreenOrientationClient* client)
-    : ContextLifecycleObserver(frame.document()),
+    : ScreenOrientationController(frame),
+      ContextLifecycleObserver(frame.document()),
       PlatformEventController(frame.page()),
       m_client(client),
       m_dispatchEventTimer(
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h
index 7fa4373..8863622b 100644
--- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h
+++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationControllerImpl.h
@@ -21,8 +21,7 @@
 class WebScreenOrientationClient;
 
 class MODULES_EXPORT ScreenOrientationControllerImpl final
-    : public GarbageCollectedFinalized<ScreenOrientationControllerImpl>,
-      public ScreenOrientationController,
+    : public ScreenOrientationController,
       public ContextLifecycleObserver,
       public PlatformEventController {
   USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationControllerImpl);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
index ab72ab8..4ae77b7 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
@@ -517,4 +517,11 @@
   return this;
 }
 
+AudioParam* AudioParam::cancelValuesAndHoldAtTime(
+    double startTime,
+    ExceptionState& exceptionState) {
+  handler().timeline().cancelValuesAndHoldAtTime(startTime, exceptionState);
+  return this;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.h b/third_party/WebKit/Source/modules/webaudio/AudioParam.h
index f52ed1f..cf2f761 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParam.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.h
@@ -251,6 +251,7 @@
                                   double duration,
                                   ExceptionState&);
   AudioParam* cancelScheduledValues(double startTime, ExceptionState&);
+  AudioParam* cancelValuesAndHoldAtTime(double startTime, ExceptionState&);
 
  private:
   AudioParam(BaseAudioContext&,
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.idl b/third_party/WebKit/Source/modules/webaudio/AudioParam.idl
index 1fa7537..1cc12ba 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParam.idl
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.idl
@@ -50,4 +50,7 @@
     // Cancels all scheduled parameter changes with times greater than or equal to startTime.
     [RaisesException, MeasureAs=AudioParamCancelScheduledValues] AudioParam cancelScheduledValues(double startTime);
 
+    // Cancel scheduled parameter changes and hold the last value
+    [RaisesException] AudioParam cancelValuesAndHoldAtTime(double startTime);
+
 };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
index 5a5448d9..dbb6a1b8 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp
@@ -29,6 +29,7 @@
 #include "platform/audio/AudioUtilities.h"
 #include "wtf/CPU.h"
 #include "wtf/MathExtras.h"
+#include "wtf/PtrUtil.h"
 #include <algorithm>
 
 #if CPU(X86) || CPU(X86_64)
@@ -106,6 +107,9 @@
       args = "..., " + String::number(event.time(), 16) + ", " +
              String::number(event.duration(), 16);
       break;
+    case ParamEvent::CancelValues:
+    // Fall through; we should never have to print out the internal
+    // CancelValues event.
     case ParamEvent::LastType:
       ASSERT_NOT_REACHED();
       break;
@@ -114,54 +118,77 @@
   return s + "(" + args + ")";
 }
 
-AudioParamTimeline::ParamEvent::ParamEvent(Type type,
-                                           float value,
-                                           double time,
-                                           double timeConstant,
+// Computes the value of a linear ramp event at time t with the given event
+// parameters.
+float AudioParamTimeline::linearRampAtTime(double t,
+                                           float value1,
+                                           double time1,
+                                           float value2,
+                                           double time2) {
+  return value1 + (value2 - value1) * (t - time1) / (time2 - time1);
+}
+
+// Computes the value of an exponential ramp event at time t with the given
+// event parameters.
+float AudioParamTimeline::exponentialRampAtTime(double t,
+                                                float value1,
+                                                double time1,
+                                                float value2,
+                                                double time2) {
+  return value1 * pow(value2 / value1, (t - time1) / (time2 - time1));
+}
+
+// Compute the value of a set target event at time t with the given event
+// parameters.
+float AudioParamTimeline::targetValueAtTime(double t,
+                                            float value1,
+                                            double time1,
+                                            float value2,
+                                            float timeConstant) {
+  return value2 + (value1 - value2) * exp(-(t - time1) / timeConstant);
+}
+
+// Compute the value of a set curve event at time t with the given event
+// parameters.
+float AudioParamTimeline::valueCurveAtTime(double t,
+                                           double time1,
                                            double duration,
-                                           const DOMFloat32Array* curve,
-                                           float initialValue,
-                                           double callTime)
-    : m_type(type),
-      m_value(value),
-      m_time(time),
-      m_timeConstant(timeConstant),
-      m_duration(duration),
-      m_initialValue(initialValue),
-      m_callTime(callTime),
-      m_needsTimeClampCheck(true) {
-  if (curve) {
-    // Copy the curve data
-    unsigned curveLength = curve->length();
-    m_curve.resize(curveLength);
-    memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float));
-  }
+                                           const float* curveData,
+                                           unsigned curveLength) {
+  double curveIndex = (curveLength - 1) / duration * (t - time1);
+  unsigned k = std::min(static_cast<unsigned>(curveIndex), curveLength - 1);
+  unsigned k1 = std::min(k + 1, curveLength - 1);
+  float c0 = curveData[k];
+  float c1 = curveData[k1];
+  float delta = std::min(curveIndex - k, 1.0);
+
+  return c0 + (c1 - c0) * delta;
 }
 
-AudioParamTimeline::ParamEvent
+std::unique_ptr<AudioParamTimeline::ParamEvent>
 AudioParamTimeline::ParamEvent::createSetValueEvent(float value, double time) {
-  return ParamEvent(ParamEvent::SetValue, value, time, 0, 0, nullptr);
+  return WTF::wrapUnique(new ParamEvent(ParamEvent::SetValue, value, time));
 }
 
-AudioParamTimeline::ParamEvent
+std::unique_ptr<AudioParamTimeline::ParamEvent>
 AudioParamTimeline::ParamEvent::createLinearRampEvent(float value,
                                                       double time,
                                                       float initialValue,
                                                       double callTime) {
-  return ParamEvent(ParamEvent::LinearRampToValue, value, time, 0, 0, nullptr,
-                    initialValue, callTime);
+  return WTF::wrapUnique(new ParamEvent(ParamEvent::LinearRampToValue, value,
+                                        time, initialValue, callTime));
 }
 
-AudioParamTimeline::ParamEvent
+std::unique_ptr<AudioParamTimeline::ParamEvent>
 AudioParamTimeline::ParamEvent::createExponentialRampEvent(float value,
                                                            double time,
                                                            float initialValue,
                                                            double callTime) {
-  return ParamEvent(ParamEvent::ExponentialRampToValue, value, time, 0, 0,
-                    nullptr, initialValue, callTime);
+  return WTF::wrapUnique(new ParamEvent(ParamEvent::ExponentialRampToValue,
+                                        value, time, initialValue, callTime));
 }
 
-AudioParamTimeline::ParamEvent
+std::unique_ptr<AudioParamTimeline::ParamEvent>
 AudioParamTimeline::ParamEvent::createSetTargetEvent(float value,
                                                      double time,
                                                      double timeConstant) {
@@ -169,16 +196,211 @@
   // returns NaN or Infinity due to division by zero.  The caller
   // should have converted this to a SetValueEvent.
   DCHECK_NE(timeConstant, 0);
-  return ParamEvent(ParamEvent::SetTarget, value, time, timeConstant, 0,
-                    nullptr);
+  return WTF::wrapUnique(
+      new ParamEvent(ParamEvent::SetTarget, value, time, timeConstant));
 }
 
-AudioParamTimeline::ParamEvent
+std::unique_ptr<AudioParamTimeline::ParamEvent>
 AudioParamTimeline::ParamEvent::createSetValueCurveEvent(
     const DOMFloat32Array* curve,
     double time,
     double duration) {
-  return ParamEvent(ParamEvent::SetValueCurve, 0, time, 0, duration, curve);
+  double curvePoints = (curve->length() - 1) / duration;
+  float endValue = curve->data()[curve->length() - 1];
+
+  return WTF::wrapUnique(new ParamEvent(
+      ParamEvent::SetValueCurve, time, duration, curve, curvePoints, endValue));
+}
+
+std::unique_ptr<AudioParamTimeline::ParamEvent>
+AudioParamTimeline::ParamEvent::createCancelValuesEvent(
+    double time,
+    std::unique_ptr<ParamEvent> savedEvent) {
+  if (savedEvent) {
+    // The savedEvent can only have certain event types.  Verify that.
+    ParamEvent::Type savedType = savedEvent->getType();
+
+    DCHECK_NE(savedType, ParamEvent::LastType);
+    DCHECK(savedType == ParamEvent::LinearRampToValue ||
+           savedType == ParamEvent::ExponentialRampToValue ||
+           savedType == ParamEvent::SetValueCurve);
+  }
+
+  return WTF::wrapUnique(
+      new ParamEvent(ParamEvent::CancelValues, time, std::move(savedEvent)));
+}
+
+std::unique_ptr<AudioParamTimeline::ParamEvent>
+AudioParamTimeline::ParamEvent::createGeneralEvent(
+    Type type,
+    float value,
+    double time,
+    float initialValue,
+    double callTime,
+    double timeConstant,
+    double duration,
+    Vector<float>& curve,
+    double curvePointsPerSecond,
+    float curveEndValue,
+    std::unique_ptr<ParamEvent> savedEvent) {
+  return WTF::wrapUnique(new ParamEvent(
+      type, value, time, initialValue, callTime, timeConstant, duration, curve,
+      curvePointsPerSecond, curveEndValue, std::move(savedEvent)));
+}
+
+AudioParamTimeline::ParamEvent* AudioParamTimeline::ParamEvent::savedEvent()
+    const {
+  DCHECK_EQ(getType(), ParamEvent::CancelValues);
+  return m_savedEvent.get();
+}
+
+bool AudioParamTimeline::ParamEvent::hasDefaultCancelledValue() const {
+  DCHECK_EQ(getType(), ParamEvent::CancelValues);
+  return m_hasDefaultCancelledValue;
+}
+
+void AudioParamTimeline::ParamEvent::setCancelledValue(float value) {
+  DCHECK_EQ(getType(), ParamEvent::CancelValues);
+  m_value = value;
+  m_hasDefaultCancelledValue = true;
+}
+
+// General event
+AudioParamTimeline::ParamEvent::ParamEvent(
+    ParamEvent::Type type,
+    float value,
+    double time,
+    float initialValue,
+    double callTime,
+    double timeConstant,
+    double duration,
+    Vector<float>& curve,
+    double curvePointsPerSecond,
+    float curveEndValue,
+    std::unique_ptr<ParamEvent> savedEvent)
+    : m_type(type),
+      m_value(value),
+      m_time(time),
+      m_initialValue(initialValue),
+      m_callTime(callTime),
+      m_timeConstant(timeConstant),
+      m_duration(duration),
+      m_curvePointsPerSecond(curvePointsPerSecond),
+      m_curveEndValue(curveEndValue),
+      m_savedEvent(std::move(savedEvent)),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  m_curve = curve;
+}
+
+// Create simplest event needing just a value and time, like setValueAtTime
+AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
+                                           float value,
+                                           double time)
+    : m_type(type),
+      m_value(value),
+      m_time(time),
+      m_initialValue(0),
+      m_callTime(0),
+      m_timeConstant(0),
+      m_duration(0),
+      m_curvePointsPerSecond(0),
+      m_curveEndValue(0),
+      m_savedEvent(nullptr),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  DCHECK_EQ(type, ParamEvent::SetValue);
+}
+
+// Create a linear or exponential ramp that requires an initial value and
+// time in case
+// there is no actual event that preceeds this event.
+AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
+                                           float value,
+                                           double time,
+                                           float initialValue,
+                                           double callTime)
+    : m_type(type),
+      m_value(value),
+      m_time(time),
+      m_initialValue(initialValue),
+      m_callTime(callTime),
+      m_timeConstant(0),
+      m_duration(0),
+      m_curvePointsPerSecond(0),
+      m_curveEndValue(0),
+      m_savedEvent(nullptr),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  DCHECK(type == ParamEvent::LinearRampToValue ||
+         type == ParamEvent::ExponentialRampToValue);
+}
+
+// Create an event needing a time constant (setTargetAtTime)
+AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
+                                           float value,
+                                           double time,
+                                           double timeConstant)
+    : m_type(type),
+      m_value(value),
+      m_time(time),
+      m_initialValue(0),
+      m_callTime(0),
+      m_timeConstant(timeConstant),
+      m_duration(0),
+      m_curvePointsPerSecond(0),
+      m_curveEndValue(0),
+      m_savedEvent(nullptr),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  DCHECK_EQ(type, ParamEvent::SetTarget);
+}
+
+// Create a setValueCurve event
+AudioParamTimeline::ParamEvent::ParamEvent(ParamEvent::Type type,
+                                           double time,
+                                           double duration,
+                                           const DOMFloat32Array* curve,
+                                           double curvePointsPerSecond,
+                                           float curveEndValue)
+    : m_type(type),
+      m_value(0),
+      m_time(time),
+      m_initialValue(0),
+      m_callTime(0),
+      m_timeConstant(0),
+      m_duration(duration),
+      m_curvePointsPerSecond(curvePointsPerSecond),
+      m_curveEndValue(curveEndValue),
+      m_savedEvent(nullptr),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  DCHECK_EQ(type, ParamEvent::SetValueCurve);
+  if (curve) {
+    unsigned curveLength = curve->length();
+    m_curve.resize(curve->length());
+    memcpy(m_curve.data(), curve->data(), curveLength * sizeof(float));
+  }
+}
+
+// Create CancelValues event
+AudioParamTimeline::ParamEvent::ParamEvent(
+    ParamEvent::Type type,
+    double time,
+    std::unique_ptr<ParamEvent> savedEvent)
+    : m_type(type),
+      m_value(0),
+      m_time(time),
+      m_initialValue(0),
+      m_callTime(0),
+      m_timeConstant(0),
+      m_duration(0),
+      m_curvePointsPerSecond(0),
+      m_curveEndValue(0),
+      m_savedEvent(std::move(savedEvent)),
+      m_needsTimeClampCheck(true),
+      m_hasDefaultCancelledValue(false) {
+  DCHECK_EQ(type, ParamEvent::CancelValues);
 }
 
 void AudioParamTimeline::setValueAtTime(float value,
@@ -189,6 +411,7 @@
   if (!isNonNegativeAudioParamTime(time, exceptionState))
     return;
 
+  MutexLocker locker(m_eventsLock);
   insertEvent(ParamEvent::createSetValueEvent(value, time), exceptionState);
 }
 
@@ -203,6 +426,7 @@
   if (!isNonNegativeAudioParamTime(time, exceptionState))
     return;
 
+  MutexLocker locker(m_eventsLock);
   insertEvent(
       ParamEvent::createLinearRampEvent(value, time, initialValue, callTime),
       exceptionState);
@@ -229,6 +453,7 @@
     return;
   }
 
+  MutexLocker locker(m_eventsLock);
   insertEvent(ParamEvent::createExponentialRampEvent(value, time, initialValue,
                                                      callTime),
               exceptionState);
@@ -245,6 +470,8 @@
                                    "Time constant"))
     return;
 
+  MutexLocker locker(m_eventsLock);
+
   // If timeConstant = 0, we instantly jump to the target value, so
   // insert a SetValueEvent instead of SetTargetEvent.
   if (timeConstant == 0) {
@@ -273,6 +500,7 @@
     return;
   }
 
+  MutexLocker locker(m_eventsLock);
   insertEvent(ParamEvent::createSetValueCurveEvent(curve, time, duration),
               exceptionState);
 
@@ -284,73 +512,73 @@
               exceptionState);
 }
 
-void AudioParamTimeline::insertEvent(const ParamEvent& event,
+void AudioParamTimeline::insertEvent(std::unique_ptr<ParamEvent> event,
                                      ExceptionState& exceptionState) {
   DCHECK(isMainThread());
 
   // Sanity check the event. Be super careful we're not getting infected with
   // NaN or Inf. These should have been handled by the caller.
-  bool isValid = event.getType() < ParamEvent::LastType &&
-                 std::isfinite(event.value()) && std::isfinite(event.time()) &&
-                 std::isfinite(event.timeConstant()) &&
-                 std::isfinite(event.duration()) && event.duration() >= 0;
+  bool isValid = event->getType() < ParamEvent::LastType &&
+                 std::isfinite(event->value()) &&
+                 std::isfinite(event->time()) &&
+                 std::isfinite(event->timeConstant()) &&
+                 std::isfinite(event->duration()) && event->duration() >= 0;
 
   DCHECK(isValid);
   if (!isValid)
     return;
 
-  MutexLocker locker(m_eventsLock);
-
   unsigned i = 0;
-  double insertTime = event.time();
+  double insertTime = event->time();
 
   if (!m_events.size() &&
-      (event.getType() == ParamEvent::LinearRampToValue ||
-       event.getType() == ParamEvent::ExponentialRampToValue)) {
+      (event->getType() == ParamEvent::LinearRampToValue ||
+       event->getType() == ParamEvent::ExponentialRampToValue)) {
     // There are no events preceding these ramps.  Insert a new setValueAtTime
     // event to set the starting point for these events.
     m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent(
-                           event.initialValue(), event.callTime()));
+                           event->initialValue(), event->callTime()));
   }
 
   for (i = 0; i < m_events.size(); ++i) {
-    if (event.getType() == ParamEvent::SetValueCurve) {
+    if (event->getType() == ParamEvent::SetValueCurve) {
       // If this event is a SetValueCurve, make sure it doesn't overlap any
       // existing event. It's ok if the SetValueCurve starts at the same time as
       // the end of some other duration.
-      double endTime = event.time() + event.duration();
-      if (m_events[i].time() > event.time() && m_events[i].time() < endTime) {
+      double endTime = event->time() + event->duration();
+      if (m_events[i]->time() > event->time() &&
+          m_events[i]->time() < endTime) {
         exceptionState.throwDOMException(
             NotSupportedError,
-            eventToString(event) + " overlaps " + eventToString(m_events[i]));
+            eventToString(*event) + " overlaps " + eventToString(*m_events[i]));
         return;
       }
     } else {
       // Otherwise, make sure this event doesn't overlap any existing
       // SetValueCurve event.
-      if (m_events[i].getType() == ParamEvent::SetValueCurve) {
-        double endTime = m_events[i].time() + m_events[i].duration();
-        if (event.time() >= m_events[i].time() && event.time() < endTime) {
+      if (m_events[i]->getType() == ParamEvent::SetValueCurve) {
+        double endTime = m_events[i]->time() + m_events[i]->duration();
+        if (event->time() >= m_events[i]->time() && event->time() < endTime) {
           exceptionState.throwDOMException(
-              NotSupportedError,
-              eventToString(event) + " overlaps " + eventToString(m_events[i]));
+              NotSupportedError, eventToString(*event) + " overlaps " +
+                                     eventToString(*m_events[i]));
           return;
         }
       }
     }
 
     // Overwrite same event type and time.
-    if (m_events[i].time() == insertTime &&
-        m_events[i].getType() == event.getType()) {
-      m_events[i] = event;
+    if (m_events[i]->time() == insertTime &&
+        m_events[i]->getType() == event->getType()) {
+      m_events[i] = std::move(event);
       return;
     }
 
-    if (m_events[i].time() > insertTime)
+    if (m_events[i]->time() > insertTime)
       break;
   }
 
-  m_events.insert(i, event);
+  m_events.insert(i, std::move(event));
 }
 
 bool AudioParamTimeline::hasValues() const {
@@ -383,13 +611,130 @@
 
   // Remove all events starting at startTime.
   for (unsigned i = 0; i < m_events.size(); ++i) {
-    if (m_events[i].time() >= startTime) {
+    if (m_events[i]->time() >= startTime) {
       m_events.remove(i, m_events.size() - i);
       break;
     }
   }
 }
 
+void AudioParamTimeline::cancelValuesAndHoldAtTime(
+    double cancelTime,
+    ExceptionState& exceptionState) {
+  DCHECK(isMainThread());
+
+  if (!isNonNegativeAudioParamTime(cancelTime, exceptionState))
+    return;
+
+  MutexLocker locker(m_eventsLock);
+
+  unsigned i;
+  // Find the first event at or just past cancelTime.
+  for (i = 0; i < m_events.size(); ++i) {
+    if (m_events[i]->time() > cancelTime) {
+      break;
+    }
+  }
+
+  // The event that is being cancelled.  This is the event just past
+  // cancelTime, if any.
+  unsigned cancelledEventIndex = i;
+
+  // If the event just before cancelTime is a SetTarget or SetValueCurve
+  // event, we need to handle that event specially instead of the event after.
+  if (i > 0 && ((m_events[i - 1]->getType() == ParamEvent::SetTarget) ||
+                (m_events[i - 1]->getType() == ParamEvent::SetValueCurve))) {
+    cancelledEventIndex = i - 1;
+  } else if (i >= m_events.size()) {
+    // If there were no events occurring after |cancelTime| (and the
+    // previous event is not SetTarget or SetValueCurve, we're done.
+    return;
+  }
+
+  // cancelledEvent is the event that is being cancelled.
+  ParamEvent* cancelledEvent = m_events[cancelledEventIndex].get();
+  ParamEvent::Type eventType = cancelledEvent->getType();
+
+  // New event to be inserted, if any, and a SetValueEvent if needed.
+  std::unique_ptr<ParamEvent> newEvent = nullptr;
+  std::unique_ptr<ParamEvent> newSetValueEvent = nullptr;
+
+  switch (eventType) {
+    case ParamEvent::LinearRampToValue:
+    case ParamEvent::ExponentialRampToValue: {
+      // For these events we need to remember the parameters of the event
+      // for a CancelValues event so that we can properly cancel the event
+      // and hold the value.
+      std::unique_ptr<ParamEvent> savedEvent = ParamEvent::createGeneralEvent(
+          eventType, cancelledEvent->value(), cancelledEvent->time(),
+          cancelledEvent->initialValue(), cancelledEvent->callTime(),
+          cancelledEvent->timeConstant(), cancelledEvent->duration(),
+          cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(),
+          cancelledEvent->curveEndValue(), nullptr);
+
+      newEvent = ParamEvent::createCancelValuesEvent(cancelTime,
+                                                     std::move(savedEvent));
+    } break;
+    case ParamEvent::SetTarget: {
+      // Don't want to remove the SetTarget event, so bump the index.  But
+      // we do want to insert a cancelEvent so that we stop this
+      // automation and hold the value when we get there.
+      ++cancelledEventIndex;
+
+      newEvent = ParamEvent::createCancelValuesEvent(cancelTime, nullptr);
+    } break;
+    case ParamEvent::SetValueCurve: {
+      double newDuration = cancelTime - cancelledEvent->time();
+
+      if (cancelTime > cancelledEvent->time() + cancelledEvent->duration()) {
+        // If the cancellation time is past the end of the curve,
+        // there's nothing to do except remove the following events.
+        ++cancelledEventIndex;
+      } else {
+        // Cancellation time is in the middle of the curve.  Therefore,
+        // create a new SetValueCurve event with the appropriate new
+        // parameters to cancel this event properly.  Since it's illegal
+        // to insert any event within a SetValueCurve event, we can
+        // compute the new end value now instead of doing when running
+        // the timeline.
+        float endValue = valueCurveAtTime(
+            cancelTime, cancelledEvent->time(), cancelledEvent->duration(),
+            cancelledEvent->curve().data(), cancelledEvent->curve().size());
+
+        // Replace the existing SetValueCurve with this new one that is
+        // identical except for the duration.
+        newEvent = ParamEvent::createGeneralEvent(
+            eventType, cancelledEvent->value(), cancelledEvent->time(),
+            cancelledEvent->initialValue(), cancelledEvent->callTime(),
+            cancelledEvent->timeConstant(), newDuration,
+            cancelledEvent->curve(), cancelledEvent->curvePointsPerSecond(),
+            endValue, nullptr);
+
+        newSetValueEvent = ParamEvent::createSetValueEvent(
+            endValue, cancelledEvent->time() + newDuration);
+      }
+    } break;
+    case ParamEvent::SetValue:
+    case ParamEvent::CancelValues:
+      // Nothing needs to be done for a SetValue or CancelValues event.
+      break;
+    case ParamEvent::LastType:
+      NOTREACHED();
+      break;
+  }
+
+  // Now remove all the following events from the timeline.
+  if (cancelledEventIndex < m_events.size())
+    m_events.remove(cancelledEventIndex, m_events.size() - cancelledEventIndex);
+
+  // Insert the new event, if any.
+  if (newEvent) {
+    insertEvent(std::move(newEvent), exceptionState);
+    if (newSetValueEvent)
+      insertEvent(std::move(newSetValueEvent), exceptionState);
+  }
+}
+
 float AudioParamTimeline::valueForContextTime(
     AudioDestinationHandler& audioDestination,
     float defaultValue,
@@ -399,7 +744,7 @@
   {
     MutexTryLocker tryLocker(m_eventsLock);
     if (!tryLocker.locked() || !m_events.size() ||
-        audioDestination.currentTime() < m_events[0].time()) {
+        audioDestination.currentTime() < m_events[0]->time()) {
       hasValue = false;
       return defaultValue;
     }
@@ -462,7 +807,7 @@
 
   // Return default value if there are no events matching the desired time
   // range.
-  if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) {
+  if (!m_events.size() || (endFrame / sampleRate <= m_events[0]->time())) {
     for (unsigned i = 0; i < numberOfValues; ++i)
       values[i] = defaultValue;
     return defaultValue;
@@ -477,20 +822,20 @@
     // Look at all the events in the timeline and check to see if any needs
     // to clamp the start time to the current time.
     for (int k = 0; k < numberOfEvents; ++k) {
-      ParamEvent& event = m_events[k];
+      ParamEvent* event = m_events[k].get();
 
       // We're examining the event for the first time and the event time is
       // in the past so clamp the event time to the current time (start of
       // the rendering quantum).
-      if (event.needsTimeClampCheck()) {
-        if (event.time() < currentTime) {
-          event.setTime(currentTime);
+      if (event->needsTimeClampCheck()) {
+        if (event->time() < currentTime) {
+          event->setTime(currentTime);
           clampedSomeEventTime = true;
         }
 
         // In all cases, we can clear the flag because the event is either
         // in the future, or we've already checked it (just now).
-        event.clearTimeClampCheck();
+        event->clearTimeClampCheck();
       }
     }
 
@@ -503,9 +848,9 @@
     }
 
     // Optimize the case where the last event is in the past.
-    ParamEvent& lastEvent = m_events[m_events.size() - 1];
-    ParamEvent::Type lastEventType = lastEvent.getType();
-    double lastEventTime = lastEvent.time();
+    ParamEvent* lastEvent = m_events[m_events.size() - 1].get();
+    ParamEvent::Type lastEventType = lastEvent->getType();
+    double lastEventTime = lastEvent->time();
 
     // If the last event is in the past and the event has ended, then we can
     // just propagate the same value.  Except for SetTarget which lasts
@@ -531,7 +876,7 @@
 
   // If first event is after startFrame then fill initial part of values buffer
   // with defaultValue until we reach the first event time.
-  double firstEventTime = m_events[0].time();
+  double firstEventTime = m_events[0]->time();
   if (firstEventTime > startFrame / sampleRate) {
     // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the
     // bound from the firstEventTime.
@@ -555,8 +900,8 @@
   // stopping when we've rendered all the requested values.
   int lastSkippedEventIndex = 0;
   for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) {
-    ParamEvent& event = m_events[i];
-    ParamEvent* nextEvent = i < numberOfEvents - 1 ? &(m_events[i + 1]) : 0;
+    ParamEvent* event = m_events[i].get();
+    ParamEvent* nextEvent = i < numberOfEvents - 1 ? m_events[i + 1].get() : 0;
 
     // Wait until we get a more recent event.
     //
@@ -579,12 +924,12 @@
       // and not applied, which is wrong.  Other events don't have this problem.
       // (Because currentFrame is unsigned, we do the time check in this funny,
       // but equivalent way.)
-      double eventFrame = event.time() * sampleRate;
+      double eventFrame = event->time() * sampleRate;
 
       // Condition is currentFrame - 1 < eventFrame <= currentFrame, but
       // currentFrame is unsigned and could be 0, so use
       // currentFrame < eventFrame + 1 instead.
-      if (!((event.getType() == ParamEvent::SetValue &&
+      if (!((event->getType() == ParamEvent::SetValue &&
              (eventFrame <= currentFrame) &&
              (currentFrame < eventFrame + 1)))) {
         // This is not the special SetValue event case, and nextEvent is
@@ -605,7 +950,7 @@
     // LinearRampToValue or ExponentialRampToValue, special handling is needed.
     // In this case, the linear and exponential ramp should start at wherever
     // the SetTarget processing has reached.
-    if (event.getType() == ParamEvent::SetTarget &&
+    if (event->getType() == ParamEvent::SetTarget &&
         (nextEventType == ParamEvent::LinearRampToValue ||
          nextEventType == ParamEvent::ExponentialRampToValue)) {
       // Replace the SetTarget with a SetValue to set the starting time and
@@ -627,36 +972,111 @@
       //    -2 <= 2 * Fs * t0 - 2 * f <= 0
       //    -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1
       //     abs(2 * Fs * t0 - 2 * f + 1) <= 1
-      if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) {
+      if (fabs(2 * sampleRate * event->time() - 2 * currentFrame + 1) <= 1) {
         // SetTarget is starting somewhere between currentFrame - 1 and
         // currentFrame. Compute the value the SetTarget would have at the
         // currentFrame.
-        value = event.value() +
-                (value - event.value()) *
-                    exp(-(currentFrame / sampleRate - event.time()) /
-                        event.timeConstant());
+        value = event->value() +
+                (value - event->value()) *
+                    exp(-(currentFrame / sampleRate - event->time()) /
+                        event->timeConstant());
       } else {
         // SetTarget has already started.  Update |value| one frame because it's
         // the value from the previous frame.
         float discreteTimeConstant = static_cast<float>(
             AudioUtilities::discreteTimeConstantForSampleRate(
-                event.timeConstant(), controlRate));
-        value += (event.value() - value) * discreteTimeConstant;
+                event->timeConstant(), controlRate));
+        value += (event->value() - value) * discreteTimeConstant;
       }
 
       // Insert a SetValueEvent to mark the starting value and time.
       // Clear the clamp check because this doesn't need it.
       m_events[i] =
           ParamEvent::createSetValueEvent(value, currentFrame / sampleRate);
-      m_events[i].clearTimeClampCheck();
+      m_events[i]->clearTimeClampCheck();
+
+      // Update our pointer to the current event because we just changed it.
+      event = m_events[i].get();
     }
 
-    float value1 = event.value();
-    double time1 = event.time();
+    float value1 = event->value();
+    double time1 = event->time();
 
     float value2 = nextEvent ? nextEvent->value() : value1;
     double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1;
 
+    // Check to see if an event was cancelled.
+    if (nextEventType == ParamEvent::CancelValues) {
+      switch (event->getType()) {
+        case ParamEvent::LinearRampToValue:
+        case ParamEvent::ExponentialRampToValue:
+        case ParamEvent::SetValue: {
+          // These three events potentially establish a starting value for
+          // the following event, so we need to examine the cancelled
+          // event to see what to do.
+          const ParamEvent* savedEvent = nextEvent->savedEvent();
+
+          // Update the end time and type to pretend that we're running
+          // this saved event type.
+          time2 = nextEvent->time();
+          nextEventType = savedEvent->getType();
+
+          if (nextEvent->hasDefaultCancelledValue()) {
+            // We've already established a value for the cancelled
+            // event, so just return it.
+            value2 = nextEvent->value();
+          } else {
+            // If the next event would have been a LinearRamp or
+            // ExponentialRamp, we need to compute a new end value for
+            // the event so that the curve works continues as if it were
+            // not cancelled.
+            switch (savedEvent->getType()) {
+              case ParamEvent::LinearRampToValue:
+                value2 =
+                    linearRampAtTime(nextEvent->time(), value1, time1,
+                                     savedEvent->value(), savedEvent->time());
+                break;
+              case ParamEvent::ExponentialRampToValue:
+                value2 = exponentialRampAtTime(nextEvent->time(), value1, time1,
+                                               savedEvent->value(),
+                                               savedEvent->time());
+                break;
+              case ParamEvent::SetValueCurve:
+              case ParamEvent::SetValue:
+              case ParamEvent::SetTarget:
+              case ParamEvent::CancelValues:
+                // These cannot be possible types for the saved event
+                // because they can't be created.
+                // createCancelValuesEvent doesn't allow them (SetValue,
+                // SetTarget, CancelValues) or cancelScheduledValues()
+                // doesn't create such an event (SetValueCurve).
+                NOTREACHED();
+                break;
+              case ParamEvent::LastType:
+                // Illegal event type.
+                NOTREACHED();
+                break;
+            }
+
+            // Cache the new value so we don't keep computing it over and over.
+            nextEvent->setCancelledValue(value2);
+          }
+        } break;
+        case ParamEvent::SetValueCurve:
+          // Everything needed for this was handled when cancelling was
+          // done.
+          break;
+        case ParamEvent::SetTarget:
+        case ParamEvent::CancelValues:
+          // Nothing special needs to be done for SetTarget or
+          // CancelValues followed by CancelValues.
+          break;
+        case ParamEvent::LastType:
+          NOTREACHED();
+          break;
+      }
+    }
+
     DCHECK_GE(time2, time1);
     double deltaTime = time2 - time1;
     float k = deltaTime > 0 ? 1 / deltaTime : 0;
@@ -788,13 +1208,13 @@
       }
     } else {
       // Handle event types not requiring looking ahead to the next event.
-      switch (event.getType()) {
+      switch (event->getType()) {
         case ParamEvent::SetValue:
         case ParamEvent::LinearRampToValue: {
           currentFrame = fillToEndFrame;
 
           // Simply stay at a constant value.
-          value = event.value();
+          value = event->value();
 
           for (; writeIndex < fillToFrame; ++writeIndex)
             values[writeIndex] = value;
@@ -802,6 +1222,37 @@
           break;
         }
 
+        case ParamEvent::CancelValues: {
+          // If the previous event was a SetTarget or ExponentialRamp
+          // event, the current value is one sample behind.  Update
+          // the sample value by one sample, but only at the start of
+          // this CancelValues event.
+          if (event->hasDefaultCancelledValue()) {
+            value = event->value();
+          } else {
+            double cancelFrame = time1 * sampleRate;
+            if (i >= 1 && cancelFrame <= currentFrame &&
+                currentFrame < cancelFrame + 1) {
+              ParamEvent::Type lastEventType = m_events[i - 1]->getType();
+              if (lastEventType == ParamEvent::SetTarget) {
+                float target = m_events[i - 1]->value();
+                float timeConstant = m_events[i - 1]->timeConstant();
+                float discreteTimeConstant = static_cast<float>(
+                    AudioUtilities::discreteTimeConstantForSampleRate(
+                        timeConstant, controlRate));
+                value += (target - value) * discreteTimeConstant;
+              }
+            }
+          }
+
+          // Simply stay at the current value.
+          for (; writeIndex < fillToFrame; ++writeIndex)
+            values[writeIndex] = value;
+
+          currentFrame = fillToEndFrame;
+          break;
+        }
+
         case ParamEvent::ExponentialRampToValue: {
           currentFrame = fillToEndFrame;
 
@@ -809,8 +1260,8 @@
           // (because the start and end values have the same sign, and neither
           // is 0), use the actual end value.  If not, we have to propagate
           // whatever we have.
-          if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0))
-            value = event.value();
+          if (i >= 1 && ((m_events[i - 1]->value() * event->value()) > 0))
+            value = event->value();
 
           // Simply stay at a constant value from the last time.  We don't want
           // to use the value of the event in case value1 * value2 < 0.  In this
@@ -827,8 +1278,8 @@
           //   v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau))
           //
 
-          float target = event.value();
-          float timeConstant = event.timeConstant();
+          float target = event->value();
+          float timeConstant = event->timeConstant();
           float discreteTimeConstant = static_cast<float>(
               AudioUtilities::discreteTimeConstantForSampleRate(timeConstant,
                                                                 controlRate));
@@ -917,16 +1368,18 @@
         }
 
         case ParamEvent::SetValueCurve: {
-          Vector<float> curve = event.curve();
+          Vector<float> curve = event->curve();
           float* curveData = curve.data();
           unsigned numberOfCurvePoints = curve.size();
 
+          float curveEndValue = event->curveEndValue();
+
           // Curve events have duration, so don't just use next event time.
-          double duration = event.duration();
+          double duration = event->duration();
           // How much to step the curve index for each frame.  This is basically
           // the term (N - 1)/Td in the specification.
           double curvePointsPerFrame =
-              (numberOfCurvePoints - 1) / duration / sampleRate;
+              event->curvePointsPerSecond() / sampleRate;
 
           if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) {
             // Error condition - simply propagate previous value.
@@ -976,7 +1429,7 @@
           }
 
           // Set the default value in case fillToFrame is 0.
-          value = curveData[numberOfCurvePoints - 1];
+          value = curveEndValue;
 
           // Render the stretched curve data using linear interpolation.
           // Oversampled curve data can be provided if sharp discontinuities are
@@ -1079,11 +1532,12 @@
 
           // If there's any time left after the duration of this event and the
           // start of the next, then just propagate the last value of the
-          // curveData.
-          if (writeIndex < nextEventFillToFrame)
-            value = curveData[numberOfCurvePoints - 1];
-          for (; writeIndex < nextEventFillToFrame; ++writeIndex)
-            values[writeIndex] = value;
+          // curveData. Don't modify |value| unless there is time left.
+          if (writeIndex < nextEventFillToFrame) {
+            value = curveEndValue;
+            for (; writeIndex < nextEventFillToFrame; ++writeIndex)
+              values[writeIndex] = value;
+          }
 
           // Re-adjust current time
           currentFrame += nextEventFillToFrame;
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h
index eeb09099..7899745 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.h
@@ -64,6 +64,7 @@
                            double duration,
                            ExceptionState&);
   void cancelScheduledValues(double startTime, ExceptionState&);
+  void cancelValuesAndHoldAtTime(double cancelTime, ExceptionState&);
 
   // hasValue is set to true if a valid timeline value is returned.
   // otherwise defaultValue is returned.
@@ -105,27 +106,50 @@
       ExponentialRampToValue,
       SetTarget,
       SetValueCurve,
+      // For cancelValuesAndHold
+      CancelValues,
       LastType
     };
 
-    static ParamEvent createLinearRampEvent(float value,
-                                            double time,
-                                            float initialValue,
-                                            double callTime);
-    static ParamEvent createExponentialRampEvent(float value,
-                                                 double time,
-                                                 float initialValue,
-                                                 double callTime);
-    static ParamEvent createSetValueEvent(float value, double time);
-    static ParamEvent createSetTargetEvent(float value,
-                                           double time,
-                                           double timeConstant);
-    static ParamEvent createSetValueCurveEvent(const DOMFloat32Array* curve,
-                                               double time,
-                                               double duration);
+    static std::unique_ptr<ParamEvent> createLinearRampEvent(float value,
+                                                             double time,
+                                                             float initialValue,
+                                                             double callTime);
+    static std::unique_ptr<ParamEvent> createExponentialRampEvent(
+        float value,
+        double time,
+        float initialValue,
+        double callTime);
+    static std::unique_ptr<ParamEvent> createSetValueEvent(float value,
+                                                           double time);
+    static std::unique_ptr<ParamEvent>
+    createSetTargetEvent(float value, double time, double timeConstant);
+    static std::unique_ptr<ParamEvent> createSetValueCurveEvent(
+        const DOMFloat32Array* curve,
+        double time,
+        double duration);
+    static std::unique_ptr<ParamEvent> createCancelValuesEvent(
+        double time,
+        std::unique_ptr<ParamEvent> savedEvent);
+    // Needed for creating a saved event where we want to supply all
+    // the possible parameters because we're mostly copying an
+    // existing event.
+    static std::unique_ptr<ParamEvent> createGeneralEvent(
+        Type,
+        float value,
+        double time,
+        float initialValue,
+        double callTime,
+        double timeConstant,
+        double duration,
+        Vector<float>& curve,
+        double curvePointsPerSecond,
+        float curveEndValue,
+        std::unique_ptr<ParamEvent> savedEvent);
 
-    static bool eventPreceeds(const ParamEvent& a, const ParamEvent& b) {
-      return a.time() < b.time();
+    static bool eventPreceeds(const std::unique_ptr<ParamEvent>& a,
+                              const std::unique_ptr<ParamEvent>& b) {
+      return a->time() < b->time();
     }
 
     Type getType() const { return m_type; }
@@ -140,34 +164,104 @@
     bool needsTimeClampCheck() const { return m_needsTimeClampCheck; }
     void clearTimeClampCheck() { m_needsTimeClampCheck = false; }
 
+    double curvePointsPerSecond() const { return m_curvePointsPerSecond; }
+    float curveEndValue() const { return m_curveEndValue; }
+
+    // For CancelValues events. Not valid for any other event.
+    ParamEvent* savedEvent() const;
+    bool hasDefaultCancelledValue() const;
+    void setCancelledValue(float);
+
    private:
+    // General event
     ParamEvent(Type type,
                float value,
                double time,
+               float initialValue,
+               double callTime,
                double timeConstant,
                double duration,
+               Vector<float>& curve,
+               double curvePointsPerSecond,
+               float curveEndValue,
+               std::unique_ptr<ParamEvent> savedEvent);
+
+    // Create simplest event needing just a value and time, like
+    // setValueAtTime.
+    ParamEvent(Type, float value, double time);
+
+    // Create a linear or exponential ramp that requires an initial
+    // value and time in case there is no actual event that preceeds
+    // this event.
+    ParamEvent(Type,
+               float value,
+               double time,
+               float initialValue,
+               double callTime);
+
+    // Create an event needing a time constant (setTargetAtTime)
+    ParamEvent(Type, float value, double time, double timeConstant);
+
+    // Create a setValueCurve event
+    ParamEvent(Type,
+               double time,
+               double duration,
                const DOMFloat32Array* curve,
-               float initialValue = 0,
-               double callTime = 0);
+               double curvePointsPerSecond,
+               float curveEndValue);
+
+    // Create CancelValues event
+    ParamEvent(Type, double time, std::unique_ptr<ParamEvent> savedEvent);
 
     Type m_type;
+
+    // The value for the event.  The interpretation of this depends on
+    // the event type. Not used for SetValueCurve. For CancelValues,
+    // it is the end value to use when cancelling a LinearRampToValue
+    // or ExponentialRampToValue event.
     float m_value;
+
+    // The time for the event. The interpretation of this depends on
+    // the event type.
     double m_time;
-    // Only used for SetTarget events
-    double m_timeConstant;
-    // Only used for SetValueCurve events.
-    double m_duration;
-    Vector<float> m_curve;
+
     // Initial value and time to use for linear and exponential ramps that don't
     // have a preceding event.
     float m_initialValue;
     double m_callTime;
+
+    // Only used for SetTarget events
+    double m_timeConstant;
+
+    // The following items are only used for SetValueCurve events.
+    //
+    // The duration of the curve.
+    double m_duration;
+    // The array of curve points.
+    Vector<float> m_curve;
+    // The number of curve points per second. it is used to compute
+    // the curve index step when running the automation.
+    double m_curvePointsPerSecond;
+    // The default value to use at the end of the curve.  Normally
+    // it's the last entry in m_curve, but cancelling a SetValueCurve
+    // will set this to a new value.
+    float m_curveEndValue;
+
+    // For CancelValues. If CancelValues is in the middle of an event, this
+    // holds the event that is being cancelled, so that processing can
+    // continue as if the event still existed up until we reach the actual
+    // scheduled cancel time.
+    std::unique_ptr<ParamEvent> m_savedEvent;
+
     // True if the start time needs to be checked against current time
     // to implement clamping.
     bool m_needsTimeClampCheck;
+
+    // True if a default value has been assigned to the CancelValues event.
+    bool m_hasDefaultCancelledValue;
   };
 
-  void insertEvent(const ParamEvent&, ExceptionState&);
+  void insertEvent(std::unique_ptr<ParamEvent>, ExceptionState&);
   float valuesForFrameRangeImpl(size_t startFrame,
                                 size_t endFrame,
                                 float defaultValue,
@@ -178,7 +272,33 @@
 
   // Produce a nice string describing the event in human-readable form.
   String eventToString(const ParamEvent&);
-  Vector<ParamEvent> m_events;
+
+  // Automation functions that compute the vlaue of the specified
+  // automation at the specified time.
+  float linearRampAtTime(double t,
+                         float value1,
+                         double time1,
+                         float value2,
+                         double time2);
+  float exponentialRampAtTime(double t,
+                              float value1,
+                              double time1,
+                              float value2,
+                              double time2);
+  float targetValueAtTime(double t,
+                          float value1,
+                          double time1,
+                          float value2,
+                          float timeConstant);
+  float valueCurveAtTime(double t,
+                         double time1,
+                         double duration,
+                         const float* curveData,
+                         unsigned curveLength);
+
+  // Vector of all automation events for the AudioParam.  Access must
+  // be locked via m_eventsLock.
+  Vector<std::unique_ptr<ParamEvent>> m_events;
 
   mutable Mutex m_eventsLock;
 
diff --git a/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp b/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp
index d2d3641..f572535 100644
--- a/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebMixedContent.cpp
@@ -33,7 +33,7 @@
 namespace blink {
 
 // static
-WebMixedContent::ContextType WebMixedContent::contextTypeFromRequestContext(
+WebMixedContentContextType WebMixedContent::contextTypeFromRequestContext(
     WebURLRequest::RequestContext context,
     bool strictMixedContentCheckingForPlugin) {
   switch (context) {
@@ -42,13 +42,13 @@
     case WebURLRequest::RequestContextFavicon:
     case WebURLRequest::RequestContextImage:
     case WebURLRequest::RequestContextVideo:
-      return ContextType::OptionallyBlockable;
+      return WebMixedContentContextType::OptionallyBlockable;
 
     // Plugins! Oh how dearly we love plugin-loaded content!
     case WebURLRequest::RequestContextPlugin: {
       return strictMixedContentCheckingForPlugin
-                 ? ContextType::Blockable
-                 : ContextType::OptionallyBlockable;
+                 ? WebMixedContentContextType::Blockable
+                 : WebMixedContentContextType::OptionallyBlockable;
     }
 
     // "Blockable" mixed content
@@ -78,96 +78,19 @@
     case WebURLRequest::RequestContextWorker:
     case WebURLRequest::RequestContextXMLHttpRequest:
     case WebURLRequest::RequestContextXSLT:
-      return ContextType::Blockable;
+      return WebMixedContentContextType::Blockable;
 
     // FIXME: Contexts that we should block, but don't currently.
     // https://crbug.com/388650
     case WebURLRequest::RequestContextDownload:
     case WebURLRequest::RequestContextPrefetch:
-      return ContextType::ShouldBeBlockable;
+      return WebMixedContentContextType::ShouldBeBlockable;
 
     case WebURLRequest::RequestContextUnspecified:
       NOTREACHED();
   }
   NOTREACHED();
-  return ContextType::Blockable;
-}
-
-// static
-const char* WebMixedContent::requestContextName(
-    WebURLRequest::RequestContext context) {
-  switch (context) {
-    case WebURLRequest::RequestContextAudio:
-      return "audio file";
-    case WebURLRequest::RequestContextBeacon:
-      return "Beacon endpoint";
-    case WebURLRequest::RequestContextCSPReport:
-      return "Content Security Policy reporting endpoint";
-    case WebURLRequest::RequestContextDownload:
-      return "download";
-    case WebURLRequest::RequestContextEmbed:
-      return "plugin resource";
-    case WebURLRequest::RequestContextEventSource:
-      return "EventSource endpoint";
-    case WebURLRequest::RequestContextFavicon:
-      return "favicon";
-    case WebURLRequest::RequestContextFetch:
-      return "resource";
-    case WebURLRequest::RequestContextFont:
-      return "font";
-    case WebURLRequest::RequestContextForm:
-      return "form action";
-    case WebURLRequest::RequestContextFrame:
-      return "frame";
-    case WebURLRequest::RequestContextHyperlink:
-      return "resource";
-    case WebURLRequest::RequestContextIframe:
-      return "frame";
-    case WebURLRequest::RequestContextImage:
-      return "image";
-    case WebURLRequest::RequestContextImageSet:
-      return "image";
-    case WebURLRequest::RequestContextImport:
-      return "HTML Import";
-    case WebURLRequest::RequestContextInternal:
-      return "resource";
-    case WebURLRequest::RequestContextLocation:
-      return "resource";
-    case WebURLRequest::RequestContextManifest:
-      return "manifest";
-    case WebURLRequest::RequestContextObject:
-      return "plugin resource";
-    case WebURLRequest::RequestContextPing:
-      return "hyperlink auditing endpoint";
-    case WebURLRequest::RequestContextPlugin:
-      return "plugin data";
-    case WebURLRequest::RequestContextPrefetch:
-      return "prefetch resource";
-    case WebURLRequest::RequestContextScript:
-      return "script";
-    case WebURLRequest::RequestContextServiceWorker:
-      return "Service Worker script";
-    case WebURLRequest::RequestContextSharedWorker:
-      return "Shared Worker script";
-    case WebURLRequest::RequestContextStyle:
-      return "stylesheet";
-    case WebURLRequest::RequestContextSubresource:
-      return "resource";
-    case WebURLRequest::RequestContextTrack:
-      return "Text Track";
-    case WebURLRequest::RequestContextUnspecified:
-      return "resource";
-    case WebURLRequest::RequestContextVideo:
-      return "video";
-    case WebURLRequest::RequestContextWorker:
-      return "Worker script";
-    case WebURLRequest::RequestContextXMLHttpRequest:
-      return "XMLHttpRequest endpoint";
-    case WebURLRequest::RequestContextXSLT:
-      return "XSLT";
-  }
-  NOTREACHED();
-  return "resource";
+  return WebMixedContentContextType::Blockable;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.cpp b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
index 46d0b1d..64be67e 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.cpp
@@ -233,12 +233,9 @@
   return fontVerticalDataCache;
 }
 
-void FontCache::setFontManager(const sk_sp<SkFontMgr>& fontManager) {
+void FontCache::setFontManager(sk_sp<SkFontMgr> fontManager) {
   DCHECK(!s_staticFontManager);
-  s_staticFontManager = fontManager.get();
-  // Explicitly AddRef since we're going to hold on to the object for the life
-  // of the program.
-  s_staticFontManager->ref();
+  s_staticFontManager = fontManager.release();
 }
 
 PassRefPtr<OpenTypeVerticalData> FontCache::getVerticalData(
diff --git a/third_party/WebKit/Source/platform/fonts/FontCache.h b/third_party/WebKit/Source/platform/fonts/FontCache.h
index 1e0ff6a..8b5febdd8 100644
--- a/third_party/WebKit/Source/platform/fonts/FontCache.h
+++ b/third_party/WebKit/Source/platform/fonts/FontCache.h
@@ -114,7 +114,7 @@
   void invalidate();
 
   SkFontMgr* fontManager() { return m_fontManager.get(); }
-  static void setFontManager(const sk_sp<SkFontMgr>&);
+  static void setFontManager(sk_sp<SkFontMgr>);
 
 #if !OS(MACOSX)
   static const AtomicString& systemFontFamily();
@@ -246,6 +246,7 @@
 
   sk_sp<SkFontMgr> m_fontManager;
 
+  // A leaky owning bare pointer.
   static SkFontMgr* s_staticFontManager;
 
 #if OS(WIN)
diff --git a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
index 4b51489..a96b8ba 100644
--- a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
+++ b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -34,14 +34,8 @@
 
 namespace blink {
 
-FontCache::FontCache() : m_purgePreventCount(0) {
-  if (s_staticFontManager) {
-    adopted(s_staticFontManager);
-    m_fontManager = sk_ref_sp(s_staticFontManager);
-  } else {
-    m_fontManager = nullptr;
-  }
-}
+FontCache::FontCache()
+    : m_purgePreventCount(0), m_fontManager(sk_ref_sp(s_staticFontManager)) {}
 
 static AtomicString& mutableSystemFontFamily() {
   DEFINE_STATIC_LOCAL(AtomicString, systemFontFamily, ());
diff --git a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
index ed5c3ec..8aebb5e 100644
--- a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
+++ b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
@@ -104,7 +104,7 @@
 FontCache::FontCache() : m_purgePreventCount(0) {
   m_fontManager = sk_ref_sp(s_staticFontManager);
   if (!m_fontManager)
-    m_fontManager.reset(SkFontMgr_New_DirectWrite());
+    m_fontManager = SkFontMgr_New_DirectWrite();
   ASSERT(m_fontManager.get());
 }
 
diff --git a/third_party/WebKit/Source/web/linux/WebFontRendering.cpp b/third_party/WebKit/Source/web/linux/WebFontRendering.cpp
index 398fc31..8a901e8 100644
--- a/third_party/WebKit/Source/web/linux/WebFontRendering.cpp
+++ b/third_party/WebKit/Source/web/linux/WebFontRendering.cpp
@@ -41,9 +41,8 @@
 namespace blink {
 
 // static
-void WebFontRendering::setSkiaFontManager(SkFontMgr* fontMgr) {
-  WTF::adopted(fontMgr);
-  FontCache::setFontManager(sk_ref_sp(fontMgr));
+void WebFontRendering::setSkiaFontManager(sk_sp<SkFontMgr> fontMgr) {
+  FontCache::setFontManager(std::move(fontMgr));
 }
 
 // static
diff --git a/third_party/WebKit/Source/web/win/WebFontRendering.cpp b/third_party/WebKit/Source/web/win/WebFontRendering.cpp
index 4d468805..56f73fd 100644
--- a/third_party/WebKit/Source/web/win/WebFontRendering.cpp
+++ b/third_party/WebKit/Source/web/win/WebFontRendering.cpp
@@ -9,9 +9,8 @@
 namespace blink {
 
 // static
-void WebFontRendering::setSkiaFontManager(SkFontMgr* fontMgr) {
-  WTF::adopted(fontMgr);
-  FontCache::setFontManager(sk_ref_sp(fontMgr));
+void WebFontRendering::setSkiaFontManager(sk_sp<SkFontMgr> fontMgr) {
+  FontCache::setFontManager(std::move(fontMgr));
 }
 
 // static
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 47e5c4a..18b84024 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -236,6 +236,7 @@
     "platform/WebMessagePortChannel.h",
     "platform/WebMessagePortChannelClient.h",
     "platform/WebMixedContent.h",
+    "platform/WebMixedContentContextType.h",
     "platform/WebMockClipboard.h",
     "platform/WebNativeScrollBehavior.h",
     "platform/WebNavigationHintType.h",
diff --git a/third_party/WebKit/public/platform/WebMixedContent.h b/third_party/WebKit/public/platform/WebMixedContent.h
index e263e5c2c..c8596eb 100644
--- a/third_party/WebKit/public/platform/WebMixedContent.h
+++ b/third_party/WebKit/public/platform/WebMixedContent.h
@@ -31,26 +31,17 @@
 #ifndef WebMixedContent_h
 #define WebMixedContent_h
 
+#include "public/platform/WebMixedContentContextType.h"
 #include "public/platform/WebURLRequest.h"
 
 namespace blink {
 
-// Types and helper functions related to mixed content checks.
+// Helper functions related to mixed content checks.
 class WebMixedContent {
  public:
-  enum class ContextType {
-    NotMixedContent,
-    Blockable,
-    OptionallyBlockable,
-    ShouldBeBlockable,
-  };
-
-  BLINK_PLATFORM_EXPORT static ContextType contextTypeFromRequestContext(
-      WebURLRequest::RequestContext,
-      bool strictMixedContentCheckingForPlugin);
-
-  BLINK_PLATFORM_EXPORT static const char* requestContextName(
-      WebURLRequest::RequestContext);
+  BLINK_PLATFORM_EXPORT static WebMixedContentContextType
+  contextTypeFromRequestContext(WebURLRequest::RequestContext,
+                                bool strictMixedContentCheckingForPlugin);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebMixedContentContextType.h b/third_party/WebKit/public/platform/WebMixedContentContextType.h
new file mode 100644
index 0000000..604526c
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebMixedContentContextType.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebMixedContentContextType_h
+#define WebMixedContentContextType_h
+
+namespace blink {
+
+// Types and helper functions related to mixed content checks.
+enum class WebMixedContentContextType {
+  NotMixedContent,
+  Blockable,
+  OptionallyBlockable,
+  ShouldBeBlockable,
+  Last = ShouldBeBlockable
+};
+
+}  // namespace blink
+
+#endif  // WebMixedContentContextType_h
diff --git a/third_party/WebKit/public/web/linux/WebFontRendering.h b/third_party/WebKit/public/web/linux/WebFontRendering.h
index d52b018..f3097e68 100644
--- a/third_party/WebKit/public/web/linux/WebFontRendering.h
+++ b/third_party/WebKit/public/web/linux/WebFontRendering.h
@@ -42,7 +42,7 @@
  public:
   // Set global font renderering preferences.
 
-  BLINK_EXPORT static void setSkiaFontManager(SkFontMgr*);
+  BLINK_EXPORT static void setSkiaFontManager(sk_sp<SkFontMgr>);
   BLINK_EXPORT static void setHinting(SkPaint::Hinting);
   BLINK_EXPORT static void setAutoHint(bool);
   BLINK_EXPORT static void setUseBitmaps(bool);
diff --git a/third_party/WebKit/public/web/win/WebFontRendering.h b/third_party/WebKit/public/web/win/WebFontRendering.h
index a4933e1..cdb39bda 100644
--- a/third_party/WebKit/public/web/win/WebFontRendering.h
+++ b/third_party/WebKit/public/web/win/WebFontRendering.h
@@ -6,6 +6,7 @@
 #define WebFontRendering_h
 
 #include "public/platform/WebCommon.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 
 class SkFontMgr;
 class SkTypeface;
@@ -14,7 +15,7 @@
 
 class WebFontRendering {
  public:
-  BLINK_EXPORT static void setSkiaFontManager(SkFontMgr*);
+  BLINK_EXPORT static void setSkiaFontManager(sk_sp<SkFontMgr>);
   BLINK_EXPORT static void setDeviceScaleFactor(float);
   BLINK_EXPORT static void addSideloadedFontForTesting(SkTypeface*);
   BLINK_EXPORT static void setMenuFontMetrics(const wchar_t* familyName,
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 2a8d12b5..7fcfd85 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Tuesday December 20 2016
+Date: Monday January 09 2017
 Branch: master
-Commit: f27276f44fa3a66c07a2a92a381f31aaf8371add
+Commit: 5b1a8ca5e846f838062becaec9ed6b5ecef306e5
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni
index d57d692..664a0fd 100644
--- a/third_party/libvpx/libvpx_srcs.gni
+++ b/third_party/libvpx/libvpx_srcs.gni
@@ -2306,7 +2306,6 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/hadamard_neon.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_1_add_neon.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_add_neon.c",
-  "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct16x16_neon.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_135_add_neon.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_1_add_neon.c",
   "//third_party/libvpx/source/libvpx/vpx_dsp/arm/idct32x32_34_add_neon.c",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
index a1696e9..c9d867d 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@
 #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon
 
 void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c
+void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon
 
 void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c
+void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon
 
 void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
 void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
index a1696e9..c9d867d 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@
 #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon
 
 void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c
+void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon
 
 void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c
+void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon
 
 void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
 void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
index 5bfb6e77..2712530 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@
 RTCD_EXTERN void (*vpx_lpf_vertical_8_dual)(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
 
 void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c
+void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+RTCD_EXTERN void (*vpx_mbpost_proc_across_ip)(unsigned char *dst, int pitch, int rows, int cols,int flimit);
 
 void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c
+void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+RTCD_EXTERN void (*vpx_mbpost_proc_down)(unsigned char *dst, int pitch, int rows, int cols,int flimit);
 
 void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
 void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
@@ -988,6 +990,10 @@
     if (flags & HAS_NEON) vpx_lpf_vertical_8 = vpx_lpf_vertical_8_neon;
     vpx_lpf_vertical_8_dual = vpx_lpf_vertical_8_dual_c;
     if (flags & HAS_NEON) vpx_lpf_vertical_8_dual = vpx_lpf_vertical_8_dual_neon;
+    vpx_mbpost_proc_across_ip = vpx_mbpost_proc_across_ip_c;
+    if (flags & HAS_NEON) vpx_mbpost_proc_across_ip = vpx_mbpost_proc_across_ip_neon;
+    vpx_mbpost_proc_down = vpx_mbpost_proc_down_c;
+    if (flags & HAS_NEON) vpx_mbpost_proc_down = vpx_mbpost_proc_down_neon;
     vpx_minmax_8x8 = vpx_minmax_8x8_c;
     if (flags & HAS_NEON) vpx_minmax_8x8 = vpx_minmax_8x8_neon;
     vpx_mse16x16 = vpx_mse16x16_c;
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
index a1696e9..c9d867d 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@
 #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon
 
 void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c
+void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon
 
 void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c
+void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon
 
 void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
 void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
index a1696e9..c9d867d 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -427,10 +427,12 @@
 #define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon
 
 void vpx_mbpost_proc_across_ip_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_c
+void vpx_mbpost_proc_across_ip_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_across_ip vpx_mbpost_proc_across_ip_neon
 
 void vpx_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols,int flimit);
-#define vpx_mbpost_proc_down vpx_mbpost_proc_down_c
+void vpx_mbpost_proc_down_neon(unsigned char *dst, int pitch, int rows, int cols,int flimit);
+#define vpx_mbpost_proc_down vpx_mbpost_proc_down_neon
 
 void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
 void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index 2617545..07f046e 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  6
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "843-gf27276f"
+#define VERSION_EXTRA  "903-g5b1a8ca5e"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.6.0-843-gf27276f"
-#define VERSION_STRING      " v1.6.0-843-gf27276f"
+#define VERSION_STRING_NOSP "v1.6.0-903-g5b1a8ca5e"
+#define VERSION_STRING      " v1.6.0-903-g5b1a8ca5e"
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index d1882a5..2ce8f3b 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -17,7 +17,6 @@
 {% endblock %} -->
 <classpath>
     <classpathentry kind="src" path="android_webview/glue/java/src"/>
-    <classpathentry kind="src" path="android_webview/java/generated_src"/>
     <classpathentry kind="src" path="android_webview/java/src"/>
     <classpathentry kind="src" path="android_webview/javatests/src"/>
     <classpathentry kind="src" path="android_webview/test/shell/src"/>
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
index bf1d77d..2d6713c 100644
--- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
+++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -431,15 +431,39 @@
       return false;
   }
 
-  // If the expression is a template input then its coming at compile time so
-  // we consider it const. And we can't check isEvaluatable() in this case as
-  // it will do bad things/crash.
-  if (expr->isInstantiationDependent())
-    return true;
+  // If the expression depends on template input, we can not call
+  // isEvaluatable() on it as it will do bad things/crash.
+  if (!expr->isInstantiationDependent()) {
+    // If the expression can be evaluated at compile time, then it should have a
+    // kFoo style name. Otherwise, not.
+    return expr->isEvaluatable(context);
+  }
 
-  // If the expression can be evaluated at compile time, then it should have a
-  // kFoo style name. Otherwise, not.
-  return expr->isEvaluatable(context);
+  // We do our best to figure out special cases as we come across them here, for
+  // template dependent situations. Some cases in code are only considered
+  // instantiation dependent for some template instantiations! Which is
+  // terrible! So most importantly we try to match isEvaluatable in those cases.
+  switch (expr->getStmtClass()) {
+    case clang::Stmt::CXXThisExprClass:
+      return false;
+    case clang::Stmt::DeclRefExprClass: {
+      auto* declref = clang::dyn_cast<clang::DeclRefExpr>(expr);
+      auto* decl = declref->getDecl();
+      if (auto* vardecl = clang::dyn_cast<clang::VarDecl>(decl)) {
+        if (auto* initializer = vardecl->getInit())
+          return CanBeEvaluatedAtCompileTime(initializer, context);
+        return false;
+      }
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  // Otherwise, we consider depending on template parameters to not interfere
+  // with being const.. with exceptions hopefully covered above.
+  return true;
 }
 
 bool IsProbablyConst(const clang::VarDecl& decl,
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc
index dc46c19a3a..5c9103d9 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc
@@ -64,6 +64,8 @@
   const bool kComplexConst = number || (number + 1);
   // A complex statement with a non-const thing is not const.
   const bool complex_not_const = number || (g_global_number + 1);
+  // A const built from other consts is a const.
+  const bool kConstFromAConst = kComplexConst || number;
 }
 
 template <int number, typename... T>
@@ -76,6 +78,40 @@
   const int kIsAConstToo = number;
 }
 
+namespace test_member_in_template {
+
+template <typename T>
+class HasAMember {
+ public:
+  HasAMember() {}
+  HasAMember(const T&) {}
+
+  void UsesMember() { const int not_const = i_; }
+  void AlsoUsesMember();
+
+ private:
+  int i_;
+};
+
+template <typename T>
+void HasAMember<T>::AlsoUsesMember() {
+  const int not_const = i_;
+}
+
+template <typename T>
+static void BasedOnSubType(const HasAMember<T>& t) {
+  const HasAMember<T> problematic_not_const(t);
+}
+
+void Run() {
+  HasAMember<int>().UsesMember();
+
+  BasedOnSubType<int>(HasAMember<int>());
+  enum E { A };
+  BasedOnSubType<E>(HasAMember<E>());
+}
+}
+
 namespace test_template_arg_is_function {
 
 void F(int x) {}
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc
index 754e755d..47aef5d8 100644
--- a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc
+++ b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc
@@ -63,6 +63,8 @@
   const bool complexConst = number || (number + 1);
   // A complex statement with a non-const thing is not const.
   const bool complexNotConst = number || (g_globalNumber + 1);
+  // A const built from other consts is a const.
+  const bool constFromAConst = complexConst || number;
 }
 
 template <int number, typename... T>
@@ -75,6 +77,40 @@
   const int isAConstToo = number;
 }
 
+namespace test_member_in_template {
+
+template <typename T>
+class HasAMember {
+ public:
+  HasAMember() {}
+  HasAMember(const T&) {}
+
+  void usesMember() { const int notConst = m_i; }
+  void alsoUsesMember();
+
+ private:
+  int m_i;
+};
+
+template <typename T>
+void HasAMember<T>::alsoUsesMember() {
+  const int notConst = m_i;
+}
+
+template <typename T>
+static void basedOnSubType(const HasAMember<T>& t) {
+  const HasAMember<T> problematicNotConst(t);
+}
+
+void Run() {
+  HasAMember<int>().usesMember();
+
+  basedOnSubType<int>(HasAMember<int>());
+  enum E { A };
+  basedOnSubType<E>(HasAMember<E>());
+}
+}
+
 namespace test_template_arg_is_function {
 
 void f(int x) {}
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 7457a91..c231521 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -399,8 +399,7 @@
 
   need_gold_plugin = 'LLVM_DOWNLOAD_GOLD_PLUGIN' in os.environ or (
       sys.platform.startswith('linux') and
-      'buildtype=Official' in os.environ.get('GYP_DEFINES', '') and
-      'branding=Chrome' in os.environ.get('GYP_DEFINES', ''))
+      'buildtype=Official' in os.environ.get('GYP_DEFINES', ''))
 
   if ReadStampFile() == PACKAGE_VERSION and not args.force_local_build:
     print 'Clang is already up to date.'
diff --git a/tools/perf/generate_perf_json.py b/tools/perf/generate_perf_json.py
index 08bb666..7819421 100755
--- a/tools/perf/generate_perf_json.py
+++ b/tools/perf/generate_perf_json.py
@@ -328,7 +328,11 @@
        'device_ids': [
            'build164-m1', 'build165-m1',
            'build166-m1', 'build167-m1', 'build168-m1'
-          ]
+          ],
+       'perf_tests': [
+         ('angle_perftests', 2),
+         ('load_library_perf_tests', 2),
+         ('performance_browser_tests', 2)]
       }
     ])
   waterfall = add_tester(
diff --git a/tools/resource_prefetch_predictor/prefetch_predictor_tool.py b/tools/resource_prefetch_predictor/prefetch_predictor_tool.py
index 1160f5f..9680c65 100755
--- a/tools/resource_prefetch_predictor/prefetch_predictor_tool.py
+++ b/tools/resource_prefetch_predictor/prefetch_predictor_tool.py
@@ -13,6 +13,7 @@
 
 import argparse
 import sqlite3
+import os
 
 from resource_prefetch_predictor_pb2 import (PrefetchData, ResourceData)
 
@@ -77,6 +78,15 @@
         continue
       self._PrettyPrintResource(resource)
 
+# The version of python sqlite3 library we have in Ubuntu 14.04 LTS doesn't
+# support views but command line util does.
+# TODO(alexilin): get rid of this when python sqlite3 adds view support.
+def CreateCompatibleDatabaseCopy(filename):
+  import tempfile, shutil, subprocess
+  _, tmpfile = tempfile.mkstemp()
+  shutil.copy2(filename, tmpfile)
+  subprocess.call(['sqlite3', tmpfile, 'DROP VIEW MmapStatus'])
+  return tmpfile
 
 def DatabaseStats(filename, domain):
   connection = sqlite3.connect(filename)
@@ -94,7 +104,12 @@
                       help='Path to the database')
   parser.add_argument('-d', dest='domain', default=None, help='Domain')
   args = parser.parse_args()
-  DatabaseStats(args.database_filename, args.domain)
+  try:
+    database_copy = CreateCompatibleDatabaseCopy(args.database_filename)
+    DatabaseStats(database_copy, args.domain)
+  finally:
+    if os.path.exists(database_copy):
+      os.remove(database_copy)
 
 
 if __name__ == '__main__':
diff --git a/ui/events/keycodes/keyboard_code_conversion_android.cc b/ui/events/keycodes/keyboard_code_conversion_android.cc
index f20e0737..5baef199 100644
--- a/ui/events/keycodes/keyboard_code_conversion_android.cc
+++ b/ui/events/keycodes/keyboard_code_conversion_android.cc
@@ -334,13 +334,13 @@
     case AKEYCODE_TV_INPUT_HDMI_4:
       return DomKey::TV_INPUT_HDMI4;
     case AKEYCODE_TV_INPUT_COMPOSITE_1:
-      return DomKey::TV_INPUT_COMPONENT1;
-    case AKEYCODE_TV_INPUT_COMPOSITE_2:
-      return DomKey::TV_INPUT_COMPONENT2;
-    case AKEYCODE_TV_INPUT_COMPONENT_1:
       return DomKey::TV_INPUT_COMPOSITE1;
-    case AKEYCODE_TV_INPUT_COMPONENT_2:
+    case AKEYCODE_TV_INPUT_COMPOSITE_2:
       return DomKey::TV_INPUT_COMPOSITE2;
+    case AKEYCODE_TV_INPUT_COMPONENT_1:
+      return DomKey::TV_INPUT_COMPONENT1;
+    case AKEYCODE_TV_INPUT_COMPONENT_2:
+      return DomKey::TV_INPUT_COMPONENT2;
     case AKEYCODE_TV_INPUT_VGA_1:
       return DomKey::TV_INPUT_VGA1;
     case AKEYCODE_TV_AUDIO_DESCRIPTION:
diff --git a/ui/gfx/vector_icons/BUILD.gn b/ui/gfx/vector_icons/BUILD.gn
index d2ce06e..9751ed4 100644
--- a/ui/gfx/vector_icons/BUILD.gn
+++ b/ui/gfx/vector_icons/BUILD.gn
@@ -122,20 +122,6 @@
     "warning.icon",
     "warning_badge.icon",
     "web.icon",
-    "window_control_back.1x.icon",
-    "window_control_back.icon",
-    "window_control_close.1x.icon",
-    "window_control_close.icon",
-    "window_control_left_snapped.1x.icon",
-    "window_control_left_snapped.icon",
-    "window_control_maximize.1x.icon",
-    "window_control_maximize.icon",
-    "window_control_minimize.1x.icon",
-    "window_control_minimize.icon",
-    "window_control_restore.1x.icon",
-    "window_control_restore.icon",
-    "window_control_right_snapped.1x.icon",
-    "window_control_right_snapped.icon",
     "zoom_minus.icon",
     "zoom_plus.icon",
     "${branding_path_component}/product.icon",
diff --git a/ui/gfx/win/direct_write.cc b/ui/gfx/win/direct_write.cc
index bf30f64c..72bb0e62 100644
--- a/ui/gfx/win/direct_write.cc
+++ b/ui/gfx/win/direct_write.cc
@@ -10,6 +10,7 @@
 #include "base/win/scoped_comptr.h"
 #include "base/win/windows_version.h"
 #include "skia/ext/fontmgr_default_win.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
 #include "third_party/skia/include/ports/SkTypeface_win.h"
 #include "ui/gfx/platform_font_win.h"
 #include "ui/gfx/switches.h"
@@ -52,10 +53,11 @@
   // factory. The GetSystemFontCollection method in the IDWriteFactory
   // interface fails with E_INVALIDARG on certain Windows 7 gold versions
   // (6.1.7600.*). We should just use GDI in these cases.
-  SkFontMgr* direct_write_font_mgr = SkFontMgr_New_DirectWrite(factory.get());
+  sk_sp<SkFontMgr> direct_write_font_mgr =
+      SkFontMgr_New_DirectWrite(factory.get());
   if (!direct_write_font_mgr)
     return;
-  SetDefaultSkiaFactory(direct_write_font_mgr);
+  SetDefaultSkiaFactory(std::move(direct_write_font_mgr));
   gfx::PlatformFontWin::SetDirectWriteFactory(factory.get());
 }
 
diff --git a/ui/message_center/views/message_center_button_bar.cc b/ui/message_center/views/message_center_button_bar.cc
index fb86d93..5f89a6a 100644
--- a/ui/message_center/views/message_center_button_bar.cc
+++ b/ui/message_center/views/message_center_button_bar.cc
@@ -68,9 +68,9 @@
     int text_id)
     : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
   ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
-  SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
-  SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
-  SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
+  SetImage(STATE_NORMAL, *resource_bundle.GetImageSkiaNamed(normal_id));
+  SetImage(STATE_HOVERED, *resource_bundle.GetImageSkiaNamed(hover_id));
+  SetImage(STATE_PRESSED, *resource_bundle.GetImageSkiaNamed(pressed_id));
   SetImageAlignment(views::ImageButton::ALIGN_CENTER,
                     views::ImageButton::ALIGN_MIDDLE);
   if (text_id)
@@ -159,7 +159,7 @@
                                    IDS_MESSAGE_CENTER_CLEAR_ALL);
   close_all_button_->SetImage(
       views::Button::STATE_DISABLED,
-      resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
+      *resource_bundle.GetImageSkiaNamed(IDR_NOTIFICATION_CLEAR_ALL_DISABLED));
   button_container_->AddChildView(close_all_button_);
 
   settings_button_ =
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc
index e875612c..fd2151e2a 100644
--- a/ui/views/controls/button/image_button.cc
+++ b/ui/views/controls/button/image_button.cc
@@ -48,10 +48,14 @@
 }
 
 void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia* image) {
+  SetImage(for_state, image ? *image : gfx::ImageSkia());
+}
+
+void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
   if (for_state == STATE_HOVERED)
-    set_animate_on_state_change(image != nullptr);
+    set_animate_on_state_change(!image.isNull());
   const gfx::Size old_preferred_size = GetPreferredSize();
-  images_[for_state] = image ? *image : gfx::ImageSkia();
+  images_[for_state] = image;
 
   if (old_preferred_size != GetPreferredSize())
     PreferredSizeChanged();
@@ -250,11 +254,11 @@
 }
 
 void ToggleImageButton::SetImage(ButtonState image_state,
-                                 const gfx::ImageSkia* image) {
+                                 const gfx::ImageSkia& image) {
   if (toggled_) {
-    alternate_images_[image_state] = image ? *image : gfx::ImageSkia();
+    alternate_images_[image_state] = image;
   } else {
-    images_[image_state] = image ? *image : gfx::ImageSkia();
+    images_[image_state] = image;
     if (state() == image_state)
       SchedulePaint();
   }
diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h
index 94f70ba8..eba2a835 100644
--- a/ui/views/controls/button/image_button.h
+++ b/ui/views/controls/button/image_button.h
@@ -44,7 +44,12 @@
   virtual const gfx::ImageSkia& GetImage(ButtonState state) const;
 
   // Set the image the button should use for the provided state.
-  virtual void SetImage(ButtonState state, const gfx::ImageSkia* image);
+  void SetImage(ButtonState state, const gfx::ImageSkia* image);
+
+  // As above, but takes a const ref. TODO(estade): all callers should be
+  // updated to use this version, and then the implementations can be
+  // consolidated.
+  virtual void SetImage(ButtonState state, const gfx::ImageSkia& image);
 
   // Set the background details.
   void SetBackground(SkColor color,
@@ -142,7 +147,7 @@
 
   // Overridden from ImageButton:
   const gfx::ImageSkia& GetImage(ButtonState state) const override;
-  void SetImage(ButtonState state, const gfx::ImageSkia* image) override;
+  void SetImage(ButtonState state, const gfx::ImageSkia& image) override;
 
   // Overridden from View:
   bool GetTooltipText(const gfx::Point& p,